@@ -42,6 +42,14 @@ const isTokenExpired = (token: string): boolean => {
4242let isRefreshing = false ;
4343let refreshPromise : Promise < string | null > | null = null ;
4444
45+ const getRefreshTokenUrl = ( ) : string => {
46+ if ( typeof window === 'undefined' ) {
47+ const baseUrl = process . env . NEXT_PUBLIC_BASE_URL ;
48+ return `${ baseUrl } /api/auth/refresh-token` ;
49+ }
50+ return '/api/auth/refresh-token' ;
51+ } ;
52+
4553const refreshTokenIfNeeded = async ( ) : Promise < string | null > => {
4654 if ( isRefreshing && refreshPromise ) {
4755 return refreshPromise ;
@@ -50,10 +58,33 @@ const refreshTokenIfNeeded = async (): Promise<string | null> => {
5058 isRefreshing = true ;
5159 refreshPromise = ( async ( ) => {
5260 try {
53- const response = await fetch ( '/api/auth/refresh-token' , {
61+ const refreshUrl = getRefreshTokenUrl ( ) ;
62+ const requestOptions : RequestInit = {
5463 method : 'POST' ,
5564 credentials : 'include'
56- } ) ;
65+ } ;
66+
67+ if ( typeof window === 'undefined' ) {
68+ try {
69+ const { cookies } = await import ( 'next/headers' ) ;
70+ const cookieStore = cookies ( ) ;
71+ const refreshToken = cookieStore . get ( 'Authorization-Refresh' ) ?. value ;
72+
73+ if ( ! refreshToken ) {
74+ console . error ( '서버 사이드: Refresh Token이 없습니다' ) ;
75+ return null ;
76+ }
77+
78+ requestOptions . headers = {
79+ Cookie : `Authorization-Refresh=${ refreshToken } `
80+ } ;
81+ } catch ( error ) {
82+ console . error ( '서버 사이드 쿠키 읽기 실패:' , error ) ;
83+ return null ;
84+ }
85+ }
86+
87+ const response = await fetch ( refreshUrl , requestOptions ) ;
5788
5889 if ( response . ok ) {
5990 const data = await response . json ( ) ;
@@ -105,7 +136,9 @@ export const fetchAuth = returnFetch({
105136 ] ;
106137 } ,
107138 response : async ( response , [ url , requestInit ] , fetch ) => {
108- if ( response . status === 401 ) {
139+ const isRetry = ( requestInit as any ) ?. _isRetry ;
140+
141+ if ( response . status === 401 && ! isRetry ) {
109142 const newToken = await refreshTokenIfNeeded ( ) ;
110143 if ( newToken ) {
111144 const headers = new Headers ( requestInit ?. headers ) ;
@@ -114,10 +147,16 @@ export const fetchAuth = returnFetch({
114147 const retryResponse = await fetch ( url , {
115148 ...requestInit ,
116149 headers,
117- credentials : 'include'
118- } ) ;
150+ credentials : 'include' ,
151+ _isRetry : true // 재시도 플래그 추가
152+ } as any ) ;
119153
120154 return retryResponse ;
155+ } else {
156+ if ( typeof window !== 'undefined' ) {
157+ console . error ( '세션이 만료되었습니다. 다시 로그인해주세요.' ) ;
158+ window . location . href = '/signin' ;
159+ }
121160 }
122161 }
123162
@@ -155,7 +194,9 @@ export const fetchAuthJson = returnFetchJson({
155194 ] ;
156195 } ,
157196 response : async ( response , [ url , requestInit ] , fetch ) => {
158- if ( response . status === 401 ) {
197+ const isRetry = ( requestInit as any ) ?. _isRetry ;
198+
199+ if ( response . status === 401 && ! isRetry ) {
159200 const newToken = await refreshTokenIfNeeded ( ) ;
160201 if ( newToken ) {
161202 const headers = new Headers ( requestInit ?. headers ) ;
@@ -164,10 +205,16 @@ export const fetchAuthJson = returnFetchJson({
164205 const retryResponse = await fetch ( url , {
165206 ...requestInit ,
166207 headers,
167- credentials : 'include'
168- } ) ;
208+ credentials : 'include' ,
209+ _isRetry : true
210+ } as any ) ;
169211
170212 return retryResponse ;
213+ } else {
214+ if ( typeof window !== 'undefined' ) {
215+ console . error ( '세션이 만료되었습니다. 다시 로그인해주세요.' ) ;
216+ window . location . href = '/signin' ;
217+ }
171218 }
172219 }
173220
0 commit comments