카테고리 없음

(인프라) NGINX + CORS + Reverse Proxy 완전 정리

불광동 물주먹 2025. 6. 25. 18:51

🌐 NGINX + CORS + Reverse Proxy 완전 정리

이 글은 실무 개발자와 블로그 작성을 위해, **CSR (Client Side Rendering, React 등)**과 SSR (Server Side Rendering, JSP 등) 환경에서 발생할 수 있는 CORS 문제, Reverse Proxy의 필요성, 그리고 NGINX 설정과 역할에 대해 깊게 정리한 문서입니다.


1. CORS란?

  • **CORS (Cross-Origin Resource Sharing)**는 브라우저 보안 정책 중 하나로, JS에서 API 요청 시 출처(origin)가 다르면 차단합니다.
  • 출처는 프로토콜 + 도메인 + 포트 조합이 일치해야 동일 출처로 인정됩니다.

🔹 브라우저는 어떤 기준으로 CORS를 판단하는가?

  • 오직 브라우저 주소창의 출처 기준으로 판단함
  • 서버가 내부적으로 어디에서 응답을 생성했는지 (예: NGINX냐 톰캣이냐)는 브라우저가 알 수 없음

2. JSP (SSR) vs React (CSR) 비교 + CORS 발생 여부

항목 JSP (SSR) React (CSR)
렌더링 위치 서버 (WAS, 톰캣) 브라우저 (React 실행 시 JS가 API 요청)
HTML 생성 서버가 요청 시점에 동적으로 생성 React가 build된 정적 HTML+JS로 브라우저에 전달
API 요청 서버 내부에서 처리 (같은 출처) 브라우저에서 별도 API 서버로 요청 (출처 다를 수 있음)
CORS 발생 ❌ 거의 없음 (동일 서버 내 처리) ✅ 자주 발생함 (출처가 다를 가능성 높음)

🔸 왜 JSP는 CORS가 안 나는가?

  • 브라우저는 단순히 https://myapp.com/page.jsp에 요청하고, HTML을 응답 받음
  • 이 HTML은 내부적으로 WAS가 만들든, 프론트 서버에서 받든 브라우저 기준으로는 같은 도메인에서 받은 것으로 간주
  • 단, JSP 내에서 JS로 외부 API(fetch('https://api.other.com')) 요청 시에는 CORS 발생 가능

🔸 CSR은 왜 CORS가 나는가?

  • 브라우저가 React 정적 파일을 NGINX로부터 받음 → JS가 실행되며 API 요청 발생
  • API 서버 도메인이 다르면 브라우저는 출처 다름으로 간주 → CORS 차단

3. NGINX와 프록시 관련 개념들

🔹 React 배포 환경에서 NGINX는 어떤 역할을 하나?

  • 정적 파일 (build 결과물: index.html, js, css 등)을 서빙
  • /api 등의 경로로 오는 요청을 Spring Boot API 서버로 리버스 프록시 처리
  • 브라우저 기준: 모든 요청은 https://myapp.com으로 보내므로 출처 같음 → CORS 발생 안 함

사진 출처 - sujinhope.github.io

🔹 React 개발 환경에서는?

  • React 개발 서버 (localhost:3000)
  • Spring Boot 서버 (localhost:8080)
  • 브라우저 기준: 출처 다름 → CORS 발생
  • 해결: package.jsonproxy 속성으로 프록시 설정 (Forward Proxy처럼 동작)
{
  "proxy": "http://localhost:8080"
}

4. 운영 환경에서 리버스 프록시로 CORS 회피하기

🔹 도메인 기반으로 경로 구분 규약 정의하기

프론트에서는 아래처럼 경로를 명확히 분리해서 요청:

fetch('/naver/search?query=cat')
fetch('/toss/pay')

NGINX에서는 이 요청을 실제 API 서버로 리버스 프록시:

location /naver/ {
    proxy_pass https://openapi.naver.com/;
    proxy_set_header Host openapi.naver.com;
}

location /toss/ {
    proxy_pass https://api.tosspayments.com/;
    proxy_set_header Host api.tosspayments.com;
}

🔹 proxy_pass 슬래시(/) 유무에 따른 경로 전달 차이

설정 실제 전달 경로 설명
proxy_pass https://api.com/; /naver/queryhttps://api.com/query ✅ prefix 제거됨
proxy_pass https://api.com; /naver/queryhttps://api.com/naver/query ❌ prefix 포함됨

→ 그래서 반드시 슬래시(/)를 붙여줘야 프록시 경로 앞에 붙인 /naver, /toss 등의 구분자가 API 서버로 전달되지 않음.


5. Reverse Proxy vs Forward Proxy 개념 차이

구분 Forward Proxy (개발용) Reverse Proxy (운영용)
위치 클라이언트(브라우저) 앞단 서버(NGINX 등) 앞단
역할 브라우저 대신 요청을 백엔드로 전달 클라이언트 요청을 서버에서 받아 백엔드로 전달
예시 React 개발 서버 proxy 설정 NGINX의 proxy_pass 설정
사용 목적 개발 시 CORS 회피 배포 시 출처 일치 유지, 보안, 라우팅, 성능 분산

✅ 핵심 요약

  • CORS는 브라우저 보안 정책: JS에서 요청 시 출처 다르면 차단
  • JSP는 서버가 HTML을 만들어 주므로 출처가 같고 CORS 발생 안 함
  • React는 클라이언트에서 API 서버로 요청하므로 CORS 발생 가능
  • 개발 중엔 Forward Proxy (package.json의 proxy)
  • 운영 환경에선 반드시 NGINX를 통한 Reverse Proxy로 CORS 우회
  • proxy_pass 설정 시 슬래시(/) 유무로 경로 전달 방식 달라짐 → 잘못하면 /naver 포함돼 API 깨짐