공식 문서 밖의 실전 패턴: Next.js i18n과 MCP 무상태 전환이 동시에 바뀌는 지금

공식 문서 밖의 실전 패턴: Next.js i18n과 MCP 무상태 전환이 동시에 바뀌는 지금

App Router 다국어 라우팅의 숨겨진 함정 5가지, MCP 2026-07-28 스펙의 무상태 전환—두 변화가 동시에 가리키는 것은 '공식 문서가 멈춘 곳에서 실전 설계가 시작된다'는 사실이다.

Next.js i18n App Router MCP 무상태 next-intl MCP 2026 스펙 서버리스 MCP 다국어 라우팅 프론트엔드 에이전트
광고

공식 문서는 항상 '행복한 경로(happy path)'만 보여준다. Next.js App Router의 i18n 가이드도, MCP의 공식 스펙 문서도 마찬가지다. 문제는 그 이후—CMS를 붙이고, 실제 인프라에 올리고, 에이전트를 연결하는 순간부터 공식 문서는 침묵한다. 최근 dev.to에 올라온 두 편의 글이 그 침묵 지점을 정면으로 다룬다. 하나는 Next.js 16 App Router와 Sanity CMS로 이중언어 사이트를 직접 운영하며 겪은 5가지 실전 패턴이고, 다른 하나는 MCP의 2026-07-28 스펙이 프로토콜의 근본 구조를 어떻게 바꿨는지를 분석한 글이다. 두 글의 공통점은 하나다. 실제로 부딪혀봐야 보이는 것들을 다룬다.

Next.js i18n: 조용히 터지는 버그들

App Router 기반 다국어 구현에서 가장 먼저 충돌하는 지점은 미들웨어다. next-intl은 모든 라우트에 로케일 프리픽스를 붙이려 한다. Sanity Studio를 /admin에 마운트하면 이것이 /en/admin으로 바뀌면서 Studio가 깨진다. 해결책은 미들웨어를 끄는 게 아니라, i18n 미들웨어에 넘기기 전에 자체 로직을 먼저 실행하는 것이다. matcher 설정에서 admin/의 트레일링 슬래시 하나가 없으면 리다이렉트 자체가 발화하지 않는다는 디테일까지, 공식 문서 어디에도 없는 내용이다.

두 번째 함정은 requestLocale의 Promise화다. 이전 버전에서는 locale 파라미터를 바로 읽었지만, 현재 App Router 방식에서는 await이 필요하고, hasLocale()로 유효성 검증을 직접 해줘야 한다. 이 세 줄짜리 가드가 없으면 지원하지 않는 로케일 요청이 들어왔을 때 404 대신 500이 터진다. 세 번째는 더 근본적이다. next/link를 그대로 쓰면 로케일이 조용히 사라진다. next-intl이 제공하는 createNavigation()으로 만든 커스텀 Link를 앱 전체에서 써야 하고, 팀 작업이라면 ESLint 규칙으로 next/link 직접 임포트를 아예 막는 게 맞다.

SEO 측면에서는 hreflangx-default가 핵심이다. 이것을 빠뜨리면 크롤러가 언어를 잘못 매핑하고, 프랑스어 쿼리에 영어 페이지가 노출되는 사태가 조용히 진행된다. 실제로 해당 글의 저자는 자사 사이트에서 이 현상을 측정으로 확인했다. 마지막으로 generateStaticParams는 지원하는 모든 로케일을 반드시 포함해야 한다. 빌드 결과물의 페이지 수가 로케일 수 × 라우트 수보다 현저히 적다면, 절반은 SSR 폴백으로 처리되고 있다는 신호다. 정적 생성의 이점을 절반만 누리는 셈이다.

MCP 무상태 전환: 인프라 한 범주가 통째로 사라졌다

MCP의 2026-07-28 스펙은 프로토콜의 작동 방식을 근본부터 바꿨다. 기존 MCP는 initialize 핸드셰이크로 세션을 열고, 이후 모든 요청이 Mcp-Session-Id를 통해 특정 서버 인스턴스에 묶이는 구조였다. 이 말은 곧 로드밸런서가 스티키 라우팅을 지원해야 하고, 세션 상태를 공유하기 위한 Redis 같은 외부 저장소가 필요하며, 게이트웨이가 요청 본문을 파싱해서 어디로 보낼지 판단해야 한다는 뜻이었다. 실제로 운영해본 팀이라면 이 복잡도가 얼마나 현실적인 부담이었는지 알 것이다.

새 스펙은 이 모델을 통째로 제거했다. 핸드셰이크도, 세션 ID도, 서버가 유지해야 할 연결도 없다. 각 요청이 프로토콜 버전과 클라이언트 ID, 캐퍼빌리티를 스스로 담아 전송된다. 일반 HTTP 요청이 원래 그래야 했던 방식이다. 이 변화의 실질적 의미는 하나다. MCP 서버를 이제 진짜 서버리스나 엣지 함수로 올릴 수 있다. 요청 하나를 처리하고 사라지면 된다. 세션 상태를 기억할 이유가 없으니까. 기존에는 장기 실행 프로세스를 유지해야 한다는 요구 자체가 소규모 팀이나 개인 개발자의 MCP 서버 구축 진입장벽이었다. 무상태 전환은 그 필터를 제거한다.

세션 상태가 사라졌다고 기능이 줄어든 건 아니다. 서버가 클라이언트에게 추가 입력을 요청해야 할 때는 resultType: "input_required"를 반환하고 클라이언트가 inputResponses를 담아 재요청하는 Multi Round-Trip 패턴으로 대체된다. 라우팅은 Mcp-MethodMcp-Name HTTP 헤더를 통해 게이트웨이가 본문 파싱 없이 결정할 수 있게 됐다. 툴·프롬프트·리소스 목록에는 ttlMscacheScope가 추가돼 클라이언트가 얼마나 캐시해도 되는지를 서버가 직접 선언한다. 수십 년간 HTTP를 안정적으로 유지해온 캐싱 계약이 드디어 MCP에도 들어온 것이다.

두 변화가 동시에 가리키는 것

Next.js i18n 패턴과 MCP 무상태 전환은 표면적으로 전혀 다른 주제다. 하지만 둘 다 같은 지점을 가리킨다. 공식 문서가 다루는 '설계 의도'와 실제 운영에서 마주치는 '작동 현실' 사이의 간극이다. i18n 미들웨어의 매처 설정 하나, MCP 세션 스토어 운영의 복잡도 하나—이것들은 튜토리얼에 나오지 않지만 프로덕션을 결정하는 디테일이다.

특히 MCP 무상태 전환은 프론트엔드 에이전트 통합 관점에서 직접적인 의미를 갖는다. 세션 관리 인프라 없이도 MCP 서버를 붙일 수 있다는 건, Next.js API Route나 Vercel Edge Function으로 MCP 엔드포인트를 구현하는 진입장벽이 사라졌다는 뜻이다. 프론트엔드 개발자가 에이전트 툴 서버를 직접 소유하고 운영하는 시나리오가 훨씬 현실적이 됐다. 월 5억 건에 달하는 MCP SDK 다운로드—연초 대비 4배—는 이 생태계가 빠르게 프로덕션 수준으로 진입하고 있다는 신호다.

지금 App Router 기반 다국어 사이트를 운영하거나 MCP 서버를 설계하고 있다면, 공식 문서 다음 챕터를 직접 써야 할 시점이다. 두 스펙 모두 공식 문서가 조용히 건너뛴 지점이 실전의 출발점이다.

출처

더 많은 AI 트렌드를 Seedora 앱에서 확인하세요