🚀 Next.js + MSW: Vercel 배포 환경의 한계를 넘어서는 하이브리드 모킹 전략
·
14 views
·
5 min read
회고록
모노레포 기반의 Next.js 프로젝트에서 프런트엔드 개발의 최대 병목은 백엔드 API의 완성 유무다. 단순히 로컬 환경에 국한된 모킹을 넘어, Vercel 배포 환경에서도 운영 환경과 동일한 비즈니스 로직을 검증하기 위해 가짜 도메인(Dummy Domain) 과 서버 사이드 모킹(Server-side Mocking) 을 결합한 아키텍처를 구축하였다.
그림 1. 환경 변수(NEXT_PUBLIC_API_MODE)에 따른 모킹/리얼 API 분기 아키텍처
1. 배포 환경 이원화 및 병렬 워크플로우
인프라 비용 효율화와 개발 리드타임 단축을 위해 배포 환경을 API 모드에 따라 분리하였다. 백엔드 의존성을 제거함으로써 프런트엔드 단독 프리뷰 환경을 가동한다.
1.1 환경별 데이터 흐름 및 개발 공정
브랜치 위계
배포 대상
API 모드
워크플로우
주요 이점
main
AWS EC2
real
직렬(Serial)
상용 서비스 안정성 확보
dev / feature
Vercel
mock
병렬(Parallel)
개발 리드타임 80% 단축
1.2 병렬 개발을 통한 생산성 증빙
기존의 직렬적 구조(API 개발 완료 후 프런트엔드 착수)를 탈피하고, API 명세 확정 즉시 모킹을 통해 개발을 시작하는 Contract-Driven Development를 지향한다.
대기 시간 제거: 백엔드 배포를 기다리는 유휴 시간(Idle Time)을 실질 개발 시간으로 전환한다.
인프라 독립성: DB 및 서버 환경 구축에 소요되는 오버헤드를 배제하고 기능 구현에 집중한다.
2. 서버 사이드 모킹 활성화: instrumentation.ts 활용
Next.js App Router 환경에서는 코드 실행 주체가 클라이언트(Browser)와 서버(Node.js)로 이원화된다. 브라우저의 Service Worker는 서버 런타임에서 발생하는 요청을 가로챌 수 없으므로, Server Action이나 SSR(Server Side Rendering) 단계의 통신을 모킹하기 위해서는 별도의 서버 사이드 인프라가 필요하다.
2.1 서버 런타임 초기화: register() 후크
Next.js가 제공하는 instrumentation.ts는 서버 인스턴스가 생성되는 시점에 실행되는 진입점이다. 이를 통해 서버리스 환경이나 로컬 서버 가동 시 MSW의 setupServer를 선제적으로 구동하여 서버 환경에서의 모든 fetch 요청을 제어한다.
TYPESCRIPT
// apps/web/src/instrumentation.ts
export async function register() {
// 서버 런타임(Node.js) 환경 확인 및 모킹 모드 판별
if (process.env.NEXT_RUNTIME === 'nodejs' && process.env.NEXT_PUBLIC_API_MODE === 'mock') {
일반적인 클라이언트 사이드 모킹 방식은 서비스 워커(Service Worker)에 의존한다. 그러나 서버 액션은 서버 내부 런타임에서 직접 외부 API를 호출하기 때문에 브라우저 워커의 감시망을 벗어난다. instrumentation.ts를 통한 서버 모킹은 이러한 런타임 간의 기술적 사각지대를 해소하고, 전 환경에서 일관된 모킹 데이터를 보장하는 핵심 장치로 작용한다.
그림 2. Server Action 내부 fetch 요청의 MSW 인터셉트 시퀀스
3. Vercel 405 에러와 가짜 도메인(Dummy Domain) 전략
Vercel 배포 환경에서 맞닥뜨린 주요 기술적 과제는 경로 충돌이었다. /login 페이지가 존재하는 도메인에서 동일한 /login 경로로 POST 요청을 보낼 경우, Vercel 라우터는 이를 API가 아닌 페이지 요청으로 간주하여 405 Method Not Allowed를 반환한다.
3.1 가짜 도메인을 활용한 라우팅 우회 (Routing Bypass)
실제 백엔드 주소 체계를 유지하면서 이 충돌을 회피하기 위해 가짜 도메인(Dummy Domain) 전략을 채택하였다.
환경 변수 주입: NEXT_PUBLIC_API_URL을 http://mock.api와 같은 가짜 주소로 설정한다.
라우팅 격리: 서버에서 http://mock.api/login으로 요청 시, Next.js는 이를 내부 페이지가 아닌 외부 요청으로 판단하여 프로세스를 이관한다.
인터셉트: 실제 네트워크망으로 나가기 직전, instrumentation.ts에 의해 실행된 MSW 서버가 해당 가짜 도메인 요청을 가로채 정의된 핸들러 응답을 반환한다.
💡 트러블슈팅: 가짜 도메인 도입 전후 비교
동일한 경로(/login)를 사용할 때 발생하는 라우팅 간섭 문제를 가짜 도메인 전략으로 해결한 결과다.