Spring 개발 서버에서 인증 방식을 헤더 Access Token에서 쿠키 기반으로 변경하면서 HTTPS 적용이 필요했습니다. Secure 속성이 있는 쿠키는 HTTPS 환경에서만 브라우저가 자동 전송되기 때문에, 개발 서버에도 인증서를 적용해야 합니다.
이번 글에서는 Nginx와 Let’s Encrypt를 활용해 간단하게 HTTPS를 적용하고, 이후 발생한 리다이렉트 루프 문제까지 해결한 과정을 공유합니다 :)
DNS 확인
dig +short dtalks.kro.kr A
# 서버 IP가 정상적으로 나와야 함
포트 개방 확인
Let’s Encrypt 인증 발급은 80 포트 접근이 필수입니다.
sudo ss -ltnp | grep -E ':80|:443'
Nginx 설치
sudo apt-get update
sudo apt-get install -y nginx
sudo systemctl enable --now nginx
# 방화벽
sudo ufw allow 'Nginx Full' # 80, 443
HTTPS 적용을 위해 무료 인증서 발급 서비스인 Let’s Encrypt를 사용합니다. certbot과 python3-certbot-nginx 패키지를 설치하면, Nginx 설정과 인증서 발급 과정을 처리할 수 있습니다.
# certbot 및 Nginx 플러그인 설치
sudo apt-get install -y certbot python3-certbot-nginx
# Nginx 플러그인으로 인증서 발급
sudo certbot --nginx -d <도메인>
실행하면 다음 작업이 자동으로 진행됩니다.
1) 도메인 소유 확인
Let’s Encrypt가 HTTP-01 챌린지를 수행하여 해당 도메인의 소유 여부를 검증합니다. 이 과정에서 80번 포트가 열려 있어야 합니다!
2) 인증서 발급
도메인 검증이 완료되면, 다음 인증서 파일이 생성됩니다.
3) Nginx 설정 자동 수정
기존 Nginx 서버 블록의 ssl_certificate, ssl_certificate_key 경로가 위 Let’s Encrypt 경로로 자동 변경됩니다.
4) 자동 갱신 등록
/etc/cron.d/certbot에 인증서 자동 갱신 크론잡이 추가됩니다.
발급이 완료되면 아래 명령어로 인증서 경로와 유효기간을 확인할 수 있습니다 ☺️
sudo nginx -T | grep ssl_certificate
sudo certbot certificates
리버스 프록시(Nginx)를 거치면, 사용자가 HTTPS로 접속하더라도 애플리케이션에는 기본적으로 HTTP 요청처럼 전달됩니다. 이때 Nginx는 원래 요청이 HTTPS였다는 정보를 X-Forwarded-Proto: https 헤더로 함께 보내고, Spring이 이 헤더를 신뢰하도록 설정해야 합니다.
# application.properties
server.forward-headers-strategy=framework
원인: 프록시 스킴 인식 불일치
Nginx는 HTTPS로 종료했지만, Spring이 요청을 HTTP로 인식 → 다시 HTTPS로 리다이렉트 → 무한 반복
해결 방법
Nginx 443 블록의 location / 안에 다음 추가
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization $http_authorization;
# 80 → 443 리다이렉트
server {
listen 80;
server_name <도메인>;
return 301 https://$host$request_uri;
}
# 443 → Spring Boot 프록시
server {
listen 443 ssl http2;
server_name <도메인>;
ssl_certificate /etc/letsencrypt/live/<도메인>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<도메인>/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization $http_authorization;
proxy_set_header Connection "";
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
🥳 이제 https://<도메인>으로 접속할 수 있습니다.