동아리 프로젝트에서 배포 파트를 담당했다. 첫 도전이라 우당탕탕이지만.. 공부하고 적용한 내용을 정리하려고 한다.
☑️ 준비
1. EC2 인스턴스는 이미 설정 끝
2. 가비아에서 도메인 결제 완료
3. 개발 환경
- Java 17, Gradle
- AWS EC2 - OS : Ubuntu 22.04
🌐 도메인과 EC2 인스턴스 연결하기
Route53
AWS에서 제공하는 DNS 웹 서비스로 도메인 등록, DNS 라우팅 등이 가능하다.
1. 호스팅 영역 생성


- 도메인 이름 : 가비아에서 구매한 도메인
- 유형 : 퍼블릭 호스팅 영역으로 선택
호스팅 영역으로 생성하면 다음과 같이 NS, SOA 레코드가 생성된다. (예시를 들기 위해 임의로 쓴 도메인이다.)
더보기
기본 레코드
- NS 레코드 (NAme Server Record)
- 도메인 이름의 호스팅 영역을 관리하는 네임서버. 해당 값은 가비아 설정에 사용된다
- 이 4개를 가비아 네임 서버에 설정해 준다
- SOA 레코드 (Start of Authority Record)
- 해당 호스팅 영역의 시작 지점으로 DNS의 모든 호스팅 영역에는 단 하나의 SOA 레코드가 있다.

2. 레코드 생성
DNS 트래픽을 특정 서버나 리소스로 라우팅 하기 위해 각 도메인에 대한 DNS 레코드를 추가
- 대시보드에서 호스팅 영역을 누르면 레코드 추가를 할 수 있다. 레코드를 추가해 보자

- 레코드 이름
: subdomain 부분을 비우면 루트 도메인이 되고, www를 입력해 서브 도메인으로 등록할 수도 있다. - 레코드 유형 - A
구매한 도메인을 EC2 public ip 주소로 매핑하는 역할 - 값 부분에 EC2 public ip 주소를 입력한다.
여기까지 하면 내가 구매한 도메인을 등록하는 것까지 완료했다. 이제 HTTPS를 적용해 보자!
이 글에서 HTTPS에 대한 내용은 따로 설명하지 않고 바로 적용해 보겠다. 이를 위해 먼저 인증서를 발급받아야 한다.
🔐 SSL 인증서 발급받기
Let's Encrypt
- 무료 SSL/TLS 인증서를 쉽게 가져오고 설치할 수 있는 방법을 제공하는 인증 기관이다.
- 웹 서버에 암호화 된 HTTPS를 사용할 수 있도록 한다
- certbot이라는 소프트웨어를 제공해 사용자가 구현 가능하게 한다.
인증서 발급 방식
- 인증서를 발급받는 방식도 여러 가지가 있다고 한다.
- standalone, webroot, Nginx 플러그인 방식
- 하지만 이 프로젝트에서는 Nginx 플러그인 방식 (Nginx + Certbot)을 선택했다.
🔎 Nginx 플러그인 방식을 선택한 이유
1. 이 방식은 EC2 인스턴스를 중지할 필요 없음
- Nginx 설정만 reload 하면 중지할 필요 없이 무중단으로 적용이 가능하다.
2. Spring Boot 컨테이너 재시작 필요 없음
현재 프로젝트는
- EIP를 적용하지 않아 중지를 하면 public ip 주소가 바뀌는 상황
- 프론트엔드에서 API 테스트를 진행하고 있는 상황
이었기 때문에 선택하게 되었다.
- 해당 방식은
1. Certbot이 내가 설정한 Nginx 설정을 읽고 SSL 인증서를 발급
2. 자동으로 설정 반영
3. HTTP -> HTTPS 리다이렉트
까지를 한 번에 처리한다.
- 만약에 내가 어떤 방식을 선택했는지 확인하고 싶다면 서버에서 다음과 같이 입력해 확인 가능하다.
sudo cat /etc/letsencrypt/renewal/등록_도메인.conf
- authenticator=standalone이면 standalone 방식
- authenticator=webroot이면 webroot 방식
- authenticator=nginx면 nginx 플러그인 방식이다.
🤫 인증서 적용하기
1. Certbot Nginx 플러그인 설치 (OS : Ubuntu 22.04)
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
2. Nginx 설정
이때 $ 뒤에 변수는 Nginx가 자동으로 채워준다.
server {
listen 80;
server_name 루트도메인 서브도메인;
# Spring Boot (Docker) 컨테이너로 프록시
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
3. 정상 서비스 여부 확인
# 문법 검사
sudo nginx -t
# 재시작
sudo systemctl reload nginx
4. Certbot으로 인증서 발급 & Nginx 자동 설정
port 80번은 알아서 443번 (HTTPS)으로 리다이렉트 된다.
sudo certbot --nginx \
-d 루트도메인 \
-d 서브도메인
5. HTTPS 동작 확인
- 브라우저에서 도메인으로 접속했을 때 자동 리다이렉트
- 유효한 인증서인지 확인한다. 크롬에서 아래처럼 확인할 수 있다.

🚀 Trouble Shooting
하지만 나는 앞선 5번 단계에서 다음과 같은 오류 메시지를 받았다.
GlobalExceptionHandler → “No static resource”
{
"isSuccess":false,
"status":"INTERNAL_SERVER_ERROR",
"code":"COMMON500",
"message":"서버 내부 오류가 발생했습니다"
}
오류 원인 및 잠정적 해결
- 지금 "/" 경로로 들어오는 모든 요청이 Spring Boot로 넘어가고 있다. (당연하다. 내가 연결한 건 Spring Boot 서버니까)
- 하지만 현재 스프링 서버는 순수 API 서버의 역할만 하고 있기 때문에, 루트 컨트롤러가 없어 내부에서 500 에러를 뱉는 것이다.
너무 당연한 얘기다. 하지만 처음에 너무너무 당황했다....
- 처음에 GPT에 물어보니 nginx 설정에서 정적 파일 서빙 관련 설정을 하라 했다. 하지만
- 아직 프론트엔드 연결이 되지 않은 상황을 고려해서 이게 연결되면 해결될 것이라 판단하고 바로 프론트엔드 배포 단계로 넘어갔다. 프론트 배포에 대해서는 다음 글에서 설명하려고 한다.
공부하는 학생입니다. 지적이나 피드백은 언제든지 환영합니다 🙇♀️
'Infra' 카테고리의 다른 글
| Blue/Green 무중단 배포를 적용해 보자 (3) | 2025.08.15 |
|---|---|
| 모니터링 시스템을 구축해 보자 (2) (CloudWatch + SNS + Grafana Cloud) (1) | 2025.08.15 |
| 모니터링 시스템을 구축해 보자 (1) (CloudWatch + SNS + Grafana Cloud) (3) | 2025.08.14 |
| Vercel 배포를 커스텀 도메인과 연결해 보자 (+ api 서브 도메인) (2) | 2025.08.14 |