Nginx Reverse Proxy 란 ❓
먼저, 설정에 앞서 Nginx Reverse Proxy를 설정하는 이유에 대해 생각해보고자 한다.
Proxy 란 ❓
다른 서버에서 리소스를 찾는 클라이언트의 요청에 대한 중개자 역할을 하는 서버이다. 프록시 서버는 클라이언트와 클라이언트가 찾고 있는 데이터를 호스팅하는 실제 서버 사이에 위치한다.
Nginx Reverse Proxy 란 ❓
리버스 프록시란 클라이언트와 웹 서버 간의 중개자 역할을 하는 서버로, 클라이언트로부터의 요청을 대신 받아 웹 서버에 전달하고, 웹 서버의 응답을 클라이언트에게 전달하는 역할을 한다. 이를 통해 리버스 프록시는 웹 서버의 부하를 분산시키고, 보안을 강화하는 등 다양한 기능을 수행할 수 있다.
기본 작동 원리는 클라이언트가 Reverse Proxy에 요청을 보내면, Reverse Proxy는 요청을 웹 서버에 전달한다. 그다음, 웹 서버는 요청된 데이터를 처리한 후 응답을 보낸다. 그리고 Reverse Proxy는 웹 서버로부터 받은 응답을 클라이언트에게 전달하는 방식으로 동작한다.
Nginx Reverse Proxy의 필요성 🧐
✅ 서버 부하 분산 (Load balancing)
웹 서비스에 동시에 많은 사용자가 접속할 경우, 서버에 부하가 집중되어 성능 저하 및 서비스 중단이 발생할 수 있다. 리버스 프록시는 들어오는 요청을 여러 대의 서버로 분산시켜 각 서버의 부하를 줄이고, 서버의 가용성을 높여 안정적인 서비스 제공이 가능하도록 한다.
✅ 보안 강화
리버스 프록시는 외부에서 직접 서버에 접근하지 못하도록 하여 웹 서비스의 보안을 강화한다. 클라이언트 요청은 먼저 리버스 프록시를 거쳐 서버로 전달되며, 이 과정에서 리버스 프록시는 악성 요청 필터링, 접근 제한 등의 역할을 수행하여 서버를 보호한다.
✅ 캐싱 및 가속화
리버스 프록시는 자주 사용되는 정적 파일들(이미지, CSS, JavaScript 등)을 캐시에 저장하여 빠르게 제공할 수 있다. 이로 인해 서버의 부하를 줄이고 응답 시간을 단축시켜 웹 서비스의 성능을 향상시킬 수 있다.
리버스 프록시의 장점 🔥
1) 로드 밸런싱 : 여러 서버에 트래픽을 분산시켜 서버 부하를 줄이고 가용성을 높일 수
있다.
2) 보안 강화 : 리버스 프록시는 외부 요청을 필터링하여 보안을 강화한다.
3) 캐싱 : 정적 콘텐츠를 캐시하여 응답 시간을 개선하고 서버 부하를 줄인다.
4) 웹 서버 최적화 : 리버스 프록시를 사용하여 웹 서버의 설정 및 성능을 최적화할 수
있다.
리버스 프록시의 단점 🔥
1) 추가적인 서버 설정과 관리 : 리버스 프록시를 사용하려면 추가적인 서버 설정과
관리가 필요하다.
2) 네트워크 지연 : 리버스 프록시를 통과하는 모든 요청에 대해 약간의 네트워크 지연이
발생할 수 있다.
3) 복잡성 증가 : 리버스 프록시가 있는 아키텍처는 일부 경우에 복잡성이 증가할 수
있다.
사전 준비사항 💻
실습은 수업때 진행되는 내용을 바탕으로 진행하다 보니, 아래와 같이 사전에 진행한 내용이 있었다.
AWS 1개의 EC2에 백엔드 서버를 배포하고, 해당 EC2 퍼블릭 IP 주소에 대한 도메인을 발급 받아 놓는다. ( 인증까지 완료하면 좋다. )
➡ 설정법 참고
🦁 Nginx Reverse Proxy 설정하기
먼저 프론트 엔드의 백엔드로 호출하는 JS 코드들을 모아놓은 JS 파일에 백엔드로 요청하는 URL을 아래와 같이 발급 받은 도메인 주소/api로 변경한다.
➡ const backend = 'https://www.test.kro.kr/api';
➡ 그러면 웹페이지에서 요청이 나갈때 https://www.test.kro.kr/api/user/signup
과
같은 URL로 요청이 보내질 것이다.
다음으로, 프론트 페이지들을 만든 것을 Nginx 에 적용시켜야 된다. 그러기 위해선 예전에 이용한 FileZilla 프로그램을 사용하였다.
사용하면서 문제가 됬던 것은 작성한 HTML, CSS, JS 파일들을 모두 nginx 의 /var/www/html
폴더로 옮겨야 되는데, FileZilla에서 자꾸 전송을 실패하는 것이다.
알고보니 해당 폴더로 파일을 옮기려면 root 계정으로 우분투 서버를 연결해야 가능했다.
✅ root 계정으로 연결하는 방법
1) 일단 Putty를 이용하여 접속 후 root 권한으로 바꿔준다 : sudo su - root
2) SSH 설정 파일을 편집해 줘야 한다 : vi /etc/ssh/sshd_config
3) 설정 파일의 33번째 줄 밑에 아래와 같이 PermitRootLogin yes
를 추가해준다.
4) 그런다음 암호키를 복사한다
➡ sudo cp /home/ubuntu/.ssh/authorized_keys /root/.ssh
5) 다음으로 SSH를 재시작한다 : sudo service ssh restart
6) FileZilla에서 root 로 연결한다.
➡ 연결은 기존 방식과 동일하나 기존에는 사용자를 ubuntu
로 했다면, 이번엔
root
로 적으면 된다.
7) 연결이 성공적으로 됬다면, 리모트 사이트에서 /var/www/html
을 검색하여 해당
디렉토리에 작성한 HTML, CSS, JS 파일들을 드래그하여 옮겨주면 된다.
마지막으로 nginx 서버 설정에서 Reverse Proxy 설정 및 nginx 의 디폴트 페이지를 바꿔주면 된다.
서버 설정 파일 열기 : sudo vi /etc/nginx/sites-available/default
디폴트 페이지 설정 ( 도메인주소로 접속했을때 가장 먼저 뜨는 페이지 지정 )
➡ 44번째 줄의 index.html
글자 앞에 내가 넣어주고 싶은 페이지를 적으면 된다. 나는
index.html
을 그냥 한번 더 적어봤다.
마지막으로, Reverse Proxy 설정은 위의 그림의 박스 친 것처럼 설정해주면 된다. 코드는 아래에 있다.
그림에는 rewrite 줄에 ?$args
가 포함되어 있지만 이것은 오류가 있어 빼야된다!! 아래 코드를 사용하자❗
location /api {
rewrite ^/api(.*)$ $1 break;
proxy_pass http://localhost:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
➡ 해당 설정이 의미하는 내용은 /api
를 달고 들어오는 요청을 받아서 proxy_pass 에
지정한 url 로 /api를 빼고 보낸다는 의미이다.
➡ 이와 같이 밑으로 여러개를 더 추가할 수 있다. 예를 들어 /api 가 아닌 /test를 달고
오는 url을 처리해주기 위해서는 location /test
로 설정을 추가해주면 된다.
Reverse Proxy 설정 간에 프록시 설정이 잘 되지 않아서, 502 Bad GateWay 에러가 처음에는 계속 떴었다. 그 이유는 백엔드 서버의 주소를 http://localhost:8080
이 아닌 동일한 EC2에서 백엔드 서버를 운영하고 있으니, 해당 도메인 주소를 써보고, 퍼블릭 ip 도 써보고 했었는데, 알고보니 localhost를 그냥 쓰면 되는 거였다.
나는 localhost:8080
이 EC2 가 아닌 내 원래 컴퓨터의 로컬 IP 주소를 의미하는 것으로 착각해서 EC2의 백엔드 서버로 계속 요청을 보내야되는데로 고민을 길게 했던 것이다.
그때, EC2가 무엇일까란 생각이 들면서 결국 EC2가 가상의 컴퓨터를 만들어준다는것이 생각났다.
결국, localhost 라는 것이 어떤 시스템에서든 자기 자신을 나타내는 호스트 이름으로 웹서버를 실행하는 해당 서버 자체를 가리킨다는 것을 말하는데, EC2 인스턴스는 가상의 컴퓨터이고, 그곳에서 백엔드 서버를 실행중이라면, 이 서버에서 사용한 localhost가 EC2 인스턴스 IP 인 것이나 다름없는 것이다.
EC2 접속 종료시에도 서버를 유지하는 방법
실습을 마무리하고, 갑자기 든 생각으로 Putty 접속을 종료했을 때, 동작중인 백엔드 서버가 꺼지기 때문에, 그럼 어떻게 컴퓨터를 종료하고도 항상 서버가 유지되도록 하지? 라는 의문이 들었다. 그것을 가능하게 해주는 것이 nohup
명령어라는 것을 알았다.
nohup
명령어는 로그아웃 등과 같이 터미널과의 세션 연결이 끊기더라도, 프로세스가 계속 동작되도록 해준다.
일반적으로 터미널과의 세션 연결이 끊기게 되면, 리눅스에서는 해당 세션에서 실행된 프로세스들에게 HUP(Hang Up,끊다) 시그널을 전달하여 프로세스들이 종료되도록 한다.
이 때, nohup 명령은 “세션이 종료되더라도 계속 실행하게 하고 싶은 프로세스에는 HUP 시그널을 전달하지 않도록(No Hang Up,끊지마) 한다"는 의미이다.
사용방법은 아주 간단합니다. 프로그램 실행 명령어 앞에 nohup
만 붙여주면 된다.
➡ 기존 실행 명령어 : java -jar [jar 파일명]
➡ 백그라운에서 실행 시 : nohup java -jar [jar 파일명] &
실행하면 스프링 부트 서버가 백그라운드에서 동작하게 된다. 따라서 에러가 떠도 로그가 출력되지 않는데, 이것은 명령어를 실행한 경로에 "nohup.out" 이라는 log파일이 생성되기 때문에 해당 로그 파일을 조회하면 로그를 볼 수가 있다.
✅ 로그 확인 명령어 정리
1) 로그 조회 : cat nohup.out
2) 실시간 로그 출력 : tail -f nohup.out
3) 마지막 10줄 조회 : tail -n 10 nohup.out
4) 파일의 10번째 줄 이후 부터 출력 : tail -n +10 nohup.out
그러나, 필요 이상의 로그를 화면에 계속해서 출력하게 되면 nohup.out 파일의 용량이 매우 커지기 때문에, 디스크 공간을 낭비하게 될 수도 있다고 한다. 따라서, 꼭 필요한 로그만 출력하거나 로그를 남기는 것이 불필요한 경우 nohup.out 파일을 생성하지 않도록 하는 것이 좋을 수도 있다.
➡ nohup.out 파일 생성하지 않고 백그라운드 실행 명령어
nohup [실행파일명] 1>/dev/null 2>&1 &
// 0 : 표준 입력, 1 : 표준 출력, 2 : 표준 에러
// 1> /dev/null : 표준 출력(1)의 결과를 /dev/null(버림)으로 전달
// 2>&1 : 표준 에러(2)를 표준 출력(1)이 전달되는 곳(/dev/null)으로 동일하게 전달
➡ 표준 출력과, 표준 에러 로그를 따로 관리하고 싶을 때
nohup [실행파일] 1>[파일1] 2>[파일2] &
마지막으로, 실행한 프로세스를 종료하기 위해서는 PID 값을 찾아서 종료 시켜줘야된다.
➡ PID 찾기 ( java -jar 로 된 것 ) : ps -ef | grep [실행파일명]
➡ 프로세스 종료 : sudo kill -9 [찾은 PID 번호]
Vue 프로젝트 배포 시 nginx 설정 파일 (24. 2.10. 추가) ✍
location / {
index index.html;
try_files $uri $uri/ @rewrites;
}
location @rewrites {
rewrite ^(.+)$ /index.html last;
}
location /api {
rewrite ^/api(.*)$ $1 break;
proxy_pass http://localhost:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
rewrite
부분이라고 생각된다. /api
를 달고 오는 요청에 대한