
이번에는 Nginx를 사용해서 간단하게 배포한 스프링부트 서버의 리버스 프록시 설정을 해보겠다. AWS EC2 프리티어 인스턴스 두 개를 사용해서 실습하였다. 스프링부트는 ubuntu 인스턴스, Nginx는 Amazon Linux 인스턴스이다. 먼저 Nginx에 대해 알아보도록 하자

Nginx는 높은 동시 접속 처리에 특화된 비동기 이벤트 기반 구조의 웹 서버 소프트웨어다. 처음에는 웹 서버로 개발되었지만, 이후에는 리버스 프록시, 메일 프록시, 범용 TCP/UDP 프록시 등으로 활용될 수 있게 확장되었다.
Nginx는 동시 접속 처리 성능이 뛰어나며, 다양한 모듈을 통해 기능을 확장할 수 있다. 또한, Apache 웹 서버와 같이 널리 사용되며, 특히 동적 콘텐츠가 적고, 정적 콘텐츠의 전송이 많은 서비스에 효율적이다.
Nginx의 주요 특징
리버스 프록시 역할을 한다. 이를 통해 부하 분산, 보안 강화 등의 기능을 수행할 수 있다.(로드 밸런싱). 이를 통해 서버의 부하를 분산하고, 서비스의 안정성을 높일 수 있다.주요 특징은 로드 밸런싱과 리버스 프록시이다.
생성한 ubuntu 인스턴스에 접속한다. 나는 깃허브의 프로젝트를 받아와 배포할 것이다.
sudo apt-get install git
명령어로 git을 설치해주자.
cd ~/.ssh
ssh-keygen -t rsa -C {yourid}@github.com
우리는 SSH key를 사용해 깃허브 프로젝트를 불러와야 한다. 그래서 깃허브의 SSH Key를 생성해준다.
cat id_rsa.pub
생성된 공개키를 출력하고, 복사해주자. 이제 깃허브 홈페이지로 간다.
Setting -> SSH and GPG keys -> new SSH key 버튼 클릭.

복사해준 공개키를 Key에 붙여넣어준다. Title은 아무렇게나 해도 상관없다.
입력 후 Add SSH Key 클릭
Clone 할 레포지토리로 이동해 HTTPS가 아닌 SSH 주소를 복사해준다.

이제 다시 CMD창으로 가서, Git Clone을 해준다
git clone {SSH URL}
먼저 자바를 설치해준다. 나는 11로 설치하였다.
sudo apt install openjdk-11-jdk
이제 클론한 레포지토리로 이동해 빌드를 시작하자.
cd {Repository_name}
./gradlew build
빌드가 성공하면 build -> libs 디렉토리가 생긴다. 우리는 이 안의 jar 파일을 실행해 서버를 열어줘야 한다.
cd build
cd libs
ls를 입력해서 무슨 파일이 있는지 확인해보면 {Repository_name}-0.0.1-SNAPSHOT.jar 파일이 있을 것이다. 없으면 build가 잘못 된 것이다.
nohup java -jar {Repository_name}-0.0.1-SNAPSHOT.jar &
명령어로 jar파일을 실행해주자.
nohub 명령어 뒤 &를 붙이면 EC2 콘솔 접속을 끊더라도 실행파일이 계속 실행된다.
cat nohup.out
명령어로 서버 로그를 볼 수 있다. 이제 서버 배포는 끝났다.
Amazon Linux 인스턴스에 연결해준다.

sudo yum install nginx
명령어로 nginx를 설치해주자.

sudo systemctl start nginx
설치가 완료되고 실행을 해줘야 한다. 실행이 잘 되었다면 이런 페이지가 뜰 것이다. 이제 리버스 프록시 설정을 해보자.

cd /etc/nginx/conf.d
sudo vim default.conf
명령어로 conf.d로 간 다음, default.conf를 생성하고 수정해보자.
insert를 누르고 아래의 코드를 복사해서 붙여넣는다. 스프링 서버 DNS 주소에는 각자 배포한 인스턴스의 DNS 주소를 입력하면 된다. 그 후 esc -> :wq 입력후 엔터를 누르면 설정이 저장된다.
server {
listen 80;
server_name _;
location / {
proxy_pass http://{스프링 서버 DNS주소}:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
설정 변경 후 nginx를 재시작해야 적용이 된다.
sudo systemctl restart nginx
추후 ci/cd 실습을 위해 proxy_pass의 프록시주소에 파라미터를 주게 되었다.
server {
listen 80;
server_name _;
include /etc/nginx/conf.d/service-url.inc;
location / {
proxy_pass $service_url;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
service-url.inc 설정
set $service_url http://{DNS주소 OR 퍼블릭 IP주소}:8080;
하지만 이렇게 하고 nginx 서버에 접속을 하니 502 BAD GATEWAY 에러가 떴다. Nginx가 도메인 이름을 IP 주소로 변환하는 데 필요한 DNS Resolver를 찾지 못해 오류가 발생했다.
Nginx에서 도메인 이름을 사용해 프록시 패스를 설정할 경우, resolver 디렉티브를 사용해 DNS 리졸버를 명시적으로 설정해야 한다. 이는 Nginx가 도메인 이름을 IP 주소로 변환하는 데 필요한 DNS 쿼리를 수행할 수 있게 해준다.
해당 문제를 해결하기 위해 nginx.conf 파일에 다음과 같이 DNS Resolver를 설정해줘야 한다.
cd /etc/nginx
sudo vim nginx.conf
nginx.conf를 수정하자.
http {
resolver 172.31.0.2; # Amazon DNS Server
...
}
Nginx 설정에서 proxy_pass 디렉티브에 직접 IP 주소나 도메인 이름을 사용하면, Nginx는 설정 파일을 로드하는 시점에 해당 주소를 해석한다. 이 경우, Nginx가 기본적으로 사용하는 시스템 DNS 리졸버를 사용해 도메인 이름을 IP 주소로 변환한다.
그러나 proxy_pass 디렉티브에 변수를 사용하면, Nginx는 각 요청을 처리하는 시점에 도메인 이름을 IP 주소로 변환해야 한다. 이때는 Nginx 설정에 명시적으로 resolver 디렉티브를 사용해 DNS 리졸버를 설정해야 한다. 만약 resolver 디렉티브가 설정되어 있지 않다면, Nginx는 도메인 이름을 IP 주소로 변환할 수 없어 에러를 발생시킨다.
결론적으로 도메인 이름을 직접 사용하는 경우에는 별도로 resolver 디렉티브를 설정할 필요가 없지만, 변수를 사용하는 경우에는 반드시 resolver 디렉티브를 설정해야 한다.
이제 아까 들어갔던 nginx 주소로 들어가면

성공!
연결한 스프링 서버의 주소로 가게된다. 위의 welcome nginx 사이트와 주소는 같다.
다음 게시글에는 Github Webhook, Jenkins, Nginx, SpringBoot 인스턴스 2개로 블루/그린 무중단 배포에 대해 작성해보겠다.
잘못된 부분이 있으면 댓글 부탁드립니다!
스프링부트 배포 참고자료 : https://velog.io/@jonghyun3668/SpringBoot-프로젝트-EC2-배포하기