TechFeedTechFeed
Frontend

ERR_TOO_MANY_REDIRECTS, 리다이렉트 루프, trailingSlash | 배포만 화면이 돌면?

ERR_TOO_MANY_REDIRECTS는 페이지가 없어서가 아니라 Location이 서로를 가리키다 브라우저 한도를 넘긴 줄입니다. 슬래시 왕복, HTTPS·www, 로그인 matcher, 카카오 콜백 URI. Next.js, 버셀, 한국 1인 개발자 기준. 2026년 9월 MDN 리다이렉트·Next.js trailingSlash 문서.

by

ERR_TOO_MANY_REDIRECTS는 페이지가 없어서가 아니라, 브라우저가 같은 요청을 리다이렉트끼리 주고받다가 한도를 넘긴 줄입니다. 그래서 404를 고치기 전에 누가 누구를 다시 보내는지부터 보세요.


로컬은 되고 프리뷰만 화면이 돌거나, 카카오 로그인 뒤에만 주소가 왕복하는 일, 넥스트를 혼자 배포하면 한 번은 만납니다. 중간 처리와 끝 슬래시와 보안 연결 강제 세 칸이 자주 겹칩니다. 페이지를 지워 고치려다 더 도는 경우가 많습니다.


크롬은 대략 20번이면 이 줄로 멈춥니다. 근거는 MDN 리다이렉트Next.js trailingSlash에 있습니다.


화면이 도는 건 404가 아니다

응답이 다른 주소만 가리키고, 그 주소가 다시 여기로 오는 고리입니다. 브라우저는 본문을 그리지 못하고 한도에 도달해 이 줄을 냅니다. 서버 기록에는 성공이 거의 없고 옮겨 가라는 응답만 반복됩니다. 주소창이 깜빡이면 없는 페이지가 아니라 서로 밀어내는 규칙입니다.


로컬에서 안 보이는 이유는 앞단이 없어서입니다. 버셀 HTTPS 강제, 커스텀 도메인 www, next.config 슬래시 정책이 배포에만 붙습니다. 카카오 콘솔 리다이렉트 URI와 앱이 서로 슬래시를 다르게 적어도 로그인 뒤에만 돕니다.


CORS로 막힌 줄은 콘솔에 출처가 찍히고, 루프는 주소창이 깜빡입니다. 헤더 허용은 CORS입니다. 쿠키를 동기 호출로 읽어 경고가 나는 줄은 cookies await입니다. 여기는 Location 고리만 봅니다.


네트워크 탭 | Preserve log를 켜고 첫 요청부터 Location 헤더를 나란히 보세요. /와 /index, http와 https, www와 apex가 서로 밀어내는 쌍이 대부분입니다.


두 주소가 서로를 301로 밀어내 브라우저가 ERR_TOO_MANY_REDIRECTS를 내는 개념 이미지
루프는 페이지가 없는 게 아니라 Location이 서로를 가리키는 줄이다

자주 도는 세 고리

슬래시, HTTPS, 로그인 보호 세 칸이면 원인이 갈립니다.


증상먼저 볼 곳
trailingSlash/foo 와 /foo/ 가 왕복next.config, 버셀 슬래시, canonical
HTTPS·wwwhttp↔https, apex↔www버셀 도메인 설정, 앱 redirects
로그인 미들웨어/login 과 / 가 왕복matcher, 쿠키 조건, 콜백 URL
OG·정적 파일이미지만 308skipTrailingSlashRedirect
카카오 콜백로그인 뒤에만 루프콘솔 URI와 앱 라우트 슬래시

넥스트는 끝 슬래시를 켜면 슬래시 없는 주소를 슬래시 있는 주소로 보냅니다. 앞단 배포망이 반대로 슬래시를 떼면 왕복입니다. 한국 검색 사이트에서 슬래시를 맞추려고 켠 설정이, 버셀 기본과 부딪히는 경우가 있습니다. 중간 처리의 경로 조건은 프록시 matcher 글과 자리가 겹치니, 루프면 옮겨 가기 주소부터 보고 경로 조건은 그다음입니다.


