feat: 인증 낙관적 체크 proxy 추가
Co-Authored-By: Claude Opus 5
@229737f7e89725755ad33f500579f993936268b5
+++ proxy.ts
... | ... | @@ -0,0 +1,35 @@ |
| 1 | +import { NextResponse } from 'next/server'; | |
| 2 | +import type { NextRequest } from 'next/server'; | |
| 3 | +import { SESSION_COOKIE_NAME } from '@/lib/auth/session-cookie'; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * 낙관적 체크 전용 — 세션 쿠키의 "존재 여부"만 확인한다. 최종 판단(서명·만료 검증)은 | |
| 7 | + * lib/auth/dal.ts의 DAL이 담당한다 (Next.js 공식 가이드 지침: Proxy는 느린 조회·최종 | |
| 8 | + * 인가 판단에 쓰지 않는다). | |
| 9 | + * | |
| 10 | + * allowlist 방식 — `/login` 외 모든 경로는 세션 쿠키가 없으면 `/login`으로 리다이렉트한다. | |
| 11 | + * 신규 라우트를 추가해도 이 목록에 넣지 않는 한 자동으로 보호된다(fail-closed). | |
| 12 | + * | |
| 13 | + * 위조/만료 쿠키를 가진 채 `/login`에 접근하는 경우의 `/` 리다이렉트는 여기서 하지 않는다 — | |
| 14 | + * proxy(`/login`→`/`)와 DAL(`/`→`/login`)이 무한 루프를 이룰 수 있으므로, 그 방향은 | |
| 15 | + * `/login` 페이지의 `getSessionAdmin()` 검증(서명까지 확인)을 통과했을 때만 수행한다. | |
| 16 | + */ | |
| 17 | +const PUBLIC_PATHS = ['/login']; | |
| 18 | + | |
| 19 | +export function proxy(request: NextRequest) { | |
| 20 | + const { pathname } = request.nextUrl; | |
| 21 | + const isPublicPath = PUBLIC_PATHS.includes(pathname); | |
| 22 | + const hasSessionCookie = request.cookies.has(SESSION_COOKIE_NAME); | |
| 23 | + | |
| 24 | + if (!isPublicPath && !hasSessionCookie) { | |
| 25 | + return NextResponse.redirect(new URL('/login', request.url)); | |
| 26 | + } | |
| 27 | + | |
| 28 | + return NextResponse.next(); | |
| 29 | +} | |
| 30 | + | |
| 31 | +export const config = { | |
| 32 | + matcher: [ | |
| 33 | + '/((?!_next/static|_next/image|favicon\\.ico|robots\\.txt|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico)$).*)', | |
| 34 | + ], | |
| 35 | +}; |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?