Next.js App Router: next-intl 다국어 라우팅 무한 리다이렉트(Too many redirects) 루프 에러 해결법

Next.js App Router next-intl 다국어 적용 시 발생하는 Routing 루프 에러 해결 가이드
3초 요약: 이렇게 고치세요
  • 원인: next-intl 미들웨어의 matcher가 이미지·favicon·_next/static·API 경로까지 다국어 대상으로 오인해 계속 언어 코드를 붙여 리다이렉트함
  • 해결: middleware.tsconfig.matcher에 정적 자원·API 경로를 제외하는 정규식 패턴 추가
  • 주의: 공식 문서 예시를 그대로 복사하면 프로젝트마다 다른 정적 자원 배치 때문에 여전히 새는 경로가 남을 수 있음
matcher: ['/', '/(ko|en)/:path*', '/((?!api|_next/static|favicon.ico).*)']
↓ 왜 이런 에러가 나는지 원리 보기

Next.js App Router에 next-intl로 다국어(i18n) 라우팅을 추가한 뒤 브라우저가 무한 로딩에 빠지거나 콘솔에 'Too many redirects' 에러가 뜨는 경우가 있습니다. 원인은 미들웨어의 matcher 설정이 정적 파일이나 API 경로까지 다국어 처리 대상으로 잘못 인식하는 데 있습니다. 원인과 matcher 설정법을 정리합니다.


i18n / next-intl 라우팅 루프가 발생하는 근본적인 이유

문제의 원인은 Next.js의 미들웨어 감시 조건(matcher) 설정에 있습니다. next-intl 미들웨어는 기본적으로 접속한 유저의 브라우저 언어 환경을 파악하여 적절한 언어 코드 경로가 붙은 URL로 강제 리다이렉션(Redirect) 시키는 역할을 수행합니다. 이때 미들웨어가 이미지(.png, .webp 등), favicon, _next/static 번들 파일, 혹은 API 엔드포인트(/api/...) 요청까지 전부 '다국어 주입 대상 경로'로 오인하게 되면, 브라우저는 내부 리소스를 호출할 때마다 끊임없이 언어 코드 경로가 덧붙여진 주소로 튕겨나가게 되어 무한 리다이렉트 늪에 빠지게 됩니다.

무한 리다이렉트 발생 아키텍처

에러 발생 루프 /favicon.ico 요청 -> 미들웨어 감지 -> 언어 코드 없다고 판단 -> /ko/favicon.ico 강제 이동 -> 파일 찾지 못해 또 미들웨어 감지 -> 무한 리다이렉션 에러 폭발.
해결된 플로우 /favicon.ico 요청 -> matcher 필터링으로 미들웨어 통과 제외 -> 순수 리소스 즉시 반환 -> /ko/dashboard 등의 실제 라우트 경로만 정상 미들웨어 타겟팅.

matcher 설정 시 놓치기 쉬운 부분

공식 문서의 미들웨어 matcher 정규식을 그대로 복사해서 쓰면 배포 후 빌드가 깨지는 경우가 종종 있습니다. 프로젝트마다 커스텀하게 배치된 정적 자원(Static Assets) 구조가 제각각이라, 공식 예시의 예외 처리 범위만으로는 다 커버되지 않기 때문입니다.

따라서 무한 루프를 근본적으로 방지하기 위해서는 정적 자원(assets) 및 API 관련 매칭 경로를 미들웨어 가드 대상에서 철저하게 제외(Negation)하는 전용 정규식 패턴을 적용해야 합니다. 아래의 실전 해결 코드를 활용하여 미들웨어 규칙을 재정비해 보시기 바랍니다.


무한 루프 해결 및 빌드 성공 보장 코드

루트 경로에 위치한 middleware.ts 파일의 config.matcher를 아래 코드로 교체해 줍니다.

import createMiddleware from 'next-intl/middleware';

export default createMiddleware({
  // 1. 지원할 다국어 언어 목록 등록
  locales: ['ko', 'en'],

  // 2. 언어 코드 접두사가 없는 요청 진입 시의 기본 로케일 지정
  defaultLocale: 'ko'
});

export const config = {
  // 핵심: 미들웨어가 실행되어야 할 경로와 제외할 정적 파일 경로 세부 지정
  matcher: [
    // '/' 첫 페이지 매칭
    '/',

    // '/ko', '/en' 등의 지원 언어 라우트 매칭
    '/(ko|en)/:path*',

    // 아래에 지정된 시스템 정적 파일 및 특정 경로들은 미들웨어 검사 대상에서 제외 처리
    // (api, _next/static, _next/image, 파비콘, png, webp 등의 모든 정적 리소스 통과)
    '/((?!api|_next/static|_next/image|favicon.ico|apple-icon.png|sitemap.xml|robots.txt|.*\\..*).*)'
  ]
};

다국어 지원을 뒤늦게 붙인 프로젝트에서 공식 문서 예시의 matcher를 그대로 복사해 썼다가, sitemap.xml만 유독 404가 나는 걸 배포 후에야 알았습니다. 그 프로젝트는 sitemap을 정적 파일이 아니라 API 라우트로 생성하고 있었는데, 문서 예시의 제외 목록엔 그 경로가 없었던 게 원인이었습니다. 그 뒤로는 matcher를 그대로 복사하지 않고 프로젝트의 실제 정적 자원 목록과 대조해서 확인하는 편입니다.


요약: 다국어 라우팅 예외 처리 타겟 요약

matcher에서 제외해야 할 대상은 크게 세 가지입니다. _next/static_next/image는 Next.js 번들 파일과 최적화된 이미지 리소스이므로 제외하지 않으면 로딩 속도가 떨어집니다. /api/* Route Handler는 언어 코드 접두사가 붙으면 404가 나므로 반드시 예외 처리해야 합니다. favicon.ico, sitemap.xml, robots.txt 같은 기타 정적 파일도 도메인 루트에 그대로 노출되어야 하므로 .*\..* 패턴으로 함께 제외합니다.

추가 추천 자료 및 공식 레퍼런스

next-intl 라이브러리의 다양한 Routing 모델과 미들웨어 명세는 공식 문서에서 확인할 수 있습니다.

호마다의 웹개발 팁

참고로 matcher 패턴은 프로젝트마다 정적 자원 배치가 다르므로, 공식 예시를 그대로 복사하기보다 실제 폴더 구조에 맞게 제외 경로를 검증해보는 게 안전합니다.

댓글

이 블로그의 인기 게시물

TypeScript: Unknown vs Any 타입 차이점과 안전한 타입 가드(Type Guard)

Next.js 하이드레이션 오류 원인과 해결법 완벽 정리

Next.js App Router에서 getServerSideProps 대체 및 데이터 페칭법