슬래시 왕복을 막는 설정 방향
// next.config.js const nextConfig = { trailingSlash: true, skipTrailingSlashRedirect: true, // 정적 PNG·OG가 308로 안 돌게 } module.exports = nextConfig // 앱 redirects 와 호스트 HTTPS 강제가 서로 반대로 가리키지 않는지 확인

로그인 보호가 로그인 페이지를 다시 보낼 때

미들웨어가 "쿠키 없으면 /login"을 하고, 로그인 페이지도 같은 보호에 걸리면 왕복입니다. matcher에서 /login, /api/auth, 콜백 경로를 빼야 합니다. 카카오 콜백이 보호 안에 있으면 인가 코드가 도착해도 다시 로그인으로 밀립니다.


쿠키 SameSite 때문에 콜백에서 세션이 안 보이면, 미들웨어는 계속 비로그인으로 봅니다. 사파리에서만 루프면 쿠키 글입니다. 루프 자체는 Location이 남고, 쿠키 속성은 SameSite에서 다룹니다.


환경 변수가 프리뷰에서 비면 콜백 URL이 프로덕션을 가리켜 또 고리가 됩니다. NEXT_PUBLIC이 클라이언트에서 비는 줄은 환경변수 글입니다. 리다이렉트 URI는 콘솔에 프리뷰 도메인까지 등록돼 있어야 합니다.


로그인 경로를 matcher에서 빼기
export const config = { matcher: [ '/((?!login|api/auth|_next/static|_next/image|favicon.ico).*)', ], } // 미들웨어 안에서 // 이미 /login 이면 다시 /login 으로 redirect 하지 말 것
  • [ ] 네트워크 탭에서 Location 쌍을 적었다
  • [ ] / 와 / 슬래시 왕복인지 봤다
  • [ ] http↔https, www↔apex인지 봤다
  • [ ] /login 이 matcher에 들어 있는지 봤다
  • [ ] 카카오 콘솔 URI와 앱 경로 슬래시를 대조했다

미들웨어가 로그인 페이지까지 보호해 서로를 리다이렉트하는 흐름 이미지
쿠키 없으면 로그인으로 보내면서 로그인 경로를 보호하면 고리가 된다

로컬은 되고 프리뷰만 돌 때

버셀 도메인 HTTPS 강제와 앱 redirects가 같은 일을 두 번 하면 고리가 납니다. 앱이 http를 https로 보내고, 플랫폼이 다시 반대로 고치는 설정은 없는지 봅니다. www를 apex로 보내는 규칙도 한곳만 맡깁니다.


OG 이미지와 favicon.ico가 308로 도는 건 본문 루프와 다릅니다. 슬래시 정책이 정적 파일까지 리다이렉트하면 네이버 수집이 실패합니다. skipTrailingSlashRedirect를 켜면 둘 다 200으로 남을 수 있습니다.


함수 시간 한도로 끊기는 줄은 FUNCTION_INVOCATION_TIMEOUT이고, 주소창이 도는 줄은 여기입니다. 502는 업스트림이 죽은 칸입니다. 루프는 업스트림이 살아 있고 헤더만 고리입니다.


보이는 것실제다음
ERR_TOO_MANY_REDIRECTS3xx 고리이 글
404없는 경로not-found 글
CORS 빨간 줄브라우저가 응답 읽기 거절CORS 글
로그인 무한 스피너콜백 쿠키 실패일 수도SameSite 글

한곳만 리다이렉트 | 플랫폼 도메인 설정과 next.config redirects와 미들웨어가 같은 규칙을 세 번 적으면 서로 반대 방향으로 밀기 쉽습니다. 슬래시·호스트·HTTPS는 한 칸만 남기세요.


실전에서 고치는 순서

Preserve log로 Location 목록을 적습니다. A→B→A면 그 쌍만 고칩니다. 슬래시면 config와 앞단을 맞추고, HTTPS면 플랫폼과 앱 중 하나를 끕니다. 로그인이면 matcher에서 콜백을 뺍니다.


