안녕하세요, 질문 글 잘 읽어봤어요.
이런 시나리오는 백엔드 아키텍처를 짜다 보면 정말 많이 부딪히는 부분이라, 궁금해하시는 게 당연해요.
Nginx를 이용해서 '특정 경로(Prefix)'로 들어오는 요청만 다른 백엔드 서버(A 서버)로 보내고, 나머지 요청은 기존 로직(예: 웹 서버 또는 다른 서비스)으로 처리하는 건, 사실 Nginx의 핵심 기능 중 하나인 location 블록과 proxy_pass 지시어를 조합해서 사용하면 아주 깔끔하게 구현할 수 있습니다.
초보자도 이해하기 쉽도록, 개념 설명부터 단계별 설정 방법, 그리고 실제 사용 시 유의사항까지 최대한 자세하게 설명해 드릴게요.
--- ###
1.
기본 개념 정리: 왜 이게 필요한가요?
우선 왜 이런 구성을 쓰는지 개념부터 잡고 가시는 게 중요해요.
우리가 보통 example.com이라는 도메인을 가지고 있다고 가정해 봅시다.
1.
/ (루트 경로): 이건 보통 웹사이트의 메인 페이지(HTML, CSS, JS 파일 같은 정적 파일이나, 첫 요청을 받는 웹 프레임워크)가 처리하는 영역이에요.
2.
/api/v2: 이 경로는 순수하게 API 호출 전용으로, 말씀하신 것처럼 별도의 백엔드 서비스(A 서버)가 전담하는 게 효율적이죠.
3.
/admin: 이건 관리자 페이지처럼 또 다른 별도의 서버(B 서버)가 처리할 수도 있고요.
이 세 가지를 하나의 Nginx 뒤에 두고, "들어온 주소(URL)가 어디까지 일치하는가?"에 따라 "어떤 서버에게 전달할지"를 라우팅 해주는 게 바로 Nginx의 역할입니다.
핵심 키워드는 location 블록입니다.
location 블록은 Nginx에게 "만약 요청 URL이 이 패턴과 일치하면, 이 블록 안에 적힌 설정을 따라라"라고 알려주는 규칙 집합이에요.
--- ###
️ 2.
핵심 지시어 조합: location + proxy_pass 말씀하신 요구사항을 구현하는 데 필요한 주요 지시어는 딱 두 가지입니다.
A.
location (위치 지정) 어떤 URL 패턴을 잡을지 지정합니다.
- 문법:
location /패턴 { ... } * 패턴 매칭: Nginx는 이 패턴을 매우 정교하게 매칭합니다.
=: 정확히 이 문자열과 일치할 때 (가장 엄격함).
^~: 정규식보다 먼저 매칭되며, 이 패턴에 걸리면 다른 정규식 검사는 무시됩니다.
(실무에서 많이 사용) * ~: 정규식으로 매칭합니다.
(가장 유연하지만, 정규식 문법을 알아야 함) * (참고: 패턴을 생략하면 기본적으로 /와 같은 기본 매칭 규칙을 따릅니다.) #### B.
proxy_pass (실제 전달) 요청을 받아 처리할 실제 백엔드 서버의 주소를 지정합니다.
- 문법:
proxy_pass http://[서버 주소]:[포트]; * 역할: Nginx가 요청을 가로채서, 지정된 주소로 마치 클라이언트가 직접 접속한 것처럼 요청을 전달해 줍니다.
--- ###
3.
단계별 설정 예시 코드 (실습용) 가장 일반적이고 안전한 시나리오를 가정하고 코드를 작성해 드릴게요.
가정 상황: 1.
example.com으로 접속하는 모든 요청이 Nginx를 거칩니다.
example.com/api/v2로 들어오는 요청만 A 서버(http://192.168.1.100:8080)로 전달해야 합니다.
3.
나머지 모든 요청 (예: /, /assets/, /images/)은 기존 웹 서버(http://127.0.0.1:80)가 처리해야 합니다.
Nginx 설정 파일 (/etc/nginx/sites-available/example.conf 등)에 추가할 내용: ```nginx server { listen 80; server_name example.com; # 1.
[특정 경로 전용] API 요청 처리 블록 (가장 먼저 검사되어야 함) # 'location /api/v2'는 'location /api/v2/' 또는 'location /api/v2' 일치 시 작동합니다.
location /api/v2/ { # A 서버로 요청을 전달합니다.
주의: URI를 그대로 전달하는 것이 핵심입니다.
proxy_pass http://192.168.1.100:8080; # 실무에서 매우 중요한 헤더 설정들 (나중에 설명) 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-Proto $scheme; } # 2.
[나머지 모든 요청] 기본 웹 서버 처리 블록 (Fallback) # 이 블록은 위에 매칭되지 않은 모든 요청을 받습니다.
location / { # 기존 웹 서버로 전달합니다.
proxy_pass http://127.0.0.1:80; # 헤더 설정은 여기에도 필요합니다.
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-Proto $scheme; } # (추가 팁: 만약 파일 요청(Static File)이 많다면, 아래처럼 별도 처리하는 게 성능상 더 좋을 수 있습니다.) # location ~* .(jpg|jpeg|png|gif|css|js)$ { # root /var/www/html/static; # expires 30d; # 캐싱 설정 예시 # } } ``` --- ### 🧐 4.
초보자가 반드시 알아야 할 실무 팁과 주의점 (
️중요
️) 여기서 멈추면 안 돼요.
실제 운영 환경에서는 이 설정 하나만으로는 부족하고, 아래의 몇 가지 디테일을 꼭 체크하셔야 합니다.
팁 1: URI 경로 처리 방식의 차이 (가장 많이 실수하는 부분) proxy_pass를 사용할 때, 백엔드 서버가 실제로 받을 URI 경로가 어떻게 처리되는지 이해해야 해요.
**Case A: location /api/v2/ 와 같이 슬래시(/)로 끝내는 경우 (권장 방식) nginx location /api/v2/ { proxy_pass http://backend_a:8080/; # 뒤에 슬래시를 붙이는 것이 중요! } 만약 클라이언트가 example.com/api/v2/users로 요청하면, Nginx는 /api/v2/를 매칭하고, 뒤의 /users 부분만 잘라서 http://backend_a:8080/users로 보내줍니다.
(Prefix 매칭 후 나머지 전달) Case B: location /api/v2 로 끝내고 슬래시가 없는 경우 (주의 필요) nginx location /api/v2 { proxy_pass http://backend_a:8080; # 뒤에 슬래시 없음 } 이 경우, Nginx는 전체 매칭된 URI를 통째로 전달하는 경향이 있어요.
즉, 클라이언트가 example.com/api/v2/users로 요청하면, A 서버는 http://backend_a:8080/api/v2/users로 받게 됩니다.
(전체 경로 유지) >
실전 가이드: 만약 A 서버가 오직 /users 같은 경로만 기대하고, /api/v2라는 접두사는 아예 모르고 있다면, Case A (location 뒤에 슬래시를 붙이고, proxy_pass 뒤에도 슬래시를 붙여서 경로를 잘라내는 방식)를 사용하는 것이 가장 안전하고 일반적입니다.
팁 2: 필수 헤더 설정 (Headering) 단순히 요청을 전달하는 것만으로는 부족합니다.
백엔드 서버(A 서버)는 "이 요청이 정말 나에게 온 건가?", "실제 클라이언트의 IP는 뭐지?" 같은 메타데이터가 필요해요.
이때 사용하는 것이 **proxy_set_header**입니다.
proxy_set_header Host $host;: 이 헤더는 백엔드 서버가 example.com으로 요청했다고 인식하게 해줍니다.
(필수) * proxy_set_header X-Real-IP $remote_addr;: 실제 요청을 보낸 클라이언트의 IP 주소를 전달합니다.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;: 프록시를 거치는 과정에서 여러 IP가 추가될 수 있으므로, 체인(Chain)을 기록해주는 것이 좋습니다.
이 헤더들을 안 넣으면, A 서버가 요청의 출처를 잘못 판단하거나, 기대했던 호스트 이름으로 요청을 처리하지 못할 수 있습니다.
팁 3: Fallback과 우선순위 (Location의 매칭 순서) Nginx는 location 블록을 처리할 때 순서가 있습니다.
가장 구체적인 매칭 (Exact Match): =으로 시작하는 것이 가장 우선순위가 높습니다.
2.
정규식 매칭: ^~ (Prefix Match)이 그 다음으로 우선순위가 높습니다.
3.
기본 매칭 (Regex): ~ (Regex Match)가 그다음입니다.
4.
나머지 (Fallback): location / 이 모든 것을 받습니다.
따라서, 가장 특수한 규칙(API 요청 등)은 반드시 location /api/v2/ { ... }처럼 가장 상단에, 그리고 가장 구체적인 패턴으로 정의해 주셔야 합니다. 그렇지 않으면 아래의 location / 규칙에 먼저 걸려서 API 요청까지도 웹 서버로 보내버릴 수 있습니다.
--- ###
최종 정리 및 추천 체크리스트 요약하자면, 질문자님이 원하시는 구조는 **"Prefix 기반의 라우팅"**이며, 구현에 필요한 핵심은 location과 proxy_pass의 조합입니다.
1.
우선순위: 가장 구체적이고 중요한 API 라우트부터 location 블록을 정의하세요.
2.
경로 분리: API 요청은 location /api/v2/ { proxy_pass http://A_SERVER/; } 형태로 분리하세요.
3.
기본 처리: 나머지 요청은 location / { proxy_pass http://WEB_SERVER/; } 형태로 처리하세요.
4.
필수 항목: proxy_set_header를 사용하여 호스트 정보와 실제 IP를 반드시 전달해 주세요.
5.
재로드: 설정 변경 후에는 sudo nginx -t로 문법 검사 후, sudo systemctl reload nginx (또는 service nginx reload)로 반드시 리로드해야 적용됩니다.
이 가이드가 개념 잡는 데 큰 도움이 되었으면 좋겠습니다.
이거 막상 설정할 때는 지시어 하나하나가 생소해서 막막할 수 있으니, 처음에는 A 서버 주소만 임시로 적어두고, '어떤 요청이 들어왔을 때, 이 블록이 실행되고, 이 헤더들이 전달되는지' 흐름만 그리면서 테스트해보시는 걸 추천드립니다.
궁금한 점 있으면 또 질문 주세요!