aws ec2로 서버 배포를 완료한 상태라고 가정한 상태에서, 가비아 도메인을 구매해서 연결하고, nginx로 ssl 인증서 발급 과정을 거쳐서 https 배포를 진행할 예정이다.
먼저 가비아 도메인을 구매한다. 가격은 1년에 500-550원 정도로 저렴한 편이다.
도메인을 구매했다면 AWS의 Route53 페이지로 들어간다. 호스팅 영역이라는 메뉴로 들어가서 호스팅 영역을 생성한다.
도메인 이름에는 구매한 도메인명을 입력하면 된다. 퍼블릭 호스팅 영역으로 설정한다. 호스팅 영역을 생성하면 자동으로 레코드가 생성된다. 여기서 추가로 레코드를 또 생성해준다.
A 레코드를 생성해주는데, 여기서 레코드 이름에는 www와 같은 서브도메인이 들어간다. 값에는 EC2 인스턴스의 IP 주소를 입력해준다.
서브도메인도 추가해주고 싶다면, A 레코드를 서브도메인 없는 버전과 있는 버전으로 두개를 생성해준다. 그러면 다음과 같이 레코드 목록이 떠야한다.
먼저 활용할 값은 NS의 1,2,3,4 값이다.
my가비아에서 구메한 도메인의 네임서버 설정으로 들어간다. 네임서버 목록에서 1,2,3,4차로 구분이 되는데, 위의 NS 레코드의 값을 순서대로 입력해주는데, 끝의 마침표를 제거하고 입력해줘야 한다.
연결이 잘 되어 있는지 확인하려면 다음 명령어를 입력한다. 연결되는 데에 시간이 걸릴 수 있다.
nslookup [도메인명]
다음은 A 레코드를 생성해줘야 한다. 도메인 툴 관리에 들어가준다.
레코드 설정으로 들어가서 레코드 수정을 클릭하면 다음과 같이 레코드를 추가해준다.
호스트는 기본 도메인(@), 서브 도메인(www)을 입력해서 총 2개를 생성했다. 값에는 ip 주소를 입력해준다.
반영되는 데에 시간이 걸릴 수 있다. 해당 명령어를 입력하고, ip주소를 반환하면 제대로 연결되어 있음을 알 수 있다.
dig [도메인명] +short
sudo apt install nginx -y
-y 옵션을 추가하면 중간에 추가 공간을 요구하는 메시지에 무조건 동의를 하도록 해서 바로 설치할 수 있다.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx
해당 명령어를 입력하면, 밑에처럼 따로 이메일입력, 동의, 도메인 입력을 진행해야 한다.
Invalid email address: .
If you really want to skip this, you can run the client with
--register-unsafely-without-email but you will then be unable to receive notice
about impending expiration or revocation of your certificates or problems with
your Certbot installation that will lead to failure to renew.
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): [이메일 입력]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): [도메인 입력]
Requesting a certificate for 도메인
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/도메인/fullchain.pem
Key is saved at: /etc/letsencrypt/live/도메인/privkey.pem
This certificate expires on 2025-10-27.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for 도메인 to /etc/nginx/sites-enabled/default
Congratulations! You have successfully enabled HTTPS on https://[도메인]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
조금 번거로운 과정을 거치기 싫다면 다음과 같이 입력하면 한번에 Nginx와 Cerbot을 연동할 수 있다.
sudo certbot --nginx \
-d 도메인 \
-d 서브도메인 \
--email 이메일 \
--agree-tos \
--no-eff-email
nginx 설정은 두가지 방법이 있다. Docker를 사용하거나, ec2 서버에 직접 설치하는 방법이 있다. 여기서는 ec2 서버에 직접 설치하는 방법을 선택했다.
먼저 심볼릭 링크가 있는지 확인한다.
ls -l /etc/nginx/sites-enabled/
다음 결과를 반환하면 default로 심볼릭 링크가 존재함을 알 수 있다.
lrwxrwxrwx 1 root root 34 Jul 29 16:26 default -> /etc/nginx/sites-available/default
default는 certbot 설정 시 기본으로 생성되는 파일이다. 직접 커스텀하고 싶다면, 해당 파일을 제거하고 도메인명으로 따로 파일을 생성한다.
sudo rm /etc/nginx/sites-enabled/default
sudo vi /etc/nginx/sites-available/[도메인명]
편집기를 열어서 다음과 같이 입력한다.
# HTTP → HTTPS 리디렉션
server {
listen 80;
listen [::]:80;
server_name [도메인명] www.[도메인명];
return 301 https://$host$request_uri;
}
# HTTPS 리버스 프록시
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name [도메인명] www.[도메인명];
ssl_certificate /etc/letsencrypt/live/www.[도메인명]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.[도메인명]/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 웹소켓 사용 시 추가
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
첫 번째 블록은 http 요청을 https로 리디렉션하도록 하는 코드이다.
listen 80
; : 80 포트에서 http 요청을 수신할 경우를 말한다.
server_name [도메인명] www.[도메인명];
: 해당 도메인으로 들어온 요청만 처리하도록 한다.
return 301 https://$host$request_uri;
모든 요청을 301 Moved Permanently로 리디렉션하여 HTTPS 주소로 강제 이동하도록 한다. host는 도메인 주소, request_uri는 요청 url을 말한다. 이 주소로 접속 시, 서버에서 301 응답 코드를 보내면서 https로 접속하도록 요청한다는 의미이다.
두 번째 블록은 https 요청을 처리한다.
listen 443 ssl;
: https용 포트인 443을 열어 ssl 통신을 수신한다.
ssl_certificate /etc/letsencrypt/live/www.[도메인명]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.[도메인명]/privkey.pem;
: Let's Encrypt에서 발급한 공개 키(인증서) 와 비공개 키를 지정한다.
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
: TLS 보안 옵션들을 포함하는 설정을 추가한다.
location 블록은 실제 백엔드 서버로 프록시하는 역할을 한다.
proxy_pass http://localhost:8080;
: 현재 스프링 서버는 8080포트를 사용하고 있으므로, / 경로로 들어오는 모든 요청을 내부의 8080포트로 저장하도록 한다.
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr;
: 클라이언트의 기존 요청 정보를 백엔드로 전달해주는 헤더를 설정한다. 즉 https://[도메인] 으로 요청을 보내더라도, 스프링 8080포트인 백엔드로 요청을 전달해주는 역할을 하는 것이다.
웹소켓을 사용하는 기능이 있다면 설정을 추가해줘야 한다. 웹소켓 요청 시, 클라이어트는 다음과 같은 헤더를 보낸다.
GET /ws HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: upgrade
...
proxy_http_version 1.1;
: nginx는 기본적으로 HTTP.1.0을 사용하는데, WebSocket은 HTTP/1.1부터 지원되기 때문에, 설정해주지 않으면 웹소켓 프로토콜을 시작할 수 없다.
proxy_set_header Upgrade $http_upgrade;
: 일반 HTTP가 아닌 WebSocket으로 업그레이드를 한다는 의미이다. 즉 $http_upgrade로 업그레이드한다는 것이다. 일반 웹소켓 요청에서는 websocket이라는 값이 담긴다.
proxy_set_header Connection "upgrade";
Upgrade 헤더의 유효성을 보장하기 위한 것으로, Connection: upgrade가 같이 있어야 WebSocket 핸드셰이크가 성립한다.해당 부분이 없으면 다음과 같은 오류가 뜰 수 있다.
"Handshake failed due to invalid Upgrade header: null"
이렇게 작성을 완료했으면, 구문 오류가 없는지 확인해주고 적용한다.
sudo nginx -t
구문 오류가 없다면 Successful 메세지가 뜰 것이다.
sudo systemctl restart nginx
최종적으로 nginx를 재시작해서 적용하면, https://도메인명으로 접속이 가능해진다.