From cd87d439b75ce0ab5765d578ddac534dfbfafd49 Mon Sep 17 00:00:00 2001 From: seongwon seo Date: Wed, 6 May 2026 10:14:57 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=ED=94=84=EB=A1=9C=EB=AA=A8=EC=85=98?= =?UTF-8?q?=20WebView=EC=97=90=EC=84=9C=20=EB=8F=99=EC=95=84=EB=A6=AC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=B6=88=EA=B0=80=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NAVIGATE_WEBVIEW 메시지 타입을 WebViewMessageTypes에 추가하고 useWebViewMessageHandler 훅에 onNavigateWebview 콜백을 지원하여 webview/[slug].tsx에서도 동아리 상세 화면으로 이동할 수 있도록 수정 --- app/webview/[slug].tsx | 10 ++++++++++ hooks/use-webview-message-handler.ts | 10 +++++++++- types/webview-message.types.ts | 4 +++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/webview/[slug].tsx b/app/webview/[slug].tsx index 119cc3f..7d07b0f 100644 --- a/app/webview/[slug].tsx +++ b/app/webview/[slug].tsx @@ -87,8 +87,18 @@ export default function WebViewScreen() { } }; + const handleNavigateWebview = (slug: string) => { + if (slug.startsWith('club/')) { + const clubId = slug.replace('club/', ''); + router.push({ pathname: '/club/[id]', params: { id: clubId } }); + } else { + router.push({ pathname: '/webview/[slug]', params: { slug } }); + } + }; + const { handleMessage } = useWebViewMessageHandler({ onNavigateBack: handleBack, + onNavigateWebview: handleNavigateWebview, }); if (!config && !path && !urlParam) { diff --git a/hooks/use-webview-message-handler.ts b/hooks/use-webview-message-handler.ts index dbfa87a..258edc5 100644 --- a/hooks/use-webview-message-handler.ts +++ b/hooks/use-webview-message-handler.ts @@ -4,6 +4,8 @@ import { useCallback } from 'react'; interface UseWebViewMessageHandlerOptions { // 뒤로가기 요청 시 호출 onNavigateBack?: () => void; + // 웹뷰 내 화면 이동 요청 시 호출 + onNavigateWebview?: (slug: string) => void; // 알림 구독 요청 시 호출 onSubscribe?: (clubId: string, clubName?: string) => Promise | void; // 알림 구독 해제 요청 시 호출 @@ -15,6 +17,7 @@ interface UseWebViewMessageHandlerOptions { // WebView 메시지를 처리하는 Hook export const useWebViewMessageHandler = ({ onNavigateBack, + onNavigateWebview, onSubscribe, onUnsubscribe, onShare, @@ -30,6 +33,11 @@ export const useWebViewMessageHandler = ({ case WebViewMessageTypes.NAVIGATE_BACK: onNavigateBack?.(); break; + case WebViewMessageTypes.NAVIGATE_WEBVIEW: + if (message.payload?.slug) { + onNavigateWebview?.(message.payload.slug); + } + break; case WebViewMessageTypes.NOTIFICATION_SUBSCRIBE: if (message.payload?.clubId) { onSubscribe?.(message.payload.clubId, message.payload.clubName); @@ -51,7 +59,7 @@ export const useWebViewMessageHandler = ({ } catch (error) { console.error('[WebViewHandler] 메시지 파싱 오류:', error); } - }, [onNavigateBack, onSubscribe, onUnsubscribe, onShare]); + }, [onNavigateBack, onNavigateWebview, onSubscribe, onUnsubscribe, onShare]); return { handleMessage }; }; diff --git a/types/webview-message.types.ts b/types/webview-message.types.ts index 6ffe7d9..9e48653 100644 --- a/types/webview-message.types.ts +++ b/types/webview-message.types.ts @@ -2,15 +2,17 @@ //WebView 메시지 타입 상수 export const WebViewMessageTypes = { NAVIGATE_BACK: 'NAVIGATE_BACK', + NAVIGATE_WEBVIEW: 'NAVIGATE_WEBVIEW', NOTIFICATION_SUBSCRIBE: 'NOTIFICATION_SUBSCRIBE', NOTIFICATION_UNSUBSCRIBE: 'NOTIFICATION_UNSUBSCRIBE', SHARE: 'SHARE', } as const; // WebView 메시지 Discriminated Union 타입 - + export type WebViewMessage = | { type: 'NAVIGATE_BACK' } + | { type: 'NAVIGATE_WEBVIEW'; payload: { slug: string } } | { type: 'NOTIFICATION_SUBSCRIBE'; payload: { clubId: string; clubName?: string } } | { type: 'NOTIFICATION_UNSUBSCRIBE'; payload: { clubId: string } } | { type: 'SHARE'; payload: { title: string; text: string; url: string } }; From 1ed94b84cc39251f298e1dee7fe580dced016f09 Mon Sep 17 00:00:00 2001 From: seongwon seo Date: Wed, 6 May 2026 10:36:25 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20replace=20=EB=8C=80=EC=8B=A0=20slice?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/webview/[slug].tsx | 3 ++- ui/home/home-webview-screen.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/webview/[slug].tsx b/app/webview/[slug].tsx index 7d07b0f..cd406ae 100644 --- a/app/webview/[slug].tsx +++ b/app/webview/[slug].tsx @@ -89,7 +89,8 @@ export default function WebViewScreen() { const handleNavigateWebview = (slug: string) => { if (slug.startsWith('club/')) { - const clubId = slug.replace('club/', ''); + const clubId = slug.slice('club/'.length); + if (!clubId) return; router.push({ pathname: '/club/[id]', params: { id: clubId } }); } else { router.push({ pathname: '/webview/[slug]', params: { slug } }); diff --git a/ui/home/home-webview-screen.tsx b/ui/home/home-webview-screen.tsx index 4469cf9..c6da484 100644 --- a/ui/home/home-webview-screen.tsx +++ b/ui/home/home-webview-screen.tsx @@ -68,7 +68,8 @@ export function HomeWebViewScreen({ onError }: HomeWebViewScreenProps) { case 'NAVIGATE_WEBVIEW': if (payload.slug?.startsWith('club/')) { - const clubId = payload.slug.replace('club/', ''); + const clubId = payload.slug.slice('club/'.length); + if (!clubId) break; router.push({ pathname: '/club/[id]', params: { id: clubId } }); } else if (payload.slug?.startsWith('promotions/')) { router.push({ pathname: '/webview/[slug]', params: { slug: 'promotions', path: `/${payload.slug}`, hideHeader: 'true' } });