🐧 Linux, shell, web server/📗 Nginx

Nginx를 리버스 프록시로 사용해보자 (EC2 + Nginx + express)

DarrenKwonDev 2020. 6. 25. 21:20

Web Server로 Nginx를 사용하고 WAS를 node.js로 사용하는 예시는 많다.

캐싱, 로드밸런싱 등을 위해서 3-tier 구성 아키텍쳐는 이제 웹앱을 만드는데는 필수다 필수!

 

 

 

NGINX Docs | NGINX Reverse Proxy

Configure NGINX as a reverse proxy for HTTP and other protocols, with support for modifying request headers and fine-tuned buffering of responses.

docs.nginx.com

 

 

 

📗 왜 리버스 프록시를 사용해야 하는가? 

(https://uhou.tistory.com/96)

 

우선 라이언 달 선생님 께서는 "You just may be hacked when some yet-unknown buffer overflow is discovered. Not that that couldn't happen behind nginx, but somehow having a proxy in front makes me happy". 라고 하셨다.

 

리버스 프록시는 사용자가 실제 서버의 정보를 알지 못하게 가리는 보안 상의 장점이 있다고 한다. 즉, node로 돌렸을 때 당연히 포트가 80번이기 때문에 해커는 이 포트로 접근을 시도하지만 리버스 프록시를 사용하면 내부 어플리케이션이 사용하는 포트를 알 수 없게 된다는 것입니다.

 

또, 일반적인 프록시가 하는 기능들을 다 사용할 수 있습니다. 즉, 캐시, 보안 방화벽, 명화 등등을 할 수 있다는 것입니다. proxy에 대해서는 http 설명서를 일고 작성한 다음 포스트를 참고합시다.

https://darrengwon.tistory.com/215

 

II. HTTP 아키텍처 | 6. 프록시

II. HTTP 아키텍처 06 프록시 웹 프록시 서버는 클라이언트와 서버 사이의 트랜잭션을 수행하는 중개인이다. 당연히 클라이언트에게는 서버의 역할을 하고 서버에게는 클라이언트의 역할을 한다.

darrengwon.tistory.com

darrengwon.tistory.com/1229

 

Forward Proxy vs Reverse Proxy

- Proxy는 무엇인가 클라이언트와 서버 사이에 존재하는 중계기로, 클라이언트 대신 서버와 대리로 통신을 한다. 함수의 관점에서는 미들웨어인 것이 서버의 관점으로 옮겨왔다고 보면 된다. - Pro

darrengwon.tistory.com

 

 

📗 왜 Apache가 아닌 NginX인가?

 

이벤트 방식인 Nginx 는 프로세스/쓰레드 방식인 Apache 에 비해 월등한 성능을 보이는 것으로 알려져 있다. 실제로 Static 파일들 CS, JSS, html 의 경우엔 그 속도가 더욱 빠르다고 한다.

 

 

📗  EC2 + Nginx(리버스 프록시) + Express 구현해보기

 

기본적인 아이디어는, Nginx의 server block의 location block을 수정한 다음 location 블록에서 프록시 설정을 통해 현재 다른 포트에서 사용 중인 express로 연결하는 것입니다. 

 

 

1️⃣ EC2에 nginx설치 및 작성한 express 서버 돌리기

 

우선 EC2에 nginx를 설치한 후 /etc/nginx/site-available의 default 설정에 따라 80번 포트가 잘 돌아가고 있는지 테스트합니다.

클라이언트가 웹으로 접속하는 포트는 80번이기 때문에 default 설정을 바꿀 필요는 없습니다.

 

이제 동일한 EC2에 express 서버를 4000번 포트에 돌려보도록 하겠습니다. 별도의 EC2를 만들어서 서비스해도 전혀 문제 없습니다만, EC2 낭비이니깐요.

 

우선 해당 EC2에 node를 설치해보도록 합시다.

 

sudo apt-get update

sudo apt-get install build-essential

sudo apt-get curl

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -  

sudo apt-get install -y nodejs // 노드가 설치됩니다. node -v와 npm -v를 확인해보세요

sudo npm i -g npm // npm update

 

노드 설치후에는 vim으로 코드를 작성합시다. 당연히 80번 포트를 사용하면 안 되겠죠? ㅋㅋ

const express = require("express");

app = express();

app.get("/", (req, res) => {
  res.send("hello from express server");
});

app.listen(4000, (req, res) => console.log("http://localhost:4000"));

 

pm2를 사용해서 express 서버를 돌려 보았습니다.

 

 

이제 우리는 ubuntu OS를 사용 중인 가상 컴퓨터의 80번 포트에 nginx, 4000번 포트에 express가 돌아가고 있는 것입니다. 

 


2️⃣ server block 에서 proxy 설정

site-available에서 사용 중인 default에서 location 수정함으로써 80번 포트로 접근하면 4000번 포트로 이동시키는 proxy를 구현해보겠습니다. virtual host를 사용중이라면 해당 호스트의 설정을 정의한 파일을 수정하시면 됩니다.

저는 간단히 기본 server block의 location /에 proxy_pass를 다음과 같이 설정해 주었습니다.

 

조금 더 자세하게 만들 수도 있습니다.

location / { 
    // 프록시화된 요청을 위해 set_header 설정입니다.  
    // 꼭 proxy_pass만 적어도 작동은 합니다. 
    // $remote_addr은 nginx의 빌트인 변수입니다. 

      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; 
      proxy_set_header X-NginX-Proxy true; 

    // 어디로 proxy 시킬까요 
      proxy_pass http://localhost:4000/; 
      proxy_redirect off; 

    // 상호작용이 많은 웹이면 buffering을 꺼주자  
      proxy_buffering off; 
} 

 

 

 

3️⃣ 재시작 및 확인

 

service nginx restart // 재시작

sudo nginx -t // 테스트

 

이제 80번 포트로 접근해도 4000번의 express 서버로 연결되는 것을 볼 수 있습니다~ 소리질러~

 

 

4️⃣ React + express로 구성된 웹을 nginx 리버스 프록스해보자

 

CRA로 react를 구성한 뒤 곧 바로 build하고 express가 그것을 렌더하도록 해보았습니다. 여기서 중요한 것은 react-router-dom 을 활용한 뒤 세부 도메인으로 곧바로 접속이 가능해야 한다는 것입니다.

 

어... 그런데 해본 결과 그냥 됩니다. 네. 

 

express 서버를 다음과 같이 구성한 다음 프록시를 돌리면 세부 항목까지 접근할 수 있게 됩니다.

// middleware
app.use(express.static(path.join(__dirname, "front", "build")));

// route
app.get("/*", function (req, res) {
  res.sendFile(__dirname + "/front/build/index.html");
});

 

 

정리하자면,

 

클라이언트가 80번 nginx로 접근합니다. nginx는 프록시 리버스로 4000번 포트에서 작동중인 express로 연결합니다. 그리고 express를 react에서 렌더한 정적 index 파일을 /에서 렌더합니다.

 

첨언하자면,

 

AWS에서 인바운드 정책은 80번만 열어놔도 됩니다. nginx에서 프록시로 움직이는 것은 내부에서의 움직임이기 때문에 인바운드의 적용을 받지 않습니다.

 

또, 라우트에서 이거 제발 꼭! 꼭! 제거하세요. 이것 때문에 3시간이나 버렸습니다.

<Redirect from="*" to="/" />

 

 


 

참고한 블로그 

 

(https://velog.io/@pinot/AWS-Ubuntu%EB%A1%9C-nginx-reverse-proxy-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0)

 

https://junojunho.com/front-end/aws-nginx-express

 

(https://velog.io/@jakeseo_me/Node%EC%97%90%EC%84%9C-NGINX%EB%A5%BC-%EB%A6%AC%EB%B2%84%EC%8A%A4-%ED%94%84%EB%A1%9D%EC%8B%9C%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EB%B2%88%EC%97%AD)