Next.js 미들웨어 캐시 키 충돌 대응 플레이북: 로그인 루프를 하루 만에 멈춘 점검 순서
💡 Key Takeaways
- 미들웨어 장애는 코드 버그보다 캐시 키 설계 누락에서 시작되는 경우가 많다.
- 재현 조건을 쿠키, 헤더, 리다이렉트 체인 단위로 고정하면 원인 분리가 빨라진다.
- 핫픽스보다 롤백 기준과 관측 지표를 먼저 잠그는 쪽이 복구 속도를 높인다.
Next.js 미들웨어 캐시 키 충돌 대응 플레이북
지난주 금요일 저녁, 결제 직전 이탈률이 갑자기 올랐는데 에러 로그는 거의 없었습니다. 이상한 점은 전체 사용자가 아니라 모바일 사파리 일부 계정에서만 로그인 -> 대시보드 -> 로그인 루프가 반복된다는 제보가 몰린 겁니다. 당시 우리는 미들웨어에서 국가 코드와 실험군 쿠키를 기준으로 리다이렉트를 태우고 있었고, CDN 캐시도 함께 쓰고 있었습니다. 처음엔 인증 서버 세션 만료를 의심했지만, 동일 계정이 데스크톱 크롬에서는 정상 동작했고 모바일에서만 깨졌습니다. 이때 문제 정의를 “인증 실패”가 아니라 “요청 문맥이 다른데 같은 캐시 엔트리를 참조하는 충돌”로 바꾸자 조사 속도가 확 올라갔습니다. 실제 장애 구간에서 x-middleware-rewrite와 cache-status를 묶어 보니 국가 헤더가 바뀐 요청이 이전 실험군 응답을 재사용하고 있었습니다. 온콜 채널에서 가장 크게 도움이 됐던 결정은 기능 개발 멈추고, 리다이렉트 체인 캡처를 30분 집중으로 돌리자고 합의한 장면이었습니다.
판단 기준은 복잡하지 않게 세 가지로 고정했습니다. 첫째, 같은 URL이라도 분기 조건이 다르면 캐시 키 입력값이 모두 반영되는지 확인합니다. 우리는 pathname과 일부 쿠키만 키에 넣고 x-country를 빠뜨려 충돌을 만들고 있었습니다. 둘째, 리다이렉트 응답 자체의 캐시 정책을 분리합니다. 미들웨어가 307을 자주 반환하는 경로에 s-maxage가 길게 걸려 있으면, 짧은 실수도 대규모 루프로 번집니다. 셋째, 인증 쿠키 변경 시점과 CDN 히트 비율의 상관을 동시에 봅니다. 이 상관을 안 보면 “로그인은 성공했는데 다음 요청에서 다시 게스트 경로로 밀리는” 현상을 서버 버그로 오해하기 쉽습니다. 우리 팀은 이 세 기준을 체크리스트 상단에 올린 뒤, 장애 재현 스크립트도 헤더 세트 A/B, 쿠키 세트 A/B 네 조합으로 단순화했습니다. 그 결과 원인 파악 시간이 기존 2시간대에서 35분으로 줄었습니다. 정답은 고급 도구가 아니라, 어떤 입력값이 캐시 식별자에 포함돼야 하는지 팀이 같은 언어로 확인하는 과정이었습니다.
실행 절차는 탐지, 완화, 수정, 검증 네 단계로 운영했습니다. 탐지 단계에서는 문제가 난 경로의 응답 헤더를 원본 그대로 저장하고, 사용자 제보 시간대와 같은 리전에 한정해 로그를 추출했습니다. 완화 단계에서는 캐시 TTL을 바로 0으로 내리지 않고, 먼저 문제 경로만 no-store로 예외 처리해 정상 트래픽 영향 범위를 줄였습니다. 수정 단계에서는 미들웨어 분기 입력값을 함수로 분리해 cacheKeyInput을 코드 리뷰에서 명시적으로 보이게 했고, 국가 헤더와 실험군 쿠키가 비어 있을 때의 기본값도 고정했습니다. 검증 단계에서는 실제로 한 번 아찔한 순간이 있었습니다. 핫픽스 배포 뒤 루프는 멈췄지만 신규 세션 생성량이 급증해 인증 서버 부하가 올라간 겁니다. 여기서 롤백할지 논쟁이 있었는데, 사전에 정해 둔 기준인 “95퍼센타일 로그인 시간 1.2초 초과 10분 지속 시 롤백”을 넘지 않아 유지하기로 했습니다. 감으로 흔들지 않고 기준으로 버틴 덕분에 40분 뒤 지표가 정상화됐고, 불필요한 재배포를 피할 수 있었습니다.
운영 체크리스트는 배포 전에 반드시 짧게라도 돌려야 합니다. 미들웨어가 참조하는 헤더·쿠키 목록을 PR 본문에 표로 남기고, 캐시 키에 포함된 값과 제외된 값을 구분해 이유를 적으세요. 리다이렉트 응답에는 경로별 캐시 정책을 분리해 두고, 실험군 트래픽에는 짧은 TTL을 적용해 확산 반경을 제한하는 편이 안전합니다. 또 장애 복구 후에는 “왜 빠졌는지”를 코드가 아니라 결정 순서 관점에서 회고해야 합니다. 우리는 당시 리뷰에서 기능 요구사항만 확인하고, 캐시 식별자 변경 영향 검토를 생략했던 것이 핵심 원인이었습니다. 마지막으로 같은 유형을 다시 막으려면 통합 테스트 하나보다 합성 모니터링 시나리오가 더 효과적이었습니다. 로그인 후 3회 연속 리다이렉트가 발생하면 즉시 경보를 울리도록 설정하니, 이후 비슷한 조짐을 배포 7분 만에 잡아냈습니다. 미들웨어 장애는 자주 조용하게 시작하지만, 입력값과 캐시 정책을 운영 언어로 고정해 두면 충분히 짧은 시간 안에 제어할 수 있습니다.