curl -I로 브라우저 없이 헤더만 봐도 됩니다. 쿠키가 필요한 고리는 curl에 세션이 없어 다르게 보일 수 있으니, 로그인 루프는 브라우저 탭이 맞습니다. 시크릿 창은 확장이 끼지 않아 원인 가리기에 좋습니다.


고친 뒤에는 로컬뿐 아니라 미리보기 주소, www, 슬래시 있는 경로, 카카오 콜백까지 네 곳을 열어 보세요. 한 주소만 보면 왕복이 숨습니다. 예전에 보안 연결만 받겠다고 기억한 브라우저가 옛 규칙을 들고 있으면, 저장을 지워야 할 때도 있습니다. 그 헤더 자체는 보안 헤더 글입니다. 한국 검색 수집이 이미지를 못 가져오면 본문 루프가 아니라 정적 파일이 옮겨 가기 응답을 받은 칸을 같이 보세요.


  • [ ] Location 목록을 두 주소 쌍으로 적었다
  • [ ] trailingSlash와 앞단 슬래시 정책을 맞췄다
  • [ ] HTTPS·www 규칙을 한곳에만 남겼다
  • [ ] matcher에서 login·콜백을 뺐다
  • [ ] 프리뷰·www·슬래시·콜백 네 주소를 다시 열었다

브라우저 네트워크 탭에서 Location 헤더 왕복을 확인하는 장면 이미지
Preserve log로 첫 Location부터 적으면 고리는 두 주소로 줄어든다

참고 자료


내부 연계: CORS, 프록시 matcher, 쿠키 SameSite, NEXT_PUBLIC, 보안 헤더


인용한 동작은 2026년 9월 공개 문서 기준입니다.


자주 묻는 질문

로컬은 되는데 배포만 화면이 돕니다.

앞단 HTTPS·www·슬래시가 배포에만 붙습니다. 네트워크 탭 Location이 로컬과 다른 쌍인지 보세요. next.config와 버셀 도메인 설정이 반대로 밀고 있는 경우가 많습니다.


카카오 로그인 뒤에만 루프가 납니다.

콘솔 Redirect URI와 앱 콜백 경로의 슬래시·프로토콜이 다른지, 콜백이 로그인 보호 matcher에 들어 있는지 봅니다. 인가 코드가 도착해도 미들웨어가 다시 /login으로 밀면 고리입니다.


trailingSlash를 켰더니 이미지가 안 붙습니다.

정적 PNG가 /opengraph-image에서 /opengraph-image/로 308 됩니다. skipTrailingSlashRedirect를 같이 켜면 페이지 슬래시와 파일 200을 나눌 수 있습니다.


미들웨어를 지우면 루프가 사라집니다. 미들웨어가 잘못된 건가요?

보호 조건이 로그인 페이지까지 덮었을 가능성이 큽니다. 미들웨어 자체보다 matcher와 redirect 목표가 문제입니다. 로그인 경로와 콜백은 제외하세요.


curl은 200인데 브라우저만 돕니다.

쿠키·HSTS·확장이 브라우저에만 있습니다. 시크릿 창과 다른 브라우저로 비교하세요. 로그인 고리는 curl에 세션이 없어 200처럼 보일 수 있습니다.


www와 루트 도메인을 둘 다 열어 두어도 되나요?

한쪽을 canonical로 정하고 나머지에서만 보냅니다. 둘 다 서로를 가리키면 루프입니다. 플랫폼 설정과 앱 redirects 중 한곳만 그 일을 하세요.


ERR_TOO_MANY_REDIRECTS는 Location이 서로를 가리키는 고리입니다. 슬래시·HTTPS·로그인 matcher를 한 쌍으로 적고, 규칙을 한곳에만 남기세요. 관련 글: CORS, SameSite, matcher.


ERR_TOO_MANY_REDIRECTS리다이렉트 루프trailingSlash미들웨어카카오넥스트버셀프론트엔드로그인개발자
EXPLORE / Frontend

이어서 읽어보기

전체 토픽 둘러보기