diff --git a/src/apis/client.ts b/src/apis/client.ts index 4fe088fd..624a0ec6 100644 --- a/src/apis/client.ts +++ b/src/apis/client.ts @@ -163,6 +163,14 @@ async function handleUnauthorized(endPoint, options, timeout); } catch { useAuthStore.getState().clearAuth(); diff --git a/src/apis/notification/index.ts b/src/apis/notification/index.ts index 41e25d49..d90d626d 100644 --- a/src/apis/notification/index.ts +++ b/src/apis/notification/index.ts @@ -1,6 +1,13 @@ import { apiClient } from '../client'; export const registerPushToken = async (token: string) => { + if (window.ReactNativeWebView) { + if (import.meta.env.DEV) { + console.log('RN WebView 환경: 웹에서 푸시 토큰 등록 생략 (네이티브가 처리)'); + } + return; + } + const response = await apiClient.post('notifications/tokens', { body: { token }, requiresAuth: true, diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 00000000..c591fa31 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,5 @@ +interface Window { + ReactNativeWebView?: { + postMessage: (message: string) => void; + }; +} diff --git a/src/pages/User/MyPage/hooks/useLogout.ts b/src/pages/User/MyPage/hooks/useLogout.ts index 2481f535..89e085ff 100644 --- a/src/pages/User/MyPage/hooks/useLogout.ts +++ b/src/pages/User/MyPage/hooks/useLogout.ts @@ -10,6 +10,13 @@ export const useLogoutMutation = () => { return useMutation({ mutationFn: logout, onSuccess: () => { + try { + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'LOGOUT' })); + } + } catch { + // 브릿지 전달 실패가 로그아웃 흐름을 중단시키지 않도록 무시 + } clearAuth(); navigate('/'); }, diff --git a/src/stores/authStore.ts b/src/stores/authStore.ts index 2a22139d..fb8b7e38 100644 --- a/src/stores/authStore.ts +++ b/src/stores/authStore.ts @@ -1,29 +1,6 @@ import { create } from 'zustand'; import { getMyInfo, refreshAccessToken } from '@/apis/auth'; import type { MyInfoResponse } from '@/apis/auth/entity'; -import { registerPushToken } from '@/apis/notification'; - -const PUSH_TOKEN_STORAGE_KEY = 'REGISTERED_PUSH_TOKEN'; -const PENDING_PUSH_TOKEN_KEY = 'PENDING_PUSH_TOKEN'; - -async function registerPushTokenIfNeeded() { - const token = localStorage.getItem(PENDING_PUSH_TOKEN_KEY); - if (!token) return; - - const lastRegisteredToken = localStorage.getItem(PUSH_TOKEN_STORAGE_KEY); - if (lastRegisteredToken === token) { - localStorage.removeItem(PENDING_PUSH_TOKEN_KEY); - return; - } - - try { - await registerPushToken(token); - localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, token); - localStorage.removeItem(PENDING_PUSH_TOKEN_KEY); - } catch (error) { - console.error('푸시 토큰 등록 실패:', error); - } -} interface AuthState { user: MyInfoResponse | null; @@ -50,14 +27,20 @@ export const useAuthStore = create((set, get) => ({ } try { - // 1. 토큰 갱신 (필수 - 이후 API 호출에 필요) const accessToken = await refreshAccessToken(); set({ accessToken }); - // 2. 사용자 정보와 푸시 토큰 등록을 병렬로 실행 - const [user] = await Promise.all([getMyInfo(), registerPushTokenIfNeeded()]); + const user = await getMyInfo(); set({ user, isAuthenticated: true, isLoading: false }); + + try { + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'LOGIN_COMPLETE', accessToken })); + } + } catch { + // 브릿지 전달 실패가 인증 성공 상태를 롤백시키지 않도록 무시 + } } catch { set({ user: null, accessToken: null, isAuthenticated: false, isLoading: false }); } @@ -71,26 +54,3 @@ export const useAuthStore = create((set, get) => ({ clearAuth: () => set({ user: null, accessToken: null, isAuthenticated: false, isLoading: false }), })); - -window.addEventListener('message', (event: MessageEvent) => { - try { - const data = JSON.parse(event.data); - if (data.type !== 'PUSH_TOKEN' || !data.token) return; - - const lastToken = localStorage.getItem(PUSH_TOKEN_STORAGE_KEY); - if (lastToken === data.token) return; - - const { accessToken } = useAuthStore.getState(); - if (!accessToken) { - // initialize() 완료 전 도착한 경우 — pending으로 저장 후 initialize()에서 처리 - localStorage.setItem(PENDING_PUSH_TOKEN_KEY, data.token); - return; - } - - registerPushToken(data.token) - .then(() => localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, data.token)) - .catch((error) => console.error('푸시 토큰 등록 실패:', error)); - } catch { - // JSON 파싱 실패 등 무시 - } -});