Nginx SSL/TLS 설정 실전: HTTPS 인증서부터 A+ 보안 강화까지

모니터링 알람이 갑자기 울렸습니다. 휴대폰을 열어 보니 웹사이트 인증서가 만료되어 있었습니다. 유효 기간이 무려 90일인 무료 인증서를 완전히 잊고 있었던 것입니다. 브라우저의 빨간색 ‘안전하지 않음’ 경고가 조롱하는 깃발처럼 블로그 첫 화면에 걸려 있었습니다.
그 사고 이후 일주일 동안 Nginx SSL/TLS 설정을 처음부터 끝까지 파고들었습니다. SSL Labs 등급을 F에서 A+로 올리고, 수동 갱신을 완전 자동화했으며, 성능을 떨어뜨리던 핸드셰이크 시간을 100ms 이내로 줄였습니다.
HTTPS는 브라우저 주소 표시줄에 작은 자물쇠를 하나 붙이는 것에 그치지 않습니다. Google은 HTTPS가 검색 순위 요소 중 하나라고 명시했으며, HTTPS를 올바르게 설정하면 검색 트래픽이 15~20% 증가할 수 있습니다. 더 중요한 점은 중간자 도청을 막을 수 있다는 것입니다. HTTPS를 사용하지 않는 것은 공공장소에서 은행 카드 비밀번호를 큰 소리로 말하는 것과 같습니다.
이 글에서는 Nginx HTTPS를 처음부터 설정하는 방법을 안내합니다. Let’s Encrypt 인증서 발급, TLS 1.3 보안 강화, SSL Labs A+ 등급 설정 템플릿, 그리고 프로덕션 환경에 꼭 필요한 자동 갱신 방안까지 다룹니다. 모든 설정은 그대로 복사해 사용할 수 있습니다.
1장: HTTPS 기본 개념과 인증서 유형 선택
1.1 모든 웹사이트에 HTTPS가 필요한 이유
HTTP는 데이터를 평문으로 전송합니다. 즉, 방문하는 모든 페이지와 제출하는 모든 양식이 네트워크에 그대로 노출됩니다. 카페의 공용 WiFi, 회사의 네트워크 출구, 주거 지역의 통신사 장비 등 중간에 있는 어떤 노드든 여러분이 보낸 내용을 볼 수 있습니다.
HTTPS는 HTTP와 TCP 사이에 TLS 암호화 계층을 추가합니다. 데이터는 전송되기 전에 암호화되고 도착한 뒤 복호화되므로, 중간에서 도청하는 사람에게는 의미 없는 문자열만 보입니다.
TLS의 역할은 암호화에 그치지 않습니다. 신원 인증도 제공합니다. 즉, 여러분이 접속한 곳이 DNS 하이재킹으로 연결된 피싱 사이트가 아니라 실제 example.com인지 확인합니다. 브라우저가 만료된 인증서나 도메인이 일치하지 않는 인증서에 빨간색 경고를 표시하는 이유도 여기에 있습니다. ‘이 웹사이트는 자신이 주장하는 그 사이트가 아닐 수 있다’고 알려 주는 것입니다.
1.2 SSL 인증서의 세 가지 유형: DV, OV, EV
인증서는 검증의 엄격한 정도에 따라 세 가지로 나뉩니다.
| 유형 | 검증 방법 | 가격 | 적합한 환경 |
|---|---|---|---|
| DV(도메인 검증) | 도메인 소유권 검증 | 무료~저가 | 개인 블로그, 테스트 환경, 소규모 프로젝트 |
| OV(조직 검증) | 도메인 + 조직 신원 검증 | 중간 | 기업 공식 웹사이트, SaaS 제품 |
| EV(확장 검증) | 가장 엄격한 신원 검증 | 높음 | 금융, 결제, 정부 기관 |
솔직히 말해 대부분의 개인 프로젝트와 소규모 팀에는 DV 인증서면 충분합니다. Let’s Encrypt가 제공하는 무료 DV 인증서는 유효 기간이 90일이며, 브라우저 신뢰 수준도 유료 DV 인증서와 다르지 않습니다. 유일한 ‘단점’은 90일마다 갱신해야 한다는 것이지만, 자동 갱신을 설정하면 전혀 문제가 되지 않습니다.
OV와 EV 인증서의 차이는 주로 브라우저 주소 표시줄에 표시되는 방식에 있습니다. EV 인증서는 회사명(예: ‘중국공상은행’)을 표시하지만, 요즘 브라우저는 EV 인증서를 시각적으로 점점 덜 강조하며 Chrome은 기본적으로 EV 인증서의 회사명을 더 이상 표시하지 않습니다. 게다가 OV/EV 인증서는 수백에서 수천에 이르는 비용이 들기 때문에 가성비가 그다지 좋지 않습니다.
1.3 Let’s Encrypt: 무료 인증서의 최선의 선택
Let’s Encrypt는 ISRG(Internet Security Research Group)가 운영하는 비영리 인증 기관입니다. 다음과 같은 핵심 장점이 있습니다.
- 완전 무료: DV 인증서를 영구적으로 무료 제공
- 자동화: ACME 프로토콜을 통해 자동으로 발급하고 갱신
- 폭넓은 신뢰: 모든 주요 브라우저와 운영체제에서 신뢰
- 90일 유효 기간: 단기 인증서로 보안을 높이고 자동화 설정을 유도
단점도 있습니다. DV 인증서만 제공하고 OV/EV 인증서는 제공하지 않으며, 와일드카드 인증서는 DNS 검증이 필요해 조금 더 번거롭습니다. 하지만 개인 프로젝트와 중소 규모 웹사이트의 99%에는 이런 ‘단점’이 사실상 문제가 되지 않습니다.
이제 Let’s Encrypt의 공식 클라이언트인 Certbot으로 인증서를 발급해 보겠습니다.
2장: Let’s Encrypt 인증서 발급 실전
2.1 Certbot 설치
Certbot 설치 방법은 운영체제에 따라 다릅니다. Ubuntu 사용자는 다음 방법이 가장 간단합니다.
# Ubuntu 20.04+ / Debian 10+
sudo apt update
sudo apt install certbot python3-certbot-nginx
CentOS/RHEL 사용자는 먼저 EPEL 저장소를 활성화해야 합니다.
# CentOS 8 / RHEL 8
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx
설치가 끝나면 certbot --version으로 버전을 확인할 수 있습니다. 이상이 없으면 다음 단계에서 인증서를 발급합니다.
2.2 인증서 발급
Certbot은 여러 검증 방식을 지원하며, 가장 많이 쓰이는 방식은 standalone(독립 검증)과 webroot(웹사이트 루트 디렉터리 검증)입니다. Nginx가 이미 실행 중이라면 webroot 모드를 권장합니다.
# webroot 모드: 웹사이트가 실행 중일 때 사용
sudo certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com
-w는 웹사이트 루트 디렉터리를, -d는 도메인을 지정합니다. 한 번에 여러 도메인의 인증서를 발급할 수 있습니다.
Nginx를 아직 시작하지 않았거나 임시 서버에서 테스트만 한다면 standalone 모드를 사용합니다.
# standalone 모드: 80번 포트를 임시로 사용해야 함
sudo certbot certonly --standalone -d example.com -d www.example.com
이 모드에서는 Certbot이 임시 HTTP 서버를 시작하고, 검증이 끝나면 자동으로 종료합니다. 검증 과정에서 80번 포트가 비어 있어야 하므로 Nginx가 이미 실행 중이라면 먼저 중지해야 합니다.
더 간단한 방법도 있습니다. Certbot의 Nginx 플러그인을 사용하면 Nginx 설정을 자동으로 수정할 수 있습니다.
# 자동 설정 모드: Certbot이 Nginx 설정을 자동으로 수정
sudo certbot --nginx -d example.com -d www.example.com
이 명령은 인증서 발급, Nginx 설정 수정, HTTPS 리디렉션 설정을 자동으로 처리합니다. 초보자가 빠르게 시작하기에는 좋지만, SSL 매개변수를 더 세밀하게 제어해야 하는 프로덕션 환경에서는 수동 설정을 권장합니다.
2.3 인증서 파일 구조
발급에 성공하면 인증서 파일은 기본적으로 /etc/letsencrypt/live/example.com/ 디렉터리에 저장됩니다.
/etc/letsencrypt/live/example.com/
├── cert.pem # 도메인 인증서
├── chain.pem # 중간 인증서 체인
├── fullchain.pem # 전체 인증서 체인(cert + chain)
└── privkey.pem # 개인 키 파일
Nginx 설정에는 fullchain.pem(ssl_certificate)과 privkey.pem(ssl_certificate_key), 두 파일이 필요합니다. privkey.pem은 민감한 파일이므로 권한을 600으로 설정하고 절대 유출하지 마세요.
3장: Nginx SSL 기본 설정
3.1 가장 기본적인 HTTPS 설정
인증서를 준비했으면 다음 단계는 Nginx에 HTTPS를 설정하는 것입니다. 가장 단순한 설정은 다음과 같습니다.
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 기타 설정...
root /var/www/example.com;
index index.html;
}
이 설정으로 HTTPS를 실행할 수 있지만 등급은 D에 불과합니다. TLS 버전을 지정하지 않아 기본적으로 TLS 1.0과 1.1을 지원하기 때문입니다. 이 두 버전은 오래전에 안전하지 않은 것으로 판정되었습니다.
3.2 HTTP에서 HTTPS로 리디렉션
HTTPS만 설정해서는 충분하지 않습니다. 사용자가 HTTP 버전으로 직접 접속할 수 있기 때문입니다. 모든 HTTP 요청을 HTTPS로 리디렉션해야 합니다.
server {
listen 80;
server_name example.com www.example.com;
# HTTPS로 영구 리디렉션
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 기타 설정...
}
return 301은 영구 리디렉션이며 브라우저가 이 이동을 캐시합니다. 다음에 사용자가 http://를 입력하면 브라우저가 https://로 바로 이동해 요청 한 번을 줄일 수 있습니다.
3.3 흔히 발생하는 설정 오류
listen 443 ssl; 뒤에 http2를 붙여 listen 443 ssl http2;로 작성하는 경우를 자주 봤습니다. Nginx 1.25.1 이후에는 HTTP/2 지원이 http2 지시어로 분리되었습니다.
# Nginx 1.25.1+의 새로운 작성 방식
server {
listen 443 ssl;
http2 on; # 독립된 http2 지시어
server_name example.com;
# ...
}
Nginx 버전이 비교적 최신이라면 설정 경고를 피할 수 있도록 새로운 작성 방식을 권장합니다. nginx -v로 버전을 확인할 수 있습니다.
4장: TLS 1.3 보안 강화 설정
4.1 TLS 버전 선택
TLS에는 1.0, 1.1, 1.2, 1.3의 네 가지 버전이 있습니다. 이 중 1.0과 1.1은 폐기되었으며, 모든 주요 브라우저가 2020년에 지원을 중단했습니다.
| 버전 | 보안 | 성능 | 호환성 | 권장 사항 |
|---|---|---|---|---|
| TLS 1.0 | 안전하지 않음 | 느림 | 폭넓게 지원 | 비활성화 |
| TLS 1.1 | 안전하지 않음 | 느림 | 폭넓게 지원 | 비활성화 |
| TLS 1.2 | 안전함 | 보통 | 거의 모두 지원 | 유지 가능 |
| TLS 1.3 | 가장 안전함 | 가장 빠름 | 최신 브라우저 | 반드시 활성화 |
TLS 1.3의 핵심 장점은 성능입니다. 핸드셰이크가 2-RTT(왕복)에서 1-RTT로 줄어 이론상 핸드셰이크 지연 시간을 절반으로 낮출 수 있습니다. 실제 테스트에서도 TLS 1.3의 핸드셰이크 시간을 100ms 이내로 줄일 수 있습니다.
Nginx 설정에서는 ssl_protocols 지시어로 TLS 버전을 지정합니다.
ssl_protocols TLSv1.2 TLSv1.3;
TLS 1.3만 활성화하는 것은 권장하지 않습니다. 2026년에는 거의 모든 브라우저가 TLS 1.3을 지원하지만 일부 구형 HTTP 클라이언트, 예를 들어 특정 API 호출 도구나 임베디드 장치는 아직 지원하지 않을 수 있습니다. 호환 옵션으로 TLS 1.2를 유지하는 편이 더 안전한 선택입니다.
4.2 Cipher Suite 설정
Cipher Suite(암호 스위트)는 암호화 알고리즘, 키 교환 방식, 메시지 인증 코드를 결정합니다. 잘못 선택하면 HTTPS가 사실상 무용지물이 될 수 있습니다.
2026년에 권장하는 TLS 1.3 cipher suite 목록은 다음과 같습니다.
ssl_protocols TLSv1.2 TLSv1.3;
# TLS 1.3 cipher(Nginx는 OpenSSL 기본 목록을 자동으로 사용)
# 이 줄은 생략할 수 있지만 유지해도 무방함
ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
# TLS 1.2 cipher(하위 호환)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
# 서버가 지정한 cipher를 우선 사용
ssl_prefer_server_ciphers on;
이 설정의 핵심은 다음과 같습니다.
- ECDHE: RSA보다 더 안전하고 빠른 타원 곡선 키 교환을 우선 사용
- AES-GCM: CBC 모드보다 안전한 인증 암호화를 제공하는 GCM 모드 사용
- CHACHA20-POLY1305: AES 하드웨어 가속이 없는 장치에 적합하고 모바일 성능이 우수함
잘 모르겠다면 Mozilla SSL Configuration Generator를 사용해 설정을 생성할 수 있습니다: https://ssl-config.mozilla.org/
4.3 HSTS: HTTPS 접속 강제
HSTS(HTTP Strict Transport Security)는 브라우저에 ‘이 웹사이트는 HTTPS 접속만 허용한다’고 알립니다. 사용자가 http://를 직접 입력해도 브라우저가 로컬에서 https://로 강제 전환하므로 네트워크 요청 한 번을 줄일 수 있습니다.
# HSTS 헤더
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
매개변수의 의미는 다음과 같습니다.
max-age=31536000: 유효 기간 1년(초 단위)includeSubDomains: 모든 하위 도메인 포함preload: HSTS Preload List에 추가(hstspreload.org에서 제출 필요)
주의: HSTS를 활성화하면 브라우저가 오랫동안 캐시합니다. HTTP 버전을 테스트해야 한다면 처음에는 preload를 추가하지 않거나 max-age를 짧게 설정하세요.
5장: SSL 성능 최적화 방법
5.1 SSL Session Cache
TLS 핸드셰이크를 할 때마다 키 교환과 인증서 검증이 필요해 오버헤드가 작지 않습니다. Session Cache를 사용하면 클라이언트가 일정 시간 동안 이전 세션을 재사용해 전체 핸드셰이크 과정을 건너뛸 수 있습니다.
# Session Cache 설정
ssl_session_cache shared:SSL:10m; # 10MB 캐시, 약 40000개 세션
ssl_session_timeout 1d; # 세션 유효 기간 1일
ssl_session_tickets off; # Session Ticket 비활성화(더 안전함)
shared:SSL:10m은 모든 worker 프로세스가 10MB 캐시 영역을 공유한다는 뜻입니다. 1MB에 약 4000개 세션을 저장할 수 있으므로 10MB면 중소 규모 웹사이트에 충분합니다.
ssl_session_tickets off는 보안을 위한 설정입니다. Session Ticket 메커니즘에서는 서버가 Ticket을 암호화할 키를 유지해야 합니다. 이 키가 유출되면 공격자가 모든 과거 세션을 복호화할 수 있습니다. 비활성화하면 더 안전하지만 서버 부담이 늘어납니다. 보안 요구 수준이 높은 환경에 적합합니다.
5.2 OCSP Stapling
브라우저가 인증서를 검증할 때는 인증서가 폐기되었는지 확인해야 합니다. 기존 방식은 CA에 OCSP 조회를 요청하므로 네트워크 요청이 한 번 늘고 사용자가 어떤 웹사이트를 방문했는지도 노출됩니다.
OCSP Stapling을 사용하면 서버가 브라우저 대신 OCSP 상태를 조회해 결과를 캐시한 뒤 브라우저에 함께 전달합니다. 개인정보를 보호하면서 지연 시간도 줄일 수 있습니다.
# OCSP Stapling 설정
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
resolver는 OCSP 서버의 도메인을 조회할 DNS 서버를 지정합니다. Google의 8.8.8.8과 8.8.4.4가 일반적으로 사용되는 선택지입니다.
설정을 마친 뒤 OpenSSL로 테스트할 수 있습니다.
openssl s_client -connect example.com:443 -status < /dev/null 2>&1 | grep -A 17 "OCSP response"
“OCSP Response Status: successful”이 표시되면 OCSP Stapling이 정상적으로 작동하는 것입니다.
5.3 ssl_buffer_size 조정
ssl_buffer_size는 TLS 레코드 크기를 제어합니다. 기본값인 16KB는 API 요청 같은 작은 응답에는 너무 커서 TTFB(첫 바이트까지 걸리는 시간)를 늘릴 수 있습니다.
작은 응답이 많은 API 서버나 블로그 웹사이트라면 값을 줄일 수 있습니다.
ssl_buffer_size 4k; # 작은 응답 환경에 적합
대용량 파일 다운로드 서버라면 기본값인 16KB를 유지하거나 32KB로 늘리는 것이 더 적합합니다.
6장: 인증서 자동 갱신 설정
6.1 Certbot 자동 갱신 명령
Let’s Encrypt 인증서의 유효 기간은 90일뿐이므로 정기적으로 갱신해야 합니다. Certbot은 renew 명령을 제공합니다.
# 갱신 테스트(실제로 갱신하지 않고 확인만 함)
sudo certbot renew --dry-run
# 실제 갱신
sudo certbot renew
renew 명령은 모든 인증서의 만료 시점을 확인하고 남은 유효 기간이 30일 미만인 인증서만 갱신합니다. 따라서 이 명령을 매일 실행해도 괜찮습니다. Let’s Encrypt의 속도 제한 할당량을 낭비하지 않습니다.
6.2 crontab 예약 작업 설정
가장 안정적인 방법은 crontab으로 자동 갱신을 설정하는 것입니다.
# root 사용자의 crontab 편집
sudo crontab -e
다음 두 줄을 추가합니다.
# 매일 새벽 3시와 오후 3시에 한 번씩 확인
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
0 15 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
--quiet은 로그를 출력하지 않는 자동 모드입니다. --post-hook "systemctl reload nginx"는 갱신에 성공한 뒤 Nginx 설정을 다시 로드해 새 인증서를 적용합니다.
왜 하루에 두 번 확인할까요? DNS 조회가 일시적으로 실패하는 등의 이유로 갱신이 가끔 실패할 수 있기 때문입니다. 여러 번 확인하면 성공 가능성이 높아집니다.
6.3 갱신 테스트 및 문제 해결
갱신에 실패하면 Certbot이 /var/log/letsencrypt/letsencrypt.log에 상세 로그를 기록합니다. 흔한 문제는 다음과 같습니다.
- 포트 사용 중: standalone 모드에는 80번 포트가 필요하므로 Nginx가 점유하지 않았는지 확인합니다.
- DNS 조회 실패: 도메인의 DNS 레코드가 서버를 올바르게 가리키는지 확인합니다.
- 속도 제한: Let’s Encrypt에서는 동일한 인증서를 주당 최대 5번 발급할 수 있으므로 테스트할 때는
--dry-run을 사용합니다. - 인증서 디렉터리 권한: Certbot에
/etc/letsencrypt/읽기 및 쓰기 권한이 있는지 확인합니다.
전체 갱신 테스트 과정은 다음과 같습니다.
# 1. 먼저 dry-run 테스트
sudo certbot renew --dry-run
# 2. dry-run에 성공하면 실제 갱신
sudo certbot renew
# 3. 인증서 유효 기간 확인
sudo certbot certificates
# 4. Nginx 다시 로드
sudo systemctl reload nginx
전체 설정 템플릿
다음은 SSL Labs A+ 등급을 달성한 프로덕션 환경용 Nginx SSL 설정 템플릿입니다.
# HTTP 리디렉션
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS 서비스
server {
listen 443 ssl;
http2 on;
server_name example.com www.example.com;
# 인증서 설정
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# TLS 버전
ssl_protocols TLSv1.2 TLSv1.3;
# Cipher Suite
ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers on;
# 보안 헤더
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# Session Cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 성능 조정
ssl_buffer_size 4k;
# 웹사이트 설정
root /var/www/example.com;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
설정을 마친 뒤 SSL Labs에서 등급을 테스트하세요: https://www.ssllabs.com/ssltest/
정리
HTTPS 설정은 시작하기 어렵지 않습니다. 몇 줄만 설정해도 실행할 수 있습니다. 하지만 SSL Labs A+ 등급에 도달하면서 성능과 호환성까지 챙기려면 TLS 버전, Cipher Suite, Session Cache, OCSP Stapling과 같은 세부 사항을 이해해야 합니다.
핵심 설정 사항을 정리하면 다음과 같습니다.
- 인증서 발급: 무료이고 편리한 Let’s Encrypt와 자동화가 쉬운 Certbot 사용
- TLS 버전: TLS 1.2 + 1.3을 사용하고 1.0과 1.1은 비활성화
- Cipher Suite: ECDHE와 AES-GCM을 우선하고 CHACHA20도 함께 지원
- HSTS: HTTPS를 강제해 리디렉션 오버헤드 감소
- 성능 최적화: Session Cache와 OCSP Stapling 모두 적용
- 자동 갱신: crontab으로 이중 확인하고 갱신 후 Nginx 자동 재로드
위 설정 템플릿을 Nginx 설정에 복사한 뒤 도메인과 인증서 경로만 바꾸면 바로 사용할 수 있습니다. 설정을 마치면 SSL Labs 등급을 테스트하고 댓글로 결과를 알려 주세요. 아마 A+일 가능성이 높습니다.
Nginx SSL/TLS를 설정해 A+ 보안 등급 달성하기
인증서 발급부터 보안 강화까지 이어지는 전체 설정 과정
⏱️ Estimated time: 30 min
- 1
Step 1: Certbot 설치 및 인증서 발급
Certbot으로 Let's Encrypt 무료 SSL 인증서를 발급합니다:
• Ubuntu/Debian: sudo apt install certbot python3-certbot-nginx
• CentOS/RHEL: sudo dnf install certbot python3-certbot-nginx
• 인증서 발급: sudo certbot certonly --webroot -w /var/www/example.com -d example.com
• 인증서 디렉터리: /etc/letsencrypt/live/example.com/
• 필요한 파일 두 개: fullchain.pem과 privkey.pem - 2
Step 2: Nginx HTTPS 기본 설정
Nginx 설정에 SSL 인증서와 HTTP 리디렉션을 추가합니다:
• listen 443 ssl;로 HTTPS 수신 설정
• http2 on;으로 HTTP/2 활성화(Nginx 1.25.1+)
• ssl_certificate가 fullchain.pem을 가리키도록 설정
• ssl_certificate_key가 privkey.pem을 가리키도록 설정
• return 301 https://$server_name$request_uri;로 HTTP를 HTTPS로 리디렉션 - 3
Step 3: TLS 1.3 및 Cipher Suite 설정
안전한 TLS 버전과 암호 스위트를 활성화합니다:
• ssl_protocols TLSv1.2 TLSv1.3;으로 구버전 비활성화
• ssl_ciphers에 ECDHE + AES-GCM + CHACHA20 설정
• ssl_prefer_server_ciphers on;으로 서버 선택 우선
• add_header Strict-Transport-Security로 HSTS 활성화 - 4
Step 4: SSL 성능 최적화
Session Cache와 OCSP Stapling을 설정해 성능을 높입니다:
• ssl_session_cache shared:SSL:10m;으로 공유 세션 캐시 설정
• ssl_session_timeout 1d;로 세션 유효 기간을 하루로 설정
• ssl_stapling on;으로 OCSP Stapling 활성화
• ssl_buffer_size 4k;로 작은 응답 환경 최적화 - 5
Step 5: 인증서 자동 갱신 설정
crontab으로 Certbot 자동 갱신을 설정합니다:
• sudo crontab -e로 예약 작업 편집
• 0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
• 매일 두 번(새벽과 오후에 한 번씩) 확인
• --post-hook으로 갱신 후 Nginx가 새 인증서를 다시 로드하도록 보장 - 6
Step 6: SSL 설정 보안 테스트
설정이 A+ 등급에 도달했는지 확인합니다:
• https://www.ssllabs.com/ssltest/ 에 접속해 SSL 설정 테스트
• openssl s_client -connect example.com:443 -status로 OCSP 테스트
• certbot certificates로 인증서 유효 기간 확인
• HSTS, OCSP Stapling, Session Cache가 모두 적용되었는지 확인
FAQ
Let's Encrypt 인증서의 유효 기간은 얼마이며 수동으로 갱신해야 하나요?
Nginx SSL 설정의 보안 수준은 어떻게 테스트하나요?
• A+는 최고 등급으로, 설정이 안전하고 성능도 우수하다는 뜻입니다.
• openssl s_client 명령으로 로컬에서 OCSP Stapling을 테스트할 수도 있습니다.
• 테스트 명령: openssl s_client -connect example.com:443 -status
HTTPS가 웹사이트 성능에 영향을 주나요? 어떻게 최적화하나요?
• TLS 1.3은 핸드셰이크를 2-RTT에서 1-RTT로 줄여 지연 시간을 절반으로 낮춥니다.
• Session Cache를 사용하면 클라이언트가 세션을 재사용해 전체 핸드셰이크를 건너뜁니다.
• OCSP Stapling은 인증서 검증을 위한 네트워크 요청을 줄입니다.
• 최적화 후에는 핸드셰이크 시간을 100ms 이내로 제어할 수 있습니다.
인증서 갱신이 실패하면 어떻게 문제를 해결하나요?
• 포트 사용 중: standalone 모드에서는 80번 포트가 비어 있어야 합니다.
• DNS 조회 실패: 도메인이 서버 IP를 올바르게 가리키는지 확인합니다.
• 속도 제한: Let's Encrypt에서는 동일한 인증서를 주당 최대 5번 발급할 수 있습니다.
• 로그 확인: /var/log/letsencrypt/letsencrypt.log
TLS 1.2와 TLS 1.3의 차이는 무엇이며 왜 둘 다 활성화해야 하나요?
• 성능: 핸드셰이크가 2-RTT에서 1-RTT로 줄어 지연 시간이 절반으로 낮아집니다.
• 보안: 안전하지 않은 암호화 알고리즘이 제거되었습니다.
• 호환성: 구형 클라이언트를 지원하기 위해 둘 다 활성화하며, TLS 1.2를 호환 옵션으로 유지합니다.
HSTS를 설정할 때 주의할 점은 무엇인가요?
• max-age는 31536000(1년)으로 설정하는 것을 권장합니다.
• includeSubDomains는 모든 하위 도메인에 영향을 줍니다.
• preload는 hstspreload.org에 제출해야 적용됩니다.
• 처음 설정할 때는 짧은 max-age로 테스트한 뒤 문제가 없음을 확인하고 늘리는 것이 좋습니다.
SSL 인증서 유형은 어떻게 선택하나요? DV, OV, EV의 차이는 무엇인가요?
• DV 인증서: 무료이며 도메인 소유권을 검증합니다. 개인 블로그와 소규모 프로젝트에 적합합니다.
• OV 인증서: 조직의 신원을 검증하고 회사 정보를 표시합니다. 기업 공식 웹사이트에 적합합니다.
• EV 인증서: 엄격하게 검증하지만 Chrome에서 더 이상 회사명을 표시하지 않아 가성비가 낮습니다.
• 99%의 환경에는 Let's Encrypt 무료 DV 인증서를 권장합니다.
3분 읽기 · 게시일: 2026년 4월 20일 · 수정일: 2026년 9월 4일



댓글
GitHub로 로그인하여 댓글을 남기세요