Nginx에서 HTTP를 HTTPS로 리다이렉트하는 방법
웹 서버를 운영한다면 HTTP로 들어오는 요청을 HTTPS로 자동으로 넘겨주는 설정은 사실상 필수입니다. 보안 연결을 강제하는 것은 사용자 데이터를 보호하고, 검색엔진 최적화에도 긍정적인 영향을 줍니다. Nginx에서는 이 설정을 비교적 간단하게 처리할 수 있지만, 올바른 방법을 모르면 리다이렉트 루프나 성능 저하 같은 문제가 생길 수 있습니다.
이 글에서는 Nginx 환경에서 HTTP를 HTTPS로 리다이렉트하는 방법을 단계별로 정리합니다.
사전 준비사항
본격적인 설정에 앞서 몇 가지가 준비되어 있어야 합니다.
- SSL/TLS 인증서: 도메인에 대한 유효한 인증서가 필요합니다. Let’s Encrypt를 통해 무료로 발급받을 수 있습니다.
- Nginx 설치: 서버에 Nginx가 설치되어 실행 중이어야 합니다.
- 도메인 DNS 설정: 도메인이 서버 IP를 올바르게 가리키고 있어야 합니다.
- 포트 80, 443 개방: 방화벽에서 두 포트가 모두 열려 있어야 합니다.
인증서가 없다면 Certbot을 이용해 Let’s Encrypt 인증서를 먼저 발급받는 것을 권장합니다.
기본 리다이렉트 설정 방법
Nginx에서 HTTP를 HTTPS로 리다이렉트하는 가장 일반적인 방법은 서버 블록을 두 개 작성하는 것입니다. 하나는 포트 80(HTTP)을 수신하고, 다른 하나는 포트 443(HTTPS)을 처리합니다.
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$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;
# 나머지 서버 설정
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
첫 번째 서버 블록은 포트 80으로 들어오는 모든 요청을 301 Moved Permanently 상태 코드와 함께 HTTPS 주소로 리다이렉트합니다. $host와 $request_uri 변수를 사용해 원래 요청한 도메인과 경로를 유지한 채로 넘겨주는 것이 핵심입니다.
301 리다이렉트를 사용하는 이유는 검색엔진에 이 변경이 영구적임을 알리기 위해서입니다. 일시적인 테스트 목적이라면 302를 쓸 수도 있지만, 실제 운영 환경에서는 301이 적합합니다.
return 301과 rewrite 중 무엇을 써야 할까
간혹 rewrite 지시어를 이용한 리다이렉트 설정을 보게 됩니다.
server {
listen 80;
server_name example.com www.example.com;
rewrite ^ https://$host$request_uri permanent;
}
기능적으로는 return 301과 동일한 결과를 냅니다. 그러나 Nginx 공식 문서와 커뮤니티에서는 return 방식을 권장합니다. 이유는 처리 방식의 차이 때문입니다. return은 요청을 즉시 반환하는 반면, rewrite는 정규식을 파싱하고 내부적으로 추가 처리를 거칩니다. 단순한 리다이렉트라면 return 301이 더 간결하고 효율적입니다.
Let’s Encrypt와 Certbot을 사용하는 경우
Certbot으로 인증서를 발급받으면 Nginx 설정 파일을 자동으로 수정해 주는 옵션이 있습니다. 다음 명령을 실행하면 인증서 발급과 함께 HTTPS 리다이렉트 설정까지 한 번에 처리됩니다.
sudo certbot --nginx -d example.com -d www.example.com
Certbot이 설정을 자동으로 수정한 뒤 HTTP에서 HTTPS로 리다이렉트할 것인지 묻는 프롬프트가 나타납니다. 리다이렉트를 선택하면 Certbot이 포트 80 서버 블록에 적절한 설정을 추가합니다.
자동 설정 후에는 /etc/nginx/sites-available/ 경로의 설정 파일을 열어 내용이 올바르게 반영되었는지 직접 확인하는 것이 좋습니다. 자동화에 의존하더라도 설정 파일의 내용을 직접 이해하고 있어야 문제가 생겼을 때 빠르게 대응할 수 있습니다.
www와 non-www를 함께 처리하는 방법
www 도메인과 non-www 도메인을 함께 운영하는 경우, 두 가지를 모두 HTTPS로 리다이렉트하면서 하나의 표준 URL로 통일하는 것이 SEO 관점에서도 유리합니다.
예를 들어 www.example.com을 기본 도메인으로 사용하고 싶다면 다음과 같이 설정합니다.
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name 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/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
이 방식에서는 HTTP로 들어오는 모든 요청은 먼저 www.example.com의 HTTPS 주소로 리다이렉트되고, example.com으로 HTTPS 접속하는 경우도 www.example.com으로 한 번 더 넘겨줍니다. 다만 이 경우 두 번의 리다이렉트가 발생할 수 있으므로, 가능하면 포트 80 서버 블록에서 최종 목적지 URL로 바로 이동시키는 것이 좋습니다.
설정 파일 문법 검사 및 Nginx 재시작
설정을 변경한 후에는 반드시 문법 검사를 먼저 수행해야 합니다. 문법 오류가 있는 상태에서 Nginx를 재시작하면 서비스가 중단될 수 있습니다.
sudo nginx -t
이 명령을 실행했을 때 syntax is ok와 test is successful 메시지가 출력되면 설정에 문제가 없는 것입니다. 이후 Nginx를 재시작하거나 설정을 다시 불러옵니다.
sudo systemctl reload nginx
reload는 Nginx를 완전히 재시작하지 않고 설정만 다시 불러옵니다. 서비스 중단 없이 설정을 반영할 수 있어 운영 중인 서버에서 권장되는 방법입니다.
자주 발생하는 문제와 해결 방법
리다이렉트 루프 발생
리다이렉트 루프는 서버가 HTTPS 연결을 제대로 처리하지 못하면서 계속 리다이렉트를 반복하는 현상입니다. 주로 로드밸런서나 리버스 프록시 뒤에 Nginx가 배치된 경우 발생합니다. 이 경우 프록시가 HTTP로 Nginx에 요청을 전달하더라도, 원래 클라이언트의 요청이 HTTPS였다면 리다이렉트를 건너뛰어야 합니다.
X-Forwarded-Proto 헤더를 확인하는 방법을 사용할 수 있습니다.
server {
listen 80;
server_name example.com;
if ($http_x_forwarded_proto != 'https') {
return 301 https://$host$request_uri;
}
}
인증서 경로 오류
SSL 인증서 파일 경로가 잘못 지정되어 Nginx가 시작되지 않는 경우가 있습니다. nginx -t 명령으로 오류 메시지를 확인하고, 실제 인증서 파일이 해당 경로에 존재하는지 확인합니다.
Mixed Content 경고
HTTPS 페이지 내에서 HTTP 리소스(이미지, 스크립트, 스타일시트 등)를 불러오는 경우 브라우저가 Mixed Content 경고를 표시합니다. 이것은 Nginx 설정 문제가 아니라 웹 애플리케이션 또는 HTML 코드 수준에서 해결해야 합니다. 모든 리소스 URL을 HTTPS 또는 프로토콜 상대 URL(//example.com/style.css)로 변경해야 합니다.
HSTS 설정으로 보안 강화하기
HTTPS 리다이렉트를 설정했다면 HSTS(HTTP Strict Transport Security)도 함께 적용하는 것을 고려할 수 있습니다. HSTS는 브라우저에게 이 사이트는 항상 HTTPS로만 접속해야 한다고 알려주는 보안 헤더입니다. 한 번 설정되면 브라우저는 지정된 기간 동안 HTTP로의 접속 시도를 직접 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;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 나머지 설정
}
max-age는 초 단위로 지정하며, 31536000은 1년에 해당합니다. includeSubDomains를 추가하면 모든 서브도메인에도 동일한 정책이 적용됩니다.
단, HSTS를 한 번 적용하면 max-age 기간 동안 HTTP 접속이 완전히 차단되므로, 설정 전에 HTTPS 환경이 완전히 안정적으로 동작하는지 충분히 검증해야 합니다.
리다이렉트 동작 확인하기
설정 후에는 실제로 리다이렉트가 제대로 동작하는지 확인하는 것이 중요합니다. 터미널에서 curl 명령을 사용하면 간단하게 확인할 수 있습니다.
curl -I http://example.com
응답 헤더에서 HTTP/1.1 301 Moved Permanently와 Location: https://example.com/ 항목이 보이면 리다이렉트가 정상 동작하는 것입니다. 브라우저 개발자 도구의 네트워크 탭을 통해서도 동일하게 확인할 수 있습니다.