혼자 공부하는 Docker Nginx Reverse Proxy: 포트와 경로 기반 라우팅 마스터하기
오늘은 제가 며칠 밤낮으로 씨름했던 Docker와 Nginx를 이용한 Reverse Proxy 설정에 대한 꿀팁을 공유하려고 합니다. 사실 처음엔 막막했는데, 이제는 제법 자신감이 생겼어요! (뿌듯) 이 글을 통해 여러분도 Reverse Proxy의 세계에 쉽게 발을 들여놓으실 수 있도록, 제가 겪었던 시행착오와 해결 과정을 상세히 설명해 드리겠습니다. 자, 시작해볼까요?
### 1. Reverse Proxy란 무엇일까요?
먼저 Reverse Proxy의 개념을 간단히 짚고 넘어가겠습니다. Forward Proxy가 클라이언트의 외부 네트워크 접근을 중개하는 역할이라면, Reverse Proxy는 **여러 개의 내부 서버들을 외부 클라이언트에게 하나의 엔트리 포인트로 보여주는 역할**을 합니다. 마치 여러 개의 방을 가진 건물의 안내데스크 같은 거죠. 클라이언트는 데스크(Reverse Proxy)에 요청하고, 데스크는 요청에 맞는 방(내부 서버)으로 안내해줍니다. 상용 서비스 운영에 필수적인 기술이라고 생각하시면 됩니다. 웹 서버 여러 대를 운영하면서 부하 분산이나 보안 강화에 굉장히 유용하게 쓰이죠.
### 2. Docker와 Nginx를 이용한 Reverse Proxy 구현: 포트 기반 라우팅
자, 이제 본격적으로 Docker와 Nginx를 이용하여 Reverse Proxy를 구현하는 방법을 알려드리겠습니다. 저는 먼저 **포트 기반 라우팅**부터 시작했습니다. 각 내부 서버에 다른 포트를 할당하고, Nginx는 요청받은 포트에 따라 해당 서버로 요청을 전달하도록 설정하는 방식이죠.
**먼저, 아래와 같이 `docker-compose.yml` 파일을 작성합니다.**
```yaml
version: "3.9"
services:
nginx:
image: nginx:latest
ports:
- "80:80"
- "8081:8081" # 내부 서버 A의 포트
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- server_a
- server_b
server_a:
image: nginx:latest
ports:
- "8081:80" # 내부 서버 A의 포트
volumes:
- ./server_a:/usr/share/nginx/html
server_b:
image: nginx:latest
ports:
- "8082:80" # 내부 서버 B의 포트 (포트 8081을 사용하는 이유는 나중에 경로 기반 라우팅에서 설명)
volumes:
- ./server_b:/usr/share/nginx/html
```
**그리고 `nginx/nginx.conf` 파일은 다음과 같이 설정합니다.** (이 부분이 가장 중요합니다!)
```nginx
upstream backend_a {
server server_a:80;
}
upstream backend_b {
server server_b:80;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend_a;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api { # 포트 8081로 요청이 들어왔을 때 서버 A로 전달
listen 8081;
proxy_pass http://backend_a;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /blog { # 포트 8082로 요청이 들어왔을 때 서버 B로 전달
listen 8082;
proxy_pass http://backend_b;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
위 설정에서 중요한 부분은 `upstream` 블록과 `location` 블록입니다. `upstream`은 내부 서버들을 정의하고, `location`은 특정 포트로 들어오는 요청을 어떤 `upstream`으로 전달할지 지정합니다. `proxy_set_header` 지시어는 클라이언트의 IP 주소와 같은 정보를 내부 서버에 전달하는 역할을 합니다. 이 설정이 없으면 내부 서버는 클라이언트의 정보를 알 수 없게 되죠. (로그인 시스템 등을 구현할 때 중요합니다!)
**(그림1) docker-compose.yml 파일 예시 이미지 삽입**
**(그림2) nginx/nginx.conf 파일 예시 이미지 삽입**
### 3. Docker와 Nginx를 이용한 Reverse Proxy 구현: 경로 기반 라우팅
포트 기반 라우팅은 간단하지만, 서버 수가 많아지면 관리하기 어렵습니다. 그래서 저는 **경로 기반 라우팅**도 시도해봤습니다. 이 방법은 URL 경로에 따라 다른 내부 서버로 요청을 전달하는 방식입니다.
이번에는 `docker-compose.yml` 파일은 위와 동일하게 사용하고, `nginx/nginx.conf` 파일을 아래와 같이 수정합니다.
```nginx
upstream backend_a {
server server_a:80;
}
upstream backend_b {
server server_b:80;
}
server {
listen 80;
server_name localhost;
location /blog {
proxy_pass http://backend_a;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /community {
proxy_pass http://backend_b;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
이제 `/blog` 경로로 접근하면 `backend_a` (서버 A), `/community` 경로로 접근하면 `backend_b` (서버 B)로 요청이 전달됩니다. 훨씬 간결하고 관리하기 쉽죠?
**(그림3) 수정된 nginx/nginx.conf 파일 예시 이미지 삽입**
### 4. 경로 재작성 (Rewrite)을 이용한 고급 라우팅
더 나아가, 기존 서비스에 새로운 서버를 추가할 때, 내부 서버의 경로 구조를 변경하지 않고 Reverse Proxy에서 경로만 변경하여 라우팅하는 방법도 있습니다. 이를 위해 `rewrite` 지시어를 사용할 수 있습니다.
예를 들어, 클라이언트가 `/blog/test.html`로 요청했을 때, 실제로는 `/test.html`로 내부 서버에 요청을 전달하고 싶다면, 아래와 같이 설정할 수 있습니다.
```nginx
server {
listen 80;
server_name localhost;
location / {
rewrite ^/blog(.*) $1 break;
proxy_pass http://backend_a;
# ... (기존 proxy_set_header 설정) ...
}
# ... (기타 location 설정) ...
}
```
`rewrite ^/blog(.*) $1 break;` 라인은 `/blog`로 시작하는 모든 요청을 `/blog` 접두어를 제거한 후 내부 서버로 전달하도록 설정합니다. `break`는 다른 `location`으로의 무한 루프를 방지합니다.
**(그림4) rewrite 설정을 포함한 nginx/nginx.conf 파일 예시 이미지 삽입**
### 5. Nginx Location Match Tester
Nginx 설정에서 여러 개의 `location`을 사용할 때, 어떤 URL이 어떤 `location`에 매치되는지 궁금할 때가 있죠. 이럴 때 유용한 사이트가 바로 **Nginx Location Match Tester ([https://nginx.viraptor.info/](https://nginx.viraptor.info/))**입니다. 여기에 `nginx.conf` 파일의 `server` 블록을 복사해서 붙여넣으면, 다양한 URL을 입력해보고 어떤 `location`으로 요청이 전달되는지 확인할 수 있습니다. 강력 추천합니다!
이것으로 Docker와 Nginx를 이용한 Reverse Proxy 설정에 대한 제 이야기는 끝입니다. 처음에는 어려웠지만, 하나씩 설정을 따라 해보면서 Reverse Proxy의 매력에 빠져들었네요. 여러분도 이 글을 통해 Reverse Proxy 설정에 자신감을 얻으셨기를 바랍니다!
'Tech Story' 카테고리의 다른 글
[Python] System에 반복 및 예약 실행 설정 (Scheduler) (1) | 2025.05.31 |
---|---|
[Flutter] API 호출을 위해 Debugging Mode에서 인증 회피 (0) | 2025.05.31 |
[SQL] SQLiTE 장단점 (0) | 2025.05.31 |
[SQL] MongoDB 활용 (0) | 2025.05.31 |
[ Flutter / Python ] 좌표 (위도, 경도) 값으로 국내/해외 판단 (0) | 2024.01.22 |