[Next.js x NestJS] 프론트엔드와 백엔드의 도메인 분리와 BFF 설계
브라우저 직접 호출과 reverse proxy 경계 비교
브라우저 직접 호출에서 reverse proxy 경계로 바뀌며 쿠키와 Cloudflare 문제는 어떻게 분리됐는가?
변경 전에는 A-domain.com의 브라우저가 api.A-domain.com을 직접 호출했고 인증 쿠키의 저장·전달 실패를 확인했습니다. 변경 후에는 브라우저가 A-domain.com의 /bff를 호출하고 Next.js reverse proxy가 Cloudflare를 거쳐 NestJS API로 요청했습니다. 서버 요청 차단은 BFF 서버의 고정 IP를 허용해 스테이징에서 복구했습니다.
Before
브라우저의 API 직접 호출
같은 기본 도메인의 서로 다른 Origin을 직접 오가며 인증 쿠키 저장·전달 실패를 확인했습니다.
- Browser · A-domain.com
- api.A-domain.com
- NestJS API
- 직접 연결Browser · A-domain.com직접 호출 · 쿠키 저장·전달 실패 확인 ↓직접 호출 · 쿠키 저장·전달 실패 확인 →api.A-domain.com
- 직접 연결api.A-domain.comAPI 요청 ↓API 요청 →NestJS API
After
Next.js reverse proxy 이후
브라우저 Origin을 프론트엔드로 맞추고 서버 요청의 Cloudflare 허용 경계를 분리했습니다.
- Browser
- A-domain.com · /bff
- Cloudflare
- NestJS API
- 직접 연결Browser프론트 Origin으로 요청 ↓프론트 Origin으로 요청 →A-domain.com · /bff
- 직접 연결A-domain.com · /bff서버 요청 · 고정 IP 허용 ↓서버 요청 · 고정 IP 허용 →Cloudflare
- 직접 연결Cloudflare스테이징 통신 복구 ↓스테이징 통신 복구 →NestJS API
같은 기본 도메인에서도 브라우저의 호출 Origin은 달랐습니다
행사 호텔 예약·결제 플랫폼에서 프론트엔드는 A-domain.com, API는 api.A-domain.com에 배치했습니다. 두 주소는 같은 기본 도메인을 사용하지만 브라우저 기준으로는 서로 다른 Origin이었습니다.
처음에는 브라우저가 API Origin을 직접 호출했습니다. 이 구조에서 인증 쿠키가 저장되거나 다음 요청에 전달되지 않는 상황을 실제로 확인했습니다. 다만 당시 브라우저 설정과 네트워크 조건을 모두 분리해 정확한 실패 원인까지 기록한 것은 아니므로, 특정 브라우저 정책 하나를 원인으로 단정하지 않습니다.
Next.js reverse proxy로 브라우저 경계를 바꿨습니다
브라우저가 API Origin을 직접 호출하는 대신 프론트엔드의 /bff 경로를 호출하도록 바꾸고, Next.js rewrite가 NestJS API로 요청을 전달하게 했습니다. 브라우저가 보는 요청 Origin을 프론트엔드에 맞추면서 인증 쿠키와 CSRF 값을 사용하는 요청도 이 경계를 통과하도록 구성했습니다.
당시 구현은 요청을 대신 전달하는 reverse proxy가 중심이었습니다. 응답 조합, 프론트엔드 전용 데이터 가공과 별도의 권한 정책까지 갖춘 완성형 BFF를 구현했다고 확대하지 않습니다.
프록시 뒤에서는 Cloudflare 경계가 새로 드러났습니다
호출 주체가 브라우저에서 Next.js 서버로 바뀐 뒤, BFF 서버가 NestJS API로 보내는 요청이 Cloudflare 봇 차단에 걸렸습니다. 저는 이 원인을 확인하고 BFF 서버의 고정 IP를 Cloudflare 허용 규칙에 등록했습니다. 그 결과 고객사 스테이징에서 서버 요청과 인증 흐름을 다시 확인할 수 있었습니다.
이 대응은 스테이징 범위에서 확인한 결과입니다. 실제 IP와 설정값은 공개하지 않으며, 전 환경 정상화나 운영 장애 해결로 표현하지 않습니다. 이 프로젝트는 정식 운영 전에 보류됐기 때문에 운영 트래픽과 성능 결과도 없습니다.
지금의 판단은 이름보다 실제 책임을 먼저 확인하는 것입니다
당시에 별도의 대안을 체계적으로 비교한 기록은 없습니다. 브라우저 직접 호출에서 확인한 문제를 Next.js reverse proxy로 옮기고, 그 뒤의 Cloudflare 서버 요청 경계를 해결한 구현 순서가 남아 있을 뿐입니다.
현재 이 구조를 설명할 때는 “BFF를 도입했다”는 이름보다 실제로 어디까지 책임졌는지를 먼저 밝히는 편이 정확하다고 판단합니다. 이 프로젝트의 BFF 경계는 브라우저의 Origin을 맞추고 서버가 API 요청을 중계한 범위입니다. 이 사례만으로 모든 외부 API 호출에 BFF가 필수라고 일반화하지 않습니다.
인증 쿠키와 서버 요청 경계를 함께 다뤄야 하는 이 프로젝트에서는 reverse proxy가 문제를 분리하는 데 필요했습니다. 반면 응답 조합·가공이나 프론트 전용 권한까지 수행하지 않았다면, 그 기능까지 완성한 BFF처럼 설명해서는 안 됩니다.