리팩토링 내용
인증 로직이 4개 계층(proxy · clientApi · serverApi · SSE)에 흩어져 있는데, 계층마다 같은 규칙이 조금씩 다르게 적혀 있다. 계층을 합치자는 게 아니라 각 계층이 참조하는 규칙을 한 곳으로 모으는 것이 목표다.
1. 로그인 리다이렉트 제외 목록 통합
같은 파일 안에 두 벌이 있고 내용이 다르다.
// apps/web/src/apis/client.ts:62-65 — 401 세션 만료
LOGIN || ROOT || /auth/callback/*
// apps/web/src/apis/client.ts:90-91 — 409 탈퇴 계정
LOGIN || ROOT
/auth/callback/* 가 한쪽에만 있는데 다를 이유가 없다. utils/loginRedirect.ts 로 isLoginRedirectDisabled(pathname) 하나를 만들어 양쪽이 참조하게 한다. serverApi 인터셉터도 같은 목록을 봐야 한다.
2. 토큰 폐기 함수 정리
"토큰을 버린다"는 한 가지 동작이 5곳에 각각 쓰여 있다.
| 위치 |
맥락 |
proxy.ts:211 |
refresh 실패 |
proxy.ts:232 |
세션 만료 신호 진입 |
apis/client.ts:85 |
탈퇴 계정(409) |
app/mypage/_hooks/usePostLogout.ts:20 |
로그아웃 |
app/mypage/withdraw/_hooks/useDeleteMe.ts:22 |
회원 탈퇴 |
브라우저용 clearAuthTokens() 와 프록시 응답용 purgeAuthCookies(response) 두 개로 모은다. (프록시는 NextResponse 에 Set-Cookie 를 붙여야 해서 시그니처가 다를 수밖에 없다)
3. 401 처리 주체 문서화
docs/spec/error-handling-policy.md 에 계층별 책임을 표로 정리한다. 지금은 파편적으로만 적혀 있어서, 새 코드를 어디에 붙여야 할지 판단하려면 4곳을 다 읽어야 한다.
| 계층 |
트리거 |
하는 일 |
못 하는 일 |
proxy.ts |
요청 전 |
exp 기반 통과 판정, refresh, 게스트 로그인, 쿠키 폐기 |
401 을 볼 수 없음(요청 전이라) |
apis/server.ts |
RSC 렌더 중 401 |
?action=session-expired 로 redirect |
쿠키 수정 불가 (Next 제약) |
apis/client.ts |
브라우저 401 |
refresh → 1회 재시도 → 실패 시 redirect |
— |
useNotificationSSE |
SSE 401 |
refresh 후 재연결, 연속 실패 시 중단 |
— |
여기에 "RSC 프리페치는 utils/serverPrefetch.ts 를 경유해야 redirect 가 전파된다"는 규칙도 같이 적는다.
리팩토링 이유
#461 (401 폭주) 을 고치면서 각 계층에 가드를 하나씩 더 붙였다. 개별 가드는 다 필요하지만, 규칙이 계층마다 흩어져 있다 보니 한쪽만 고치고 다른 쪽을 빠뜨리기 쉬운 구조가 됐다. 위 1번의 제외 목록 두 벌이 정확히 그 증상이다.
요청 출처가 미들웨어 · RSC · 브라우저 · SSE 로 실제로 4개이고 계층마다 권한이 다르므로(예: RSC 는 쿠키를 못 지운다) 계층 수를 줄이는 건 불가능하다. 줄일 수 있는 건 각 계층이 제각각 들고 있는 규칙의 사본이다.
동작 변경 없는 정리 작업이라 #461 검증이 끝난 뒤 착수한다.
참고
리팩토링 내용
인증 로직이 4개 계층(proxy · clientApi · serverApi · SSE)에 흩어져 있는데, 계층마다 같은 규칙이 조금씩 다르게 적혀 있다. 계층을 합치자는 게 아니라 각 계층이 참조하는 규칙을 한 곳으로 모으는 것이 목표다.
1. 로그인 리다이렉트 제외 목록 통합
같은 파일 안에 두 벌이 있고 내용이 다르다.
/auth/callback/*가 한쪽에만 있는데 다를 이유가 없다.utils/loginRedirect.ts로isLoginRedirectDisabled(pathname)하나를 만들어 양쪽이 참조하게 한다.serverApi인터셉터도 같은 목록을 봐야 한다.2. 토큰 폐기 함수 정리
"토큰을 버린다"는 한 가지 동작이 5곳에 각각 쓰여 있다.
proxy.ts:211proxy.ts:232apis/client.ts:85app/mypage/_hooks/usePostLogout.ts:20app/mypage/withdraw/_hooks/useDeleteMe.ts:22브라우저용
clearAuthTokens()와 프록시 응답용purgeAuthCookies(response)두 개로 모은다. (프록시는NextResponse에 Set-Cookie 를 붙여야 해서 시그니처가 다를 수밖에 없다)3. 401 처리 주체 문서화
docs/spec/error-handling-policy.md에 계층별 책임을 표로 정리한다. 지금은 파편적으로만 적혀 있어서, 새 코드를 어디에 붙여야 할지 판단하려면 4곳을 다 읽어야 한다.proxy.tsapis/server.ts?action=session-expired로 redirectapis/client.tsuseNotificationSSE여기에 "RSC 프리페치는
utils/serverPrefetch.ts를 경유해야 redirect 가 전파된다"는 규칙도 같이 적는다.리팩토링 이유
#461 (401 폭주) 을 고치면서 각 계층에 가드를 하나씩 더 붙였다. 개별 가드는 다 필요하지만, 규칙이 계층마다 흩어져 있다 보니 한쪽만 고치고 다른 쪽을 빠뜨리기 쉬운 구조가 됐다. 위 1번의 제외 목록 두 벌이 정확히 그 증상이다.
요청 출처가 미들웨어 · RSC · 브라우저 · SSE 로 실제로 4개이고 계층마다 권한이 다르므로(예: RSC 는 쿠키를 못 지운다) 계층 수를 줄이는 건 불가능하다. 줄일 수 있는 건 각 계층이 제각각 들고 있는 규칙의 사본이다.
동작 변경 없는 정리 작업이라 #461 검증이 끝난 뒤 착수한다.
참고
docs/spec/error-handling-policy.md,docs/spec/api-status-audit.md