HTTPS와 SSL/TLS 인증서 쉽게 이해하기
HTTPS가 왜 필요한지, SSL과 TLS는 뭐가 다른지, 인증서는 어떻게 작동하는지. 비전공자도 이해할 수 있게 정리한 HTTPS 가이드.

브라우저 주소창에 자물쇠 아이콘 보이는 거. 그게 HTTPS다. 요즘은 거의 모든 사이트가 HTTPS를 쓰고 있어서 당연하게 느껴지지만, 이게 정확히 뭘 하는 건지 아는 사람은 의외로 적다.
HTTP의 문제
HTTP는 데이터를 **평문(plain text)**으로 주고받는다. 내가 로그인 폼에 비밀번호를 입력하고 전송을 누르면, 그 비밀번호가 텍스트 그대로 네트워크를 타고 서버까지 날아간다.
이게 왜 문제냐면, 네트워크 경로 어딘가에서 누군가가 패킷을 엿볼 수 있기 때문이다. 카페 와이파이 같은 공용 네트워크에서는 특히 위험하다. 공항이나 호텔 와이파이도 마찬가지. 같은 네트워크에 연결된 사람이 패킷 캡처 도구를 돌리면 다른 사람의 HTTP 트래픽을 그대로 볼 수 있다. 아이디, 비밀번호, 카드 번호... 전부.
HTTPS는 이 문제를 해결한다. 데이터를 암호화해서 전송하니까, 중간에 누가 패킷을 잡아도 내용을 읽을 수 없다.
SSL, TLS — 이름이 왜 두 개야
자주 혼동되는 부분인데, 짧게 정리하면 이렇다.
**SSL(Secure Sockets Layer)**은 1990년대에 넷스케이프가 만든 암호화 프로토콜이다. SSL 3.0까지 나왔는데, 보안 취약점이 발견되면서 더 이상 사용하지 않는다.
**TLS(Transport Layer Security)**는 SSL의 후속 프로토콜이다. SSL 3.0을 기반으로 만들어졌고, 현재 TLS 1.3까지 나와있다. 2026년 기준으로 실제 사용되는 건 TLS 1.2와 TLS 1.3이다.
그러니까 기술적으로 정확하게 말하면 "TLS 인증서"가 맞는데, 업계에서는 관성적으로 "SSL 인증서"라고 부르는 경우가 많다. "SSL/TLS 인증서"라고 하면 무난하다. 어쨌든 핵심은 SSL이라는 단어가 나와도 실제로는 TLS가 동작하고 있다는 거다.
HTTPS 연결이 만들어지는 과정
브라우저에서 https://example.com에 접속하면 뒤에서 이런 일이 일어난다. 이걸 TLS 핸드셰이크라고 한다.
1단계 — 브라우저가 서버에 "안녕" 한다 (Client Hello)
브라우저가 서버에 연결을 요청하면서, 자기가 지원하는 TLS 버전과 암호화 방식 목록(cipher suite)을 보낸다.
2단계 — 서버가 인증서를 보여준다 (Server Hello)
서버가 TLS 버전과 암호화 방식을 선택하고, 자기 인증서를 전송한다. 인증서에는 서버의 공개키와 "이 서버가 진짜 example.com이 맞다"는 인증 기관(CA)의 서명이 들어있다.
3단계 — 브라우저가 인증서를 검증한다
브라우저는 인증서가 신뢰할 수 있는 CA에서 발급된 건지, 유효기간이 지나지 않았는지, 도메인이 일치하는지 확인한다. 이 중 하나라도 문제가 있으면 "이 연결은 안전하지 않습니다" 경고가 뜬다.
4단계 — 암호화 키를 교환한다
검증이 통과하면, 양쪽이 이 세션에서 사용할 대칭키를 안전하게 만들어낸다. TLS 1.3에서는 이 과정에 ECDHE 같은 키 교환 알고리즘을 쓴다.
5단계 — 암호화 통신 시작
이후 모든 데이터는 대칭키로 암호화되어 오간다.
이 전체 과정이 밀리초 단위로 일어난다. TLS 1.3에서는 핸드셰이크가 한 번의 왕복(1-RTT)으로 완료되고, 이전에 연결했던 서버라면 0-RTT로 바로 데이터를 보낼 수도 있다.
인증서, 대체 누가 발급하는 건가
인증서는 **인증 기관(CA, Certificate Authority)**이 발급한다. CA는 "이 인증서의 주인이 정말로 이 도메인의 소유자가 맞다"를 보증해주는 역할이다. 브라우저에는 신뢰할 수 있는 CA 목록이 내장되어 있고, 그 CA가 서명한 인증서만 유효한 것으로 인정한다.
인증서 종류는 세 가지:
- DV (Domain Validation) — 도메인 소유권만 확인. 가장 간단하고 빠르다. 개인 사이트, 블로그에 충분
- OV (Organization Validation) — 도메인 + 조직 실체 확인. 기업 사이트에 주로 사용
- EV (Extended Validation) — 엄격한 검증 절차. 예전에는 주소창이 초록색으로 바뀌었는데, 요즘 브라우저는 EV도 일반 자물쇠로 표시한다. 실질적 가치가 좀 떨어졌다는 평가
Let's Encrypt — 무료 인증서의 혁명
2015년 이전에는 SSL 인증서가 유료였다. 연간 수만 원에서 수십만 원. 개인 블로그에 HTTPS를 붙이기엔 부담스러운 비용이었다.
Let's Encrypt가 이걸 바꿨다. 무료 DV 인증서를 자동으로 발급해주는 비영리 CA다. Certbot 같은 도구를 쓰면 인증서 발급, 설치, 갱신까지 자동화할 수 있다. 90일마다 갱신해야 하지만, 자동화하면 신경 쓸 일이 없다.
Vercel, Netlify, Cloudflare 같은 호스팅/CDN 서비스는 아예 HTTPS를 기본 제공한다. 도메인만 연결하면 인증서가 자동으로 발급되고 갱신된다. 2026년 기준으로 HTTPS를 위해 별도로 인증서를 구매해야 하는 상황은 거의 없어졌다.
HTTPS를 안 쓰면 생기는 일
보안 문제 외에도 실질적인 불이익이 있다.
브라우저 경고 — Chrome은 HTTP 사이트에 접속하면 주소창에 "안전하지 않음"을 표시한다. 사용자가 이걸 보면 신뢰도가 바로 떨어진다.
SEO 불이익 — 구글은 HTTPS를 랭킹 시그널로 사용한다. 같은 조건이면 HTTPS 사이트가 HTTP 사이트보다 검색 결과에서 위에 나온다.
최신 웹 API 사용 불가 — Service Worker, 위치정보, 카메라/마이크 접근 같은 브라우저 API는 HTTPS 환경에서만 동작한다. HTTP에서는 아예 차단된다.
HTTP/2, HTTP/3 사용 불가 — 최신 HTTP 프로토콜은 사실상 HTTPS를 전제로 설계되어 있다. 성능 최적화를 하려면 HTTPS가 필수다.
TLS 1.3 vs TLS 1.2 — 뭐가 달라졌나
TLS 1.2와 1.3 둘 다 현역이긴 한데, 차이가 꽤 있다.
가장 큰 건 핸드셰이크 속도다. TLS 1.2는 핸드셰이크에 2-RTT(왕복 두 번)가 필요하다. 클라이언트가 "안녕"하고, 서버가 인증서 보내고, 다시 키 교환하고... 이 과정이 두 번 왔다 갔다 해야 끝난다. TLS 1.3은 이걸 1-RTT로 줄였다. 클라이언트가 첫 메시지에서 키 교환 파라미터를 같이 보내버리니까 한 번만 왕복하면 된다.
암호화 알고리즘도 정리됐다. TLS 1.2는 지원하는 cipher suite가 수십 개에 달했는데, 그중에는 보안이 약한 것들도 섞여 있었다. CBC 모드나 RC4 같은 게 대표적. TLS 1.3은 이런 레거시를 전부 쳐내고 AES-GCM, ChaCha20-Poly1305 등 검증된 알고리즘만 남겼다. 선택지가 줄었다는 건 잘못된 설정으로 보안에 구멍이 생길 가능성도 줄었다는 뜻이다.
또 하나, TLS 1.3에서는 0-RTT 재연결이 가능하다. 이전에 연결했던 서버라면 핸드셰이크 없이 바로 데이터를 보낼 수 있다. 다만 0-RTT 데이터는 재전송 공격(replay attack)에 취약할 수 있어서, 결제 처리 같은 민감한 요청에는 쓰지 않는 게 좋다.
2026년 기준으로 대부분의 최신 브라우저와 서버는 TLS 1.3을 기본으로 쓴다. TLS 1.2 지원을 아예 끄는 사이트도 늘어나는 추세다.
Let's Encrypt 인증서 발급 — 실제로 어떻게 하나
Let's Encrypt가 무료라는 건 위에서 말했고, 실제 발급 과정이 궁금할 수 있으니 좀 더 풀어본다.
가장 많이 쓰이는 클라이언트는 Certbot이다. 리눅스 서버에 Nginx나 Apache가 설치되어 있다면, Certbot을 깔고 한 줄이면 된다.
sudo certbot --nginx -d example.com -d www.example.com
이 명령 하나로 인증서 발급부터 Nginx 설정 수정까지 자동으로 처리된다. Certbot이 알아서 Let's Encrypt 서버와 통신해서 도메인 소유권을 검증하고(HTTP-01 챌린지 방식), 인증서를 받아와서 서버 설정에 적용한다.
갱신도 자동이다. certbot renew 명령을 cron이나 systemd timer에 등록해두면 만료 30일 전에 자동으로 갱신한다. 대부분의 리눅스 배포판에서 Certbot을 설치하면 자동 갱신 타이머가 같이 설정된다.
와일드카드 인증서(*.example.com)도 발급 가능한데, 이 경우에는 DNS-01 챌린지를 써야 한다. DNS 레코드에 특정 TXT 레코드를 추가하는 방식인데, DNS 제공업체가 API를 지원하면 이것도 자동화할 수 있다. Cloudflare나 Route 53 같은 서비스에는 Certbot 플러그인이 있다.
물론 Vercel이나 Netlify를 쓰면 이런 과정 자체가 필요 없다. 도메인 연결하면 인증서가 뒤에서 알아서 돌아간다.
개발자가 챙겨야 할 것들
HTTPS를 적용하는 것 자체는 호스팅 서비스가 알아서 해주는 시대가 됐지만, 개발할 때 주의할 점은 여전히 있다.
Mixed Content 문제 — 은근히 많이 걸린다
HTTPS 페이지에서 HTTP 리소스(이미지, 스크립트 등)를 로드하면 브라우저가 차단하거나 경고를 띄운다. 이걸 Mixed Content라고 한다. 모든 리소스 URL을 https://로 통일하거나, 프로토콜 상대 URL(//example.com/image.png)을 쓰면 해결된다.
문제는 직접 쓴 코드보다 외부 리소스에서 이게 많이 발생한다는 거다. 오래된 CDN 링크, 서드파티 위젯, 사용자가 입력한 이미지 URL 같은 것들. 특히 CMS나 에디터에서 사용자가 HTTP 이미지 URL을 붙여넣은 경우, 나중에 HTTPS로 전환하면서 전부 깨질 수 있다.
Chrome DevTools의 Console 탭에서 "Mixed Content" 경고를 확인할 수 있고, Content-Security-Policy: upgrade-insecure-requests 헤더를 설정하면 브라우저가 HTTP 리소스를 자동으로 HTTPS로 업그레이드하도록 요청할 수 있다. 다만 실제 HTTPS를 지원하지 않는 리소스는 여전히 실패하니까 근본적인 해결은 아니다.
HSTS — 한번 켜면 되돌리기 어렵다
Strict-Transport-Security 헤더를 설정하면, 브라우저가 해당 도메인에 항상 HTTPS로 접속하도록 강제한다. HTTP로 접속을 시도해도 자동으로 HTTPS로 리다이렉트된다.
Strict-Transport-Security: max-age=31536000; includeSubDomains
이게 강력한 이유는 서버 측 리다이렉트와 다르기 때문이다. 일반적인 301 리다이렉트는 HTTP 요청이 서버에 먼저 도달한 다음 HTTPS로 보내는 건데, HSTS는 브라우저 자체에서 HTTP 요청을 보내기도 전에 HTTPS로 바꿔버린다. 중간자 공격으로 HTTP 리다이렉트를 가로채는 것도 막을 수 있다.
주의점이 있다. max-age를 1년(31536000초)으로 설정해놓은 상태에서 HTTPS를 제거하면, 그 기간 동안 사이트에 접속이 불가능해진다. 브라우저가 캐시를 비우기 전까지는 무조건 HTTPS로만 접속을 시도하니까. 처음 적용할 때는 max-age=300 같이 짧게 시작하고, 문제없으면 점진적으로 늘리는 게 안전하다.
preload 지시자를 추가하고 HSTS preload list에 등록하면 브라우저가 처음 방문하는 사이트도 HTTPS로만 접속한다. 하지만 preload list에서 제거하는 건 수개월이 걸릴 수 있으니 정말 확실할 때만 등록해야 한다.
로컬 개발 환경 — localhost는 HTTPS 없이도 대부분의 브라우저 API가 동작한다. 브라우저가 localhost를 보안 컨텍스트(secure context)로 취급하기 때문이다. 로컬에서 HTTPS가 필요한 특수한 경우에는 mkcert 같은 도구로 로컬 인증서를 만들 수 있다.
HTTPS는 이제 선택이 아니라 기본값이다. 다행히 적용 난이도도 크게 낮아져서, 새 프로젝트를 시작할 때 HTTPS를 고민할 필요는 거의 없다. 다만 그 뒤에서 어떤 원리로 동작하는지 이해하고 있으면, 보안 관련 이슈가 생겼을 때 훨씬 빠르게 대응할 수 있다.