HTTPS와 TLS의 실제 동작 원리: 핸드셰이크 완벽 해설
URL을 입력하고 Enter를 누르면 자물쇠 아이콘이 나타납니다. 하지만 브라우저와 서버 사이에서 연결을 안전하게 만들기 위해 실제로 무슨 일이 일어날까요? 많은 개발자가 HTTPS를 블랙박스로 취급합니다—인증서 오류나 성능 문제 같은 것이 터지기 전까지는요. 이 글은 HTTPS 뒤에 있는 프로토콜인 TLS의 베일을 벗기고 핸드셰이크를 알기 쉽게 설명합니다.
HTTPS의 진짜 정체
HTTPS는 간단히 말해 TLS(Transport Layer Security) 위에 HTTP를 얹은 것입니다. TLS는 세 가지 보장을 제공합니다:
- 기밀성 – 데이터가 암호화되어 도청자가 읽을 수 없습니다.
- 무결성 – 전송 중 데이터가 변조되면 감지됩니다.
- 인증 – 가짜가 아닌 실제 서버와 통신하고 있음을 보장합니다.
TLS가 없으면 HTTP는 모든 것을 평문으로 전송합니다: 비밀번호, 쿠키, 폼 데이터가 네트워크 경로상의 누구에게나 노출됩니다.
쉬운 말로 풀어보는 TLS 핸드셰이크
핸드셰이크는 애플리케이션 데이터가 전송되기 전에 이루어지는 협상입니다. 목표는 암호화 알고리즘 합의, 서버 신원 확인, 공유 비밀 키 설정입니다. 현대 표준인 TLS 1.3의 흐름은 다음과 같습니다:
- Client Hello – 브라우저가 지원하는 암호화 스위트 목록, 랜덤 값, 키 공유(키 교환용)를 보냅니다.
- Server Hello – 서버가 암호화 스위트를 선택하고, 자체 랜덤 값과 키 공유를 보내며, 인증서 체인을 제공합니다.
- 인증서 검증 – 브라우저가 신뢰할 수 있는 루트 CA에 대해 인증서를 확인하고, 도메인 이름을 검증하며, 만료 여부를 확인합니다.
- 키 유도 – 양측이 키 교환(일반적으로 ECDHE)을 통해 동일한 공유 비밀을 계산합니다. 세션 키가 유도됩니다.
- Finished – 양측이 핸드셰이크 트랜스크립트에 대한 MAC을 보내 변조가 없음을 확인합니다.
그 후 암호화된 애플리케이션 데이터가 흐릅니다. TLS 1.3에서 핸드셰이크는 1회 왕복(1-RTT)이 걸리며, 재개(resumption) 시 0-RTT를 달성할 수 있습니다.
TLS 1.2 vs TLS 1.3
TLS 1.2는 2회 왕복이 필요했고 더 약한 알고리즘을 지원했습니다. TLS 1.3은 구식 암호를 제거하고 핸드셰이크를 단순화했으며 핸드셰이크 자체를 더 많이 암호화합니다. 항상 TLS 1.3을 선호하세요; 대부분의 현대 서버와 브라우저가 이를 지원합니다.
인증서: 신뢰의 닻
인증서는 공개 키를 도메인 이름에 바인딩하고 인증 기관(CA)이 서명합니다. 브라우저는 신뢰할 수 있는 루트 CA 저장소를 내장하고 있습니다. 검증 중에 브라우저는 서버 인증서에서 신뢰할 수 있는 루트까지 체인을 구성합니다.
일반적인 인증서 유형:
- DV (Domain Validation) – 도메인 제어를 증명; 빠르고 무료 (예: Let's Encrypt).
- OV (Organization Validation) – 검증된 회사 세부 정보 포함.
- EV (Extended Validation) – 더 엄격한 신원 확인; 대부분의 브라우저에서 더 이상 녹색 표시줄을 표시하지 않음.
인증서는 만료됩니다. Certbot과 같은 ACME 클라이언트로 갱신을 자동화하여 중단을 방지하세요.
키 교환과 완전 순방향 비밀성
현대 TLS는 임시 키 교환(ECDHE)을 사용합니다. 각 세션마다 새로운 키 쌍을 생성하므로, 나중에 서버의 개인 키가 손상되더라도 과거 세션은 복호화할 수 없습니다. 이 속성을 순방향 비밀성이라고 합니다. 이 보호 기능이 없는 정적 RSA 키 교환은 피하세요.
흔한 HTTPS 함정과 피하는 방법
- 혼합 콘텐츠 – HTTPS 페이지에서 HTTP 리소스를 로드하면 브라우저 경고가 발생합니다. 상대 URL을 사용하거나 HTTPS로 업데이트하세요.
- 만료된 인증서 – 모니터링과 자동 갱신을 설정하세요.
- 약한 암호화 스위트 – TLS 1.0/1.1 및 RC4/3DES를 비활성화하세요. SSL Labs 같은 도구로 테스트하세요.
- HSTS 누락 –
Strict-Transport-Security헤더를 추가하여 HTTPS를 강제하세요.
TLS 문제 디버깅
핸드셰이크가 실패하면 openssl s_client를 사용하여 연결을 검사하세요:
openssl s_client -connect example.com:443 -servername example.com
이 명령은 인증서 체인, 협상된 프로토콜, 암호를 보여줍니다. 브라우저별 오류의 경우 DevTools의 보안 패널을 확인하세요.
FAQ
HTTPS와 TLS는 같은 건가요?
HTTPS는 TLS 위의 HTTP입니다. TLS는 암호화 프로토콜이고, HTTPS는 HTTP 애플리케이션 프로토콜의 보안 버전입니다.
각 하위 도메인마다 별도 인증서가 필요한가요?
반드시 그렇지는 않습니다. 와일드카드 인증서는 모든 1차 하위 도메인을 포함하며, 다중 도메인(SAN) 인증서는 여러 이름을 나열할 수 있습니다.
TLS 1.3은 어떻게 성능을 향상시키나요?
TLS 1.3은 핸드셰이크를 1회 왕복(재개 시 0회)으로 줄이고 암호 협상을 단순화하여 지연 시간을 낮춥니다.
자신의 사이트 보안을 점검할 준비가 되셨나요? Nginx 로그 분석기를 사용하여 로그에서 의심스러운 TLS 오류와 핸드셰이크 실패를 찾아보세요.