10년 전만 해도 SSL/HTTPS는 결제 페이지에서만 쓰는 옵션이었지만, 지금은 모든 사이트의 기본입니다. 이 글에서는 SSL 인증서의 역할, TLS 핸드셰이크 동작, 그리고 무료 인증서를 설치하는 실전 방법을 정리합니다.

TLS 1.3 핸드셰이크와 인증서 검증


왜 모든 사이트에 SSL이 필요한가

1) 데이터 도청·변조 방어

HTTP는 평문 통신입니다. 와이파이나 중간 라우터에서 누구나 내용을 볼 수 있습니다. HTTPS는 이를 암호화해 도청을 막고, MAC(메시지 인증 코드)로 위변조를 막습니다.

2) 신원 확인

브라우저는 인증서를 검증해 “이 서버가 정말 example.com인가”를 확인합니다. 가짜 서버가 중간자로 끼어들면 신원 검증에서 실패합니다.

3) 브라우저 경고 회피

크롬·파이어폭스·사파리는 HTTP 사이트에 “안전하지 않음” 경고를 띄웁니다. 사용자가 들어왔다 바로 떠나는 원인이 됩니다.

4) SEO 점수

구글은 HTTPS를 명시적인 랭킹 시그널로 사용합니다. HTTP 사이트는 검색 순위에서 불리합니다.

5) 현대 웹 기능 사용 가능

다음 기능들은 HTTPS 사이트에서만 동작합니다.

  • HTTP/2, HTTP/3 (성능 향상)
  • Service Worker (PWA)
  • 위치·카메라·마이크 API
  • Push 알림
  • WebAuthn (생체 인증)

SSL과 TLS는 같은 건가

엄밀히는 다릅니다.

  • SSL은 옛 프로토콜 (1.0~3.0, 모두 deprecated)
  • TLS가 현재 사용 중인 프로토콜 (1.0~1.3)
  • 다만 관습적으로 “SSL 인증서”라고 부르고, 실제로는 TLS를 사용

현재 권장 버전은 TLS 1.2 이상, 가급적 TLS 1.3입니다. TLS 1.0/1.1은 더 이상 안전하지 않아 비활성화해야 합니다.


SSL 인증서의 종류

용도별로 나뉩니다.

검증 수준 별

종류 검증 발급 시간 가격
DV (Domain Validation) 도메인 소유 확인 즉시~수 분 무료~$
OV (Organization Validation) 회사 정보 확인 1~3일 $$
EV (Extended Validation) 엄격한 회사 검증 1~2주 $$$

대부분의 사이트는 DV로 충분합니다. EV는 옛날엔 주소창에 회사명이 표시됐지만 최신 브라우저에서 그 시각적 차이가 사라져 메리트가 줄었습니다.

도메인 범위 별

종류 범위
단일 도메인 example.com만
멀티 도메인(SAN) example.com, foo.example.com, bar.com 등
와일드카드 *.example.com (모든 서브도메인)

서브도메인이 많으면 와일드카드가 편합니다. 무료 인증서 발급처인 Let’s Encrypt도 와일드카드를 지원합니다(DNS 인증 방식).


TLS 1.3 핸드셰이크 동작

위 그림처럼 클라이언트와 서버는 다음 순서로 안전한 연결을 수립합니다.

  1. ClientHello — 클라이언트가 지원 cipher와 키 공유를 보냄
  2. ServerHello + 인증서 — 서버가 자신의 인증서와 키 공유를 응답
  3. 인증서 검증 — 브라우저가 도메인 일치·체인·유효기간·폐기 확인
  4. 세션 키 확정 — 양측이 동일한 대칭키 합의
  5. 암호화 통신 — AES-GCM 또는 ChaCha20으로 데이터 송수신

TLS 1.3은 1-RTT로 완료되며, 이전 1.2(2-RTT)보다 한 단계 더 빠릅니다. 재방문 시 0-RTT도 가능합니다(보안 trade-off는 별도 고려).


무료 SSL 인증서 — Let’s Encrypt

Let’s Encrypt는 ISRG가 운영하는 무료 인증 기관(CA)입니다. 자동 발급·자동 갱신이 가능합니다.

Nginx + certbot 설치 (Ubuntu)

apt install -y certbot python3-certbot-nginx

# 자동 발급 + Nginx 설정 + HTTP→HTTPS 리다이렉트
certbot --nginx -d example.com -d www.example.com \
  --non-interactive --agree-tos -m admin@example.com --redirect

90일마다 자동 갱신되며, certbot이 systemd timer로 등록되어 추가 작업이 필요 없습니다.

Apache 사용 시

apt install -y certbot python3-certbot-apache
certbot --apache -d example.com -d www.example.com \
  --non-interactive --agree-tos -m admin@example.com --redirect

와일드카드 인증서 (DNS-01 인증)

서브도메인이 동적이면 와일드카드가 편합니다. DNS 인증이 필요해 약간 복잡합니다.

certbot certonly --manual --preferred-challenges=dns \
  -d "*.example.com" -d example.com

certbot이 표시하는 TXT 레코드를 DNS에 추가하면 발급됩니다. 자동 갱신을 위해 Cloudflare 등의 DNS API 플러그인을 쓰는 게 일반적입니다.

# Cloudflare DNS 자동 인증
apt install -y python3-certbot-dns-cloudflare
certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /root/.cf-credentials \
  -d "*.example.com" -d example.com

강력한 TLS 설정 (Nginx)

certbot이 기본 설정을 해주지만, 최상급 보안을 원한다면 직접 강화할 수 있습니다.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 프로토콜
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    # 강력한 cipher
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

    # 세션 캐싱
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 1.1.1.1 8.8.8.8 valid=300s;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

설정 후 Qualys SSL Labs에서 점검하면 A+ 등급을 받을 수 있습니다.


자주 발생하는 인증서 오류

NET::ERR_CERT_DATE_INVALID

  • 인증서 유효기간 만료. 자동 갱신 cron 동작 확인:
    certbot certificates
    systemctl status certbot.timer
    

NET::ERR_CERT_AUTHORITY_INVALID

  • 중간 인증서(체인) 누락. fullchain.pem을 쓰고 있는지 확인.

NET::ERR_CERT_COMMON_NAME_INVALID

  • 인증서가 다른 도메인용. SAN에 현재 도메인이 포함됐는지 확인.

Mixed Content 경고

  • HTTPS 페이지에 HTTP 리소스가 섞임 (이미지·JS·CSS)
  • 모든 자원을 HTTPS 또는 상대경로(//cdn...)로

인증서 자동 갱신 확인

# 갱신 시뮬레이션 (실제 갱신 X)
certbot renew --dry-run

# 인증서 만료일 확인
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

만료 30일 전이 되면 certbot이 자동 갱신을 시도합니다. 자동 갱신이 실패하면 메일 알림을 받기 위해 -m 옵션의 메일 주소를 유효한 것으로 등록해 두세요.


SSL 외에 적용하면 좋은 보안 헤더

HTTPS 적용 후 함께 적용하면 좋습니다.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

자세한 내용은 HTTPS 보안 헤더 가이드를 참고하세요.


마무리

SSL/TLS는 이제 선택이 아닌 기본입니다. Let’s Encrypt + certbot으로 무료·자동 설정이 가능하고, 한 번 설정해두면 90일 주기 갱신도 자동입니다.

TCP-80.NET의 VPS·전용서버는 SSL 발급·설치를 @tcp80net 텔레그램으로 한국어 안내합니다. 와일드카드 발급이나 다중 도메인 인증서 설정도 지원합니다.