Nginx의 포워드 프록시와 리버스 프록시

✍🏼 작성일 2021년 07월 06일   
❗️ 참고: 이 글이 작성된 지 이미 일이 지났습니다. 시의성에 유의하세요
🖥  설명:모든 것은 무지에서 비롯되었다

이 글의 배경

폴더/파일 이름에는 콜론을 포함할 수 없기 때문에, Chrome이 포트 번호가 포함된 URL에 대해 Override 기능을 사용할 수 없다고 오해했습니다. 그래서 내부망 원격 테스트 환경의 포트가 포함된 URL을 로컬의 기본 80 포트로 변경하여 Chrome이 override할 수 있도록 하려고 했습니다. 나중에 Chrome이 실제로 포트 번호가 포함된 URL을 override할 수 있다는 것을 알게 되었는데, URL을 %3a로 디코딩하면 됩니다.

자신의 어리석음을 깨닫고 나서, 한 시간을 들여 Nginx를 사용해 포트 문제를 해결하려던 방법이 불필요한 작업이었다는 사실에 아쉬움을 느꼈습니다. 그래서 이 과정을 기록하여 제가 들인 시간이 헛되지 않도록 하고, 후배들이 같은 실수를 하지 않도록 이 글을 작성하게 되었습니다.

여기서 다루는 몇 가지 개념은 대학 때 배웠을 수도 있지만, 초보자를 위해 설명합니다.

용어 설명

포워드 프록시(Forward Proxy)

포워드 프록시는 일반적으로 클라이언트 측에서 사용됩니다. 예를 들어, VPN이 포워드 프록시에 해당합니다. 로컬 요청은 프록시 서버에 구성된 규칙에 따라 원격 서버로 전송됩니다. 물론 서버가 다른 서버의 리소스를 요청할 때도 포워드 프록시를 구성할 수 있으며, 이 경우 프록시는 서버를 위한 것입니다.

포워드 프록시의 가장 널리 알려진 예는 VPN입니다.

리버스 프록시(Reverse Proxy)

이름에서 알 수 있듯이, 위의 포워드 프록시와 반대되는 개념입니다. 이는 서버 측에서만 적용되는 개념입니다. 즉, 클라이언트의 요청이 서버에 도달하면, 서버에 구성된 리버스 프록시를 통해 요청이 분배된 후 다른 서버로 트래픽이 전달됩니다.

nginx 리버스 프록시는 서버 측에서 매우 광범위하게 사용됩니다. 예를 들어, 로드 밸런싱의 경우 5대의 서버가 있다고 가정할 때, 매번 들어오는 요청의 수를 카운트한 후 5로 나눈 나머지가 1이면 첫 번째 서버로, 2이면 두 번째 서버로 트래픽을 전달하는 전략을 사용할 수 있습니다. 또 다른 예로는 경로 재작성(path rewrite)이 있는데, 요청 경로가 xxx/yyy인 경우 이를 zzz로 재작성한 후 서버로 트래픽을 전달하는 등의 작업이 가능합니다.

제 요구사항

저는 http://baidu.com:8888``에 접근해야 하지만, http://baidu.com:80 즉 `http://baidu.com 방식으로 `http://baidu.com:8888``에 접근하고 싶습니다. 따라서 작동 원리는 VPN과 동일하며, 포워드 프록시에 해당합니다.

어려운 점

전체적으로 어려운 점은 없습니다. server.listen 80 포트를 설정하고, 경로를 매칭한 후 proxy_pass를 통해 8888 포트와 같은 올바른 경로로 요청을 전송하면 됩니다. 유일하게 조금 번거로운 점은 웹소켓(ws) 요청도 프록시를 통해 전달되어야 한다는 것입니다. 따라서 http 시작 부분에 다음과 같은 내용을 추가해야 합니다:

1
2
3
4
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

그런 다음 server.location 블록 안에 다음을 추가합니다:

1
2
3
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

물론 proxy_set_header, proxy_pass 등도 관련이 있지만, 이번 주제에서는 다루지 않습니다. 관심이 있으시면 공식 문서를 참고하세요: http://nginx.org/en/docs/http/websocket.html

아, 맞다. 깜빡할 뻔했는데, nginx 서버는 로컬의 127.0.0.1에서 실행되기 때문에 http://baidu.com``을 통해 http://baidu.com:8888``에 접근하려면 로컬의 hosts 파일을 수정하여 127.0.0.1을 baidu.com으로 지정해야 합니다:

1
127.0.0.1  www.baidu.com

어떤 분들은 왜 직접 hosts에 포트를 지정하지 않는지 궁금해할 수 있습니다. 예를 들어 다음과 같이 말이죠:

1
127.0.0.1. www.baidu.com:8888

답은 분명합니다. hosts 파일은 포트를 지원하지 않기 때문이죠~

후기

계속 프론트엔드와 도구 개발 쪽에만 몰두하다 보니 서버 쪽은 거의 다뤄본 적이 없어서, nginx에 추가 모듈을 설치하는 방법을 아직 완전히 이해하지 못했습니다. 빠르게 검색해보니 nginx와 함께 컴파일해야 하는 것 같더군요. 일반 소프트웨어처럼 플러그인을 설치하는 방식으로는 안 되는 모양입니다. 추가 모듈이 필요한 이유는 nginx가 기본적으로 HTTPS 요청을 프록시하지 않기 때문인데, 이 기능이 필요하면 별도 모듈을 설치해야 합니다.

nginx의 활용도가 매우 높아 보이니 시간 내서 제대로 공부해봐야겠네요!

- EOF -
이 글의 최초 게시: Nginx의 포워드 프록시와 리버스 프록시 - Xheldon Blog