- BOM 항목 추가/수정/삭제 시 섹션탭 즉시 반영 - 섹션 복제 시 UI 즉시 업데이트 (null vs undefined 이슈 해결) - 항목 수정 기능 추가 (useTemplateManagement) - 실시간 동기화 문서 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
4.6 KiB
4.6 KiB
Middleware 인증 문제 해결 보고서
📅 작성일: 2025-11-07
🔍 문제 증상
로그인하지 않은 상태에서 /dashboard에 접근 시, 인증 체크가 작동하지 않고 대시보드에 바로 접근되는 문제가 발생했습니다.
증상 상세
- ✅ 로그인/로그아웃 기능 정상 작동
- ✅ 쿠키(
user_token) 저장/삭제 정상 - ❌ Middleware에서 보호된 라우트 접근 차단 실패
- ❌ Middleware console.log가 터미널에 전혀 출력되지 않음
🐛 발견된 문제들
1. Next.js 15 + next-intl 호환성 문제
위치: next.config.ts
원인:
- Next.js 15에서 next-intl v4를 사용할 때
turbopack설정이 필수 - 이 설정이 없으면 middleware가 제대로 컴파일되지 않음
해결:
// next.config.ts
const nextConfig: NextConfig = {
turbopack: {}, // ✅ 추가
};
2. 복잡한 Matcher 정규식
위치: src/middleware.ts - config.matcher
원인:
- 너무 복잡한 regex 패턴으로 라우트 매칭 실패
- 중복된 matcher 패턴 (정규식 + 명시적 경로)
기존 코드:
matcher: [
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico)$).*)',
'/dashboard/:path*',
'/login',
'/register',
]
해결:
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico|.*\\..*|robots\\.txt).*)',
]
3. isPublicRoute 함수 로직 버그 ⭐ (핵심 문제)
위치: src/middleware.ts - isPublicRoute() 함수
원인:
// 문제 코드
function isPublicRoute(pathname: string): boolean {
return AUTH_CONFIG.publicRoutes.some(route =>
pathname === route || pathname.startsWith(route)
);
}
버그 시나리오:
AUTH_CONFIG.publicRoutes에'/'포함/dashboard.startsWith('/') →true반환- 모든 경로가 public route로 잘못 판단됨
- 인증 체크가 스킵되어 보호된 라우트 접근 가능
해결:
function isPublicRoute(pathname: string): boolean {
return AUTH_CONFIG.publicRoutes.some(route => {
// '/' 는 정확히 일치해야만 public
if (route === '/') {
return pathname === '/';
}
// 다른 라우트는 시작 일치 허용
return pathname === route || pathname.startsWith(route + '/');
});
}
수정 후 동작:
/→ public ✅/dashboard→ protected ✅/about→ public ✅/about/team→ public ✅
✅ 해결 결과
적용된 수정 사항
- ✅
next.config.ts에turbopack: {}추가 - ✅ Middleware matcher 단순화
- ✅
isPublicRoute()함수 로직 수정 - ✅ 디버깅 로그 제거 (클린 코드)
검증 결과
# 로그아웃 상태에서 /dashboard 접근 시:
[Auth Required] Redirecting to /login from /dashboard
→ 자동으로 /login 페이지로 리다이렉트 ✅
# 로그인 상태에서 /dashboard 접근 시:
[Authenticated] Mode: bearer, Path: /dashboard
→ 정상 접근 ✅
📝 교훈
1. Middleware 디버깅
- 브라우저 콘솔이 아닌 서버 터미널에서 로그 확인
console.log는 서버 사이드에서 실행되므로 터미널 출력
2. 문자열 매칭 주의
startsWith('/')같은 패턴은 모든 경로와 매칭됨- Root path(
/)는 항상 정확한 일치(===) 사용
3. Next.js 버전별 설정
- Next.js 15 + next-intl 사용 시
turbopack설정 필수 - 공식 문서 및 마이그레이션 가이드 확인 필요
🔗 관련 파일
수정된 파일
next.config.ts- turbopack 설정 추가src/middleware.ts- isPublicRoute 로직 수정, matcher 단순화
관련 설정 파일
src/lib/api/auth/auth-config.ts- 라우트 설정src/lib/api/auth/sanctum-client.ts- 인증 로직src/lib/api/auth/token-storage.ts- 토큰 관리
🎯 현재 인증 플로우
로그인
- 사용자가
/login에서 인증 정보 입력 - PHP API(
/api/v1/login)로 요청 (API Key 포함) - Bearer Token 발급 (
user_token) - localStorage 저장 + Cookie 동기화
/dashboard로 리다이렉트
보호된 라우트 접근
- Middleware에서 요청 가로채기
- Cookie에서
user_token확인 - 토큰 있음 → 통과
- 토큰 없음 →
/login으로 리다이렉트
로그아웃
- PHP API(
/api/v1/logout) 호출 - localStorage 및 Cookie 정리
/login으로 리다이렉트
📚 참고 자료
- Next.js 15 Middleware 공식 문서
- next-intl v4 마이그레이션 가이드
claudedocs/research_nextjs15_middleware_authentication_2025-11-07.md