lib/api/axios.tswithCredentials: true설정 (HttpOnly Cookie 지원)- Request Interceptor: Access Token을 Authorization 헤더에 자동 주입
- Response Interceptor: 401 에러 시 자동 토큰 갱신
- 동시성 제어:
isRefreshing플래그와failedQueue를 사용한 Race Condition 방지
lib/store/authStore.ts- Zustand를 사용한 인증 상태 관리
accessToken,isAuthenticated상태setAccessToken,logout액션- localStorage 영속화 (새로고침 시 상태 유지)
lib/api/authApi.tslogin(provider): OAuth 로그인 시작 (백엔드로 리다이렉트)reissue(): Refresh Token으로 Access Token 재발급logout(): 로그아웃 처리
app/oauth/callback/page.tsx- URL 파라미터를 읽지 않음 (토큰이 URL에 없음)
- 컴포넌트 마운트 시 즉시
reissue()호출 - 성공 시 메인 페이지로 이동, 실패 시 로그인 페이지로 이동
- React StrictMode 대응:
useRef로 중복 호출 방지
app/login/page.tsx- OAuth 로그인 버튼 제공
- 이미 로그인된 경우 메인 페이지로 리다이렉트
-
components/auth/AuthProvider.tsx- 앱 초기 로딩 시 토큰 갱신 시도 (새로고침 시 로그인 유지)
app/layout.tsx에 통합됨
-
components/auth/PrivateRoute.tsx- 인증이 필요한 페이지를 보호하는 컴포넌트
- 인증되지 않은 경우 로그인 페이지로 리다이렉트
components/header.tsx- 로그인/로그아웃 버튼 추가
- 인증 상태에 따라 버튼 표시
- 여러 요청이 동시에 401 에러를 받아도 토큰 갱신은 한 번만 실행
- 갱신 중인 요청들은 큐에 대기 후 순차 처리
- 401 에러 발생 시 자동으로
/reissue호출 - 새 Access Token으로 원래 요청 자동 재시도
AuthProvider에서 초기 로딩 시 토큰 갱신 시도- localStorage에 Access Token 저장
withCredentials: true설정으로 Refresh Token 자동 전송- XSS 공격으로부터 Refresh Token 보호
import { PrivateRoute } from '@/components/auth/PrivateRoute'
export default function ProtectedPage() {
return (
<PrivateRoute>
<div>인증이 필요한 콘텐츠</div>
</PrivateRoute>
)
}import { apiClient } from '@/lib/api/axios'
// Access Token이 자동으로 헤더에 추가됨
const response = await apiClient.get('/api/v1/some-endpoint')import { authApi } from '@/lib/api/authApi'
// 로그인
authApi.login('google')
// 로그아웃
await authApi.logout()import { authStore } from '@/lib/store/authStore'
const isAuthenticated = authStore((state) => state.isAuthenticated)
const accessToken = authStore((state) => state.accessToken).env.local 파일에 다음 변수를 설정하세요:
NEXT_PUBLIC_API_URL=http://localhost:8080기본값은 http://localhost:8080입니다.
구현된 코드는 다음 백엔드 API를 사용합니다:
POST /api/v1/auth/reissue- Access Token 재발급POST /api/v1/auth/logout- 로그아웃GET /oauth2/authorization/{provider}- OAuth 로그인 시작
- OAuth Callback URL: 백엔드에서
/oauth/callback으로 리다이렉트하도록 설정되어 있어야 합니다. - CORS 설정: 백엔드에서
withCredentials: true를 지원하도록 CORS 설정이 필요합니다. - Refresh Token: HttpOnly Cookie로 전송되므로 JavaScript에서 직접 접근할 수 없습니다.