Nginx
NGINX로 Front 배포하기
EC2 인스턴스 설정 요약
이전에 EC2 인스턴스를 생성하고 Docker를 설치하는 과정을 진행했으므로 여기에선 약 정리 정도로만 작성했다.
1
2
3
4
5
6
7
8
9
10
11
12
sudo ssh -i {keypair}.pem ubuntu@{ec2 ipv4 주소}
sudo apt-get update
sudo apt-get install docker.io -y
sudo docker login -u {github username} ghcr.io
sudo docker pull ghcr.io/haedal/cicd:latest
sudo docker images
sudo docker run --name cicd -p 8080:8080 -e hello.world="hello world" -d ghcr.io/haedal/cicd:latest
위 과정까지 완료되면 Spring Boot 서버가 8080 포트에서 실행된다.
NGINX 설치 및 테스트 페이지 확인
NGINX 설치
1
2
3
sudo apt-get update
sudo apt-get install nginx
sudo nginx -v
설치가 완료되면 기본적으로 80 포트에서 NGINX가 실행된다.
페이지 띄워보기
1
curl -X GET http://localhost
HTML 파일 위치
1
2
3
cd /
cd var/www/html
cat index.nginx-debian.html
HTML 파일 수정 및 새 파일 생성
1
2
sudo nano index.nginx-debian.html
sudo cat index.nginx-debian.html
새로운 HTML 파일을 생성
1
2
sudo nano home.html
sudo cat home.html
서버에서 작성한 rest api 주소를 넣어준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
<head>
<title>HELLO-WORLD</title>
</head>
<body>
<h2>HELLO</h2>
<h5>WORLDd</h5>
<script>
fetch('http://{ec2 ipv4 주소}:8080/hello')
.then(res => {
if (res.ok) {
return res.json();
} else {
throw new Error('Response was not OK.');
}
})
.then(data => {
document.write(data);
})
.catch(error => {
console.error(error);
});
</script>
</body>
</html>
이 상태에서는 CORS 문제가 발생할 수 있다.
NGINX 설정
Configuring NGINX and NGINX Plus as a Web Server
NGINX 설정 파일은 /etc/nginx 경로에 있다.
1
2
3
cd /
cd etc/nginx
ls
nginx.conf는 메인 설정 파일이며, conf.d 디렉토리는 추가 설정 파일을 포함하는 공간이다.
location과 proxy_pass
location은 특정 경로로 들어오는 요청을 어떻게 처리할지 정의하는 설정이다.
1
2
3
location /api {
proxy_pass http://backend_server;
}
위 설정은 /api로 시작하는 요청을 backend_server로 전달한다.
예를 들어 /api/users 요청이 들어오면 실제 백엔드에는 /users로 전달된다.
이 방식은 client에게 백엔드의 실제 구조를 노출하지 않는 장점이 있다.
CORS 문제 해결을 위한 Reverse Proxy 설정
브라우저는 서로 다른 포트나 도메인 간 요청에 대해 CORS 정책을 적용한다.
현재 구조에서는 front는 80 port, back은 8080 port이기 때문에 서로 다른 출처로 인식된다.
이를 해결하기 위해 NGINX가 중간에서 요청을 받아 백엔드로 전달하도록 설정한다.
1
2
3
4
5
6
7
8
9
10
http {
server {
listen 80;
server_name {ec2 ipv4 주소};
location /api/ {
proxy_pass http://{docker gateway 주소}:8080/;
}
}
}
Docker 기본 bridge 네트워크의 gateway 주소는 172.17.0.1이다.
컨테이너 IP는 다음 명령어로 확인할 수 있다.
1
sudo docker inspect {container name}
이 설정을 적용하면 클라이언트는 80 포트로만 요청을 보내고 실제 처리는 8080 포트의 Spring Boot가 수행한다.
Docker에서 사용 가능한 네트워크
1
sudo docker network ls
Reverse Proxy
Reverse Proxy는 클라이언트의 요청을 대신 받아 내부 서버로 전달하는 구조다.
클라이언트는 오직 NGINX와만 통신하고 실제 백엔드 서버는 외부에 직접 노출되지 않는다.
예를 들어 클라이언트가 80 포트로 요청을 보내면 NGINX가 이를 받아 8080 포트의 Spring Boot로 전달한다.
Spring Boot가 응답을 반환하면 다시 NGINX를 거쳐 클라이언트에게 전달된다.
이 방식은 보안을 강화하고 포트 노출을 최소화할 수 있으며 로드 밸런싱 확장도 가능하다.
정적 파일과 API를 함께 처리하도록 설정 수정
현재 설정에서는 /api/ 경로만 처리하고 있기 때문에 /home.html 요청 시 404 오류가 발생할 수 있다.
이를 해결하기 위해 정적 파일 경로도 추가한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
http {
server {
listen 80;
server_name {ec2 ipv4 주소};
location / {
root /var/www/html;
}
location /api/ {
proxy_pass http://{docker gateway 주소}:8080/;
}
}
}
이제 / 경로는 정적 파일을 처리하고 /api/ 경로는 백엔드로 전달된다.
home.html의 fetch 주소도 다음과 같이 수정한다.
1
fetch('http://{ec2 ipv4 주소}/api/hello')
설정 적용
1
sudo service nginx reload
reload 명령어를 사용하면 서버를 중단하지 않고 설정 변경을 반영할 수 있다.
정리
client는 NGINX에 요청을 보내고 /api/로 시작하는 요청은 내부적으로 Spring Boot로 전달된다. (front, back 분리)
EC2 보안 그룹에서 8080 포트를 외부에 열 필요가 없으며 80 포트만 열어두어도 정상 동작한다.
8080 포트는 내부적으로 proxy_pass를 통해서만 사용되기 때문이다.
Docker bridge 네트워크는 172.17.0.0/16 대역을 사용하며 각 컨테이너는 내부 IP를 할당받는다.
NGINX는 해당 gateway 주소를 통해 컨테이너 내부의 Spring Boot와 통신한다.
사용자는 도메인 주소만으로 서비스에 접근할 수 있고 내부 포트 구조는 외부에 노출되지 않는다.
REFERENCE