Skip to content

Revert "Revert " [release] FE v1.1.19""#1115

Merged
seongwon030 merged 1 commit intomainfrom
revert-1112-revert-1106-develop-fe
Jan 25, 2026
Merged

Revert "Revert " [release] FE v1.1.19""#1115
seongwon030 merged 1 commit intomainfrom
revert-1112-revert-1106-develop-fe

Conversation

@oesnuj
Copy link
Member

@oesnuj oesnuj commented Jan 25, 2026

Reverts #1112

리버트를 다시 리버트...

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 기기별 반응형 헤더 제어 추가 (모바일/태블릿/데스크톱 별 표시/숨김)
    • 클럽 상세 페이지에 고정 상단 네비게이션 바 추가
    • React Native 웹뷰 공유 및 알림 구독 기능 지원
    • 기기 유형별 동적 이미지 로딩 최적화
  • Build & Performance

    • 빌드 도구를 Webpack에서Vite로 마이그레이션
    • 개발/프로덕션 빌드 성능 개선
  • Documentation

    • 프로젝트 구조 및 기능 설명 개선
    • 기여자 섹션 추가

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
moadong Ready Ready Preview, Comment Jan 25, 2026 1:40pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 25, 2026

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "**" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Webpack 기반 빌드 시스템을 Vite로 마이그레이션하고, 클럽 상세 페이지의 반응형 UI를 개선하며, WebView 메시징과 공유 기능을 추가하고, 디바이스별 조건부 렌더링이 가능한 Header 컴포넌트를 확장했습니다. 스크롤 기반 위상단 표시 및 탭 관리 기능을 구현했습니다.

Changes

구성 / 파일(들) 변경 사항 요약
빌드 설정 마이그레이션
frontend/config/vite.config.ts, frontend/config/webpack.*.ts, frontend/package.json
Webpack에서 Vite로 전환: webpack 설정 파일 3개 제거, Vite 플러그인(svgr, tsconfig-paths) 추가, 관련 의존성 교체, 빌드/미리보기/타입 체크 스크립트 추가
디바이스별 조건부 렌더링
frontend/src/components/common/Header/Header.tsx, frontend/src/pages/ApplicationFormPage/ApplicationFormPage.tsx, frontend/src/pages/ClubUnionPage/ClubUnionPage.tsx, frontend/src/pages/IntroducePage/IntroducePage.tsx
Header에 showOn/hideOn props 추가로 디바이스별 표시 제어, 런타임 조건문 대체
ClubDetailPage 리팩토링
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx, frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts, frontend/src/pages/ClubDetailPage/components/ClubProfileCard/*, frontend/src/pages/ClubDetailPage/components/ClubFeed/ClubFeed.tsx
탭 클릭 시 스크롤 동작 추가, ClubDetailTopBar 컴포넌트 통합, 콘텐츠 영역 ref 기반 스크롤링, 이미지 로딩 최적화(디바이스별 eager/lazy 로딩), 뒤로가기 버튼 제거
ClubDetailTopBar 새 컴포넌트
frontend/src/pages/ClubDetailPage/components/ClubDetailTopBar/ClubDetailTopBar.tsx, frontend/src/pages/ClubDetailPage/components/ClubDetailTopBar/ClubDetailTopBar.styles.ts
스크롤 기반 헤더 표시, 알림 토글(앱 환경 감지), 탭 네비게이션, 뒤로가기 기능 포함
공유 기능 개선
frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx
Kakao SDK 제거, RN webview/웹 공유 API/클립보드 폴백 멀티 경로 지원, 접근성 텍스트 업데이트
WebView 브릿지 유틸리티
frontend/src/utils/webviewBridge.ts
React Native 앱과의 메시징 시스템 추가: 네비게이션, 알림 구독/구독해제, 공유 요청
스크롤 유틸리티 훅
frontend/src/hooks/Scroll/useScrollTo.ts, frontend/src/hooks/Scroll/ScrollToTop.tsx
스크롤 동작 재사용 가능 훅 추가, 기존 ScrollToTop 컴포넌트에 적용
API 타입 강화
frontend/src/apis/applicants.ts, frontend/src/apis/application.ts
반환 타입 명시화: ApplicantsInfo, ApplicationListResponse 추가, 제너릭 응답 처리
에러 핸들링 개선
frontend/src/hooks/Queries/useClubCover.ts, frontend/src/hooks/Queries/useClubImages.ts, frontend/src/pages/AdminPage/auth/LoginTab/LoginTab.tsx
URL 생성 실패 시 명시적 에러 스로우, 로그인 응답 검증 추가
AdminPage 최적화
frontend/src/pages/AdminPage/components/SideBar/SideBar.tsx
탭 클릭 시 쿼리 캐시 무효화 추가
스타일 업데이트
frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts, frontend/src/pages/AdminPage/tabs/ApplicantsTab/*.styles.ts, frontend/src/components/application/modals/ApplicationSelectModal.styles.ts, frontend/src/pages/MainPage/components/Popup/Popup.styles.ts
반응형 패딩/높이 추가, CSS-in-JS URL 이스케이프, 텍스트 색상 명시
TypeScript 설정
frontend/src/styles/styled.d.ts, frontend/src/styles/zIndex.ts, frontend/src/vite-env.d.ts, frontend/public/index.html
styled-components 테마 타입 확장, z-index modal 값 추가(1200), Vite/SVGR 타입 선언, viewport-fit 메타 태그 추가
모의 객체 정리
frontend/src/mocks/mswDevSetup.ts
RequestHandler 타입 단언 제거
문서 업데이트
README.md
프로젝트 소개 재구성, 다국어 네비게이션 추가, 기능/기여자 섹션 개편, 이미지 및 비주얼 자산 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ShareButton as ShareButton<br/>Component
    participant WebView as WebView Bridge
    participant RNApp as RN App
    participant WebAPI as Web Share API
    participant Clipboard as Clipboard

    User->>ShareButton: 공유 클릭
    
    alt RN WebView 환경
        ShareButton->>WebView: requestShare()
        WebView->>RNApp: postMessage(SHARE)
        RNApp-->>ShareButton: 성공
        ShareButton->>User: 공유 완료 (RN)
    else 모바일 웹 환경
        alt navigator.share 지원
            ShareButton->>WebAPI: navigator.share()
            WebAPI-->>User: 공유 옵션 표시
            User->>WebAPI: 공유 선택
            WebAPI-->>ShareButton: 성공
        else navigator.share 미지원
            ShareButton->>Clipboard: 클립보드 복사
            Clipboard-->>ShareButton: 복사 완료
        end
    else 데스크탑
        ShareButton->>Clipboard: 클립보드 복사
        Clipboard-->>User: 복사 완료 알림
    end
Loading
sequenceDiagram
    participant User
    participant ClubDetailPage as ClubDetailPage
    participant ClubDetailTopBar as ClubDetailTopBar
    participant ScrollListener as Scroll Listener
    participant Content as Content Section

    User->>ClubDetailPage: 클럽 상세 페이지 진입
    activate ClubDetailPage
    ClubDetailPage->>ClubDetailTopBar: 컴포넌트 마운트
    activate ClubDetailTopBar
    
    User->>Content: 스크롤
    activate ScrollListener
    ScrollListener->>ScrollListener: 스크롤 거리 계산
    
    alt 임계값 이상 스크롤
        ScrollListener->>ClubDetailTopBar: isVisible = true
        ClubDetailTopBar->>ClubDetailTopBar: 배경/섀도우 표시
        ClubDetailTopBar->>ClubDetailTopBar: 클럽명 페이드인
    else 임계값 미만
        ScrollListener->>ClubDetailTopBar: isVisible = false
        ClubDetailTopBar->>ClubDetailTopBar: 투명 상태
    end
    deactivate ScrollListener
    
    User->>ClubDetailTopBar: 탭 클릭
    ClubDetailTopBar->>Content: onTabClick 이벤트
    Content->>Content: contentRef로 스크롤 이동
    Content->>User: 탭 콘텐츠 표시
    
    deactivate ClubDetailTopBar
    deactivate ClubDetailPage
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

📈 release, 💻 FE

Suggested reviewers

  • seongwon030
  • lepitaaar
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경 내용의 핵심을 명확하게 설명하고 있습니다. Webpack에서 Vite로의 전환, 웹뷰 브릿지 추가, README 개편 등 주요 변경사항을 정확히 반영하는 revert 작업입니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@oesnuj oesnuj added 💻 FE Frontend 📈 release 릴리즈 배포 labels Jan 25, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx (1)

25-53: 스크롤 오프셋이 탑바 높이와 불일치합니다.
TOP_BAR_HEIGHT가 50인데, ClubDetailTopBar.styles.ts Line 18-20에서 TopBarContent 높이가 60px이고 Line 14에서 safe-top 패딩도 추가됩니다. 오프셋이 작으면 콘텐츠가 탑바 아래로 가려질 수 있어 높이를 맞추거나 실제 높이를 계산해 주세요.

✅ 제안 수정(간단 정렬)
-const TOP_BAR_HEIGHT = 50;
+// ClubDetailTopBar.styles.ts Line 18-20 기준(60px)과 맞춤
+const TOP_BAR_HEIGHT = 60;
🤖 Fix all issues with AI agents
In `@frontend/public/index.html`:
- Around line 12-14: The HTML uses viewport-fit=cover but GlobalStyles lacks
safe-area insets, so add CSS to the global stylesheet (or root element) to apply
env(safe-area-inset-*) paddings to prevent content overlapping the iOS notch;
update your GlobalStyles or body/root selector (where global layout is defined)
to include padding-top: env(safe-area-inset-top), padding-left:
env(safe-area-inset-left), padding-right: env(safe-area-inset-right), and
padding-bottom: env(safe-area-inset-bottom) so the viewport-fit=cover behavior
is safe on iOS.

In `@frontend/src/index.tsx`:
- Around line 3-6: Remove the dead Kakao SDK initializer by deleting the unused
initializeKakaoSDK function and any related imports/exports from
utils/initSDK.ts; ensure no callers (e.g., index.tsx) rely on it and clean up
any Kakao-specific constants or types in that module so the file only exports
active SDK initializers like initializeMixpanel and initializeSentry.

In `@frontend/src/pages/ApplicationFormPage/ApplicationFormPage.tsx`:
- Around line 123-124: Header was changed to show only on desktop but
PageContainer always has paddingTop: '80px', leaving unwanted gap on mobile;
update the layout so the top padding is applied only when the Header is actually
rendered. Locate Header and PageContainer in ApplicationFormPage and either: (a)
compute a desktop boolean (e.g., via a responsive hook/useMediaQuery or
window.matchMedia) and conditionally set PageContainer's style/paddingTop when
desktop is true, or (b) move the padding into a responsive
stylesheet/styled-component for PageContainer using a min-width media query so
paddingTop: 80px only applies on desktop; ensure the change references Header,
PageContainer and any responsive hook you add (e.g., useMediaQuery) so mobile
does not get the extra top padding.

In `@frontend/src/utils/webviewBridge.ts`:
- Around line 29-45: The postMessageToApp function returns true whenever
isInAppWebView() is true even if window.ReactNativeWebView is missing or
postMessage wasn't called; modify postMessageToApp to explicitly check for the
bridge (e.g., const bridge = window.ReactNativeWebView) before attempting to
call bridge.postMessage, log and return false if bridge is undefined, then call
bridge.postMessage inside the try and return true only after a successful call;
keep the existing try/catch around the actual postMessage call and ensure
console/process logs reference message.type and the error when returning false.
🧹 Nitpick comments (4)
frontend/src/components/application/modals/ApplicationSelectModal.styles.ts (1)

16-25: 테마 컬러 상수 사용 권장 (일관성 향상)
직접 black 리터럴 대신 테마의 컬러 상수를 쓰면 다크모드/디자인 토큰 변경 시 유지보수가 쉬워집니다.

♻️ 예시 수정안
 export const OptionButton = styled.button`
   width: 100%;
   padding: 18px 20px;
   border-radius: 10px;
   border: 1px solid ${colors.gray[400]};
   background: ${colors.base.white};
   font-weight: 600;
   font-size: 16px;
   cursor: pointer;
-  color: black;
+  color: ${colors.base.black};
frontend/src/pages/AdminPage/components/SideBar/SideBar.tsx (1)

57-63: 모든 쿼리 무효화는 과도할 수 있습니다.

invalidateQueries()를 인자 없이 호출하면 캐시된 모든 쿼리가 무효화됩니다. 탭 클릭 시마다 불필요한 네트워크 요청이 발생할 수 있습니다.

특정 쿼리 키를 지정하여 필요한 쿼리만 무효화하는 것을 고려해 보세요:

// 예시: 특정 쿼리만 무효화
queryClient.invalidateQueries({ queryKey: ['admin'] });

의도적으로 모든 쿼리를 무효화하려는 것이라면, 해당 의도를 주석으로 명시하는 것이 좋습니다.

frontend/src/pages/AdminPage/auth/LoginTab/LoginTab.tsx (1)

53-53: trackEvent 호출 위치 검토를 권장합니다.

현재 trackEvent(ADMIN_EVENT.LOGIN_BUTTON_CLICKED)try-catch-finally 블록 이후에 위치하여 로그인 성공/실패와 관계없이 항상 실행됩니다. 이벤트 트래킹 의도에 따라 위치 조정을 고려해 주세요:

  • 로그인 버튼 클릭 추적이 목적이라면: handleLogin 함수 시작 부분으로 이동
  • 로그인 성공 추적이 목적이라면: try 블록 내 navigate() 호출 전으로 이동
frontend/src/components/common/Header/Header.tsx (1)

49-61: showOn/hideOn 동시 사용 시 동작이 모호합니다.
현재는 hideOn이 있으면 showOn이 무시됩니다. 둘 다 받는 경우를 지원하려면 “showOn에 포함되고 hideOn에 제외” 규칙으로 정리하는 편이 안전합니다.

♻️ 제안 변경
-  const shouldRender = (): boolean => {
-    const currentTypes = getCurrentDeviceTypes();
-
-    if (hideOn) {
-      return !hideOn.some((type) => currentTypes.includes(type));
-    }
-
-    if (showOn) {
-      return showOn.some((type) => currentTypes.includes(type));
-    }
-
-    return true;
-  };
+  const shouldRender = (): boolean => {
+    const currentTypes = getCurrentDeviceTypes();
+
+    if (showOn && !showOn.some((type) => currentTypes.includes(type))) {
+      return false;
+    }
+
+    if (hideOn && hideOn.some((type) => currentTypes.includes(type))) {
+      return false;
+    }
+
+    return true;
+  };

Comment on lines 12 to 14
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# safe-area 대응 스타일 존재 여부 확인
rg -n "safe-area-inset" -g '*.{css,scss,tsx,ts,jsx,js,html}'

Repository: Moadong/moadong

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Broader search for safe-area patterns
echo "=== Searching for 'safe-area' pattern ==="
rg -i "safe-area" --max-count=20

echo "=== Checking for CSS/SCSS files ==="
fd -e css -e scss

echo "=== Searching for padding/margin with inset patterns ==="
rg "inset|padding-top|margin-top" -g '*.{css,scss}' | head -20

echo "=== Checking main CSS structure ==="
find frontend -name "*.css" -o -name "*.scss" | head -10

Repository: Moadong/moadong

Length of output: 395


🏁 Script executed:

#!/bin/bash
# Explore frontend structure
echo "=== Frontend directory structure ==="
find frontend -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" -o -name "*.css" | head -30

echo "=== Check frontend/public directory ==="
ls -la frontend/public/

echo "=== List files in frontend root ==="
ls -la frontend/

echo "=== Search for viewport-fit or safe-area in all text files ==="
rg "viewport-fit|safe-area" --max-count=20

Repository: Moadong/moadong

Length of output: 3514


🏁 Script executed:

#!/bin/bash
# Check App.tsx and root styling
echo "=== App.tsx content ==="
cat -n frontend/src/App.tsx

echo "=== Check for createGlobalStyle or similar ==="
rg "createGlobalStyle|GlobalStyle|css\`" --max-count=20

echo "=== Check main.tsx/index.tsx ==="
ls -la frontend/src/main.* frontend/src/index.*

Repository: Moadong/moadong

Length of output: 4967


🏁 Script executed:

#!/bin/bash
# Check Global.styles.ts
echo "=== Global.styles.ts content ==="
cat -n frontend/src/styles/Global.styles.ts

echo "=== Check for any padding/inset related styles ==="
rg "padding|inset|margin" frontend/src/styles/Global.styles.ts

Repository: Moadong/moadong

Length of output: 827


iOS 안전영역 CSS 대응 필수
viewport-fit=cover를 사용하고 있으나 GlobalStyles에 env(safe-area-inset-*)이 적용되지 않았습니다. iOS 노치 영역에 콘텐츠가 겹치는 현상을 방지하기 위해 root 요소 또는 body에 다음과 같이 추가해 주세요:

body {
  padding-top: env(safe-area-inset-top);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
}
🤖 Prompt for AI Agents
In `@frontend/public/index.html` around lines 12 - 14, The HTML uses
viewport-fit=cover but GlobalStyles lacks safe-area insets, so add CSS to the
global stylesheet (or root element) to apply env(safe-area-inset-*) paddings to
prevent content overlapping the iOS notch; update your GlobalStyles or body/root
selector (where global layout is defined) to include padding-top:
env(safe-area-inset-top), padding-left: env(safe-area-inset-left),
padding-right: env(safe-area-inset-right), and padding-bottom:
env(safe-area-inset-bottom) so the viewport-fit=cover behavior is safe on iOS.

Comment on lines +3 to 6
import { initializeMixpanel, initializeSentry } from './utils/initSDK';

initializeMixpanel();
initializeSentry();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for Kakao SDK references in the codebase
echo "=== Searching for Kakao references in TypeScript/TSX files ==="
rg -n "kakao|Kakao|KAKAO" --type=ts --type=tsx -g '!*.test.*' -g '!*.spec.*' || echo "No Kakao references found"

echo ""
echo "=== Checking initSDK file ==="
# Find and display initSDK file
fd "initSDK" --type f -x cat {}

echo ""
echo "=== Checking index.tsx imports ==="
# Check what's imported in index.tsx
head -20 frontend/src/index.tsx 2>/dev/null || head -20 src/index.tsx 2>/dev/null

Repository: Moadong/moadong

Length of output: 2587


🏁 Script executed:

#!/bin/bash
# Additional search for Kakao in various file types
echo "=== Broader search for Kakao references ==="
rg -i "kakao" --type=js --type=json --type=tsx --type=ts 2>/dev/null | head -30 || echo "No additional Kakao references found"

echo ""
echo "=== Check for any SDK initialization files ==="
fd "SDK|sdk" --type f -path "*/utils/*" | head -20

Repository: Moadong/moadong

Length of output: 336


미사용 Kakao SDK 함수 제거 필요

initializeKakaoSDK() 호출이 index.tsx에서 제거되었으며, 코드베이스 전체에서 Kakao SDK 참조가 없음을 확인했습니다. 다만 utils/initSDK.tsinitializeKakaoSDK() 함수가 여전히 미사용 상태로 존재하므로 제거가 필요합니다.

🤖 Prompt for AI Agents
In `@frontend/src/index.tsx` around lines 3 - 6, Remove the dead Kakao SDK
initializer by deleting the unused initializeKakaoSDK function and any related
imports/exports from utils/initSDK.ts; ensure no callers (e.g., index.tsx) rely
on it and clean up any Kakao-specific constants or types in that module so the
file only exports active SDK initializers like initializeMixpanel and
initializeSentry.

Comment on lines +123 to 124
<Header showOn={['desktop']} />
<PageContainer style={{ paddingTop: '80px' }}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

모바일에서 상단 여백이 남을 수 있어요.
헤더가 데스크톱에서만 보이도록 변경되었는데 PageContainerpaddingTop: 80px는 모바일에서도 유지되어 빈 공간이 생길 가능성이 있습니다. 헤더가 렌더링되는 경우에만 상단 여백을 주는 방식으로 조정해 주세요.

🛠️ 예시 수정안
-import { useEffect, useRef, useState } from 'react';
+import { useEffect, useRef, useState } from 'react';
+import useDevice from '@/hooks/useDevice';
 ...
-  const trackEvent = useMixpanelTrack();
+  const trackEvent = useMixpanelTrack();
+  const { isMobile } = useDevice();
 ...
-      <PageContainer style={{ paddingTop: '80px' }}>
+      <PageContainer style={{ paddingTop: isMobile ? '0' : '80px' }}>
🤖 Prompt for AI Agents
In `@frontend/src/pages/ApplicationFormPage/ApplicationFormPage.tsx` around lines
123 - 124, Header was changed to show only on desktop but PageContainer always
has paddingTop: '80px', leaving unwanted gap on mobile; update the layout so the
top padding is applied only when the Header is actually rendered. Locate Header
and PageContainer in ApplicationFormPage and either: (a) compute a desktop
boolean (e.g., via a responsive hook/useMediaQuery or window.matchMedia) and
conditionally set PageContainer's style/paddingTop when desktop is true, or (b)
move the padding into a responsive stylesheet/styled-component for PageContainer
using a min-width media query so paddingTop: 80px only applies on desktop;
ensure the change references Header, PageContainer and any responsive hook you
add (e.g., useMediaQuery) so mobile does not get the extra top padding.

Comment on lines +29 to +45
export const postMessageToApp = (message: WebViewMessage): boolean => {
if (!isInAppWebView()) {
if (isDev) {
console.log('[WebViewBridge] 웹 환경, 메시지 무시:', message.type);
}
return false;
}

try {
window.ReactNativeWebView?.postMessage(JSON.stringify(message));
if (isDev) {
console.log('[WebViewBridge] 앱으로 전송:', message.type);
}
return true;
} catch (error) {
console.error('[WebViewBridge] 전송 실패:', error);
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

전송 성공 여부를 정확히 반영하세요.
isInAppWebView()가 true여도 ReactNativeWebView가 없으면 실제 전송이 되지 않는데, 현재는 true를 반환합니다. 호출부가 성공으로 오인할 수 있으니 브릿지 유무를 확인하고 실패 처리하는 게 안전합니다.

✅ 제안 수정
 export const postMessageToApp = (message: WebViewMessage): boolean => {
   if (!isInAppWebView()) {
     if (isDev) {
       console.log('[WebViewBridge] 웹 환경, 메시지 무시:', message.type);
     }
     return false;
   }

   try {
-    window.ReactNativeWebView?.postMessage(JSON.stringify(message));
+    const bridge = window.ReactNativeWebView;
+    if (!bridge?.postMessage) {
+      if (isDev) {
+        console.warn('[WebViewBridge] 브릿지 없음, 전송 실패:', message.type);
+      }
+      return false;
+    }
+    bridge.postMessage(JSON.stringify(message));
     if (isDev) {
       console.log('[WebViewBridge] 앱으로 전송:', message.type);
     }
     return true;
   } catch (error) {
     console.error('[WebViewBridge] 전송 실패:', error);
     return false;
   }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const postMessageToApp = (message: WebViewMessage): boolean => {
if (!isInAppWebView()) {
if (isDev) {
console.log('[WebViewBridge] 웹 환경, 메시지 무시:', message.type);
}
return false;
}
try {
window.ReactNativeWebView?.postMessage(JSON.stringify(message));
if (isDev) {
console.log('[WebViewBridge] 앱으로 전송:', message.type);
}
return true;
} catch (error) {
console.error('[WebViewBridge] 전송 실패:', error);
return false;
export const postMessageToApp = (message: WebViewMessage): boolean => {
if (!isInAppWebView()) {
if (isDev) {
console.log('[WebViewBridge] 웹 환경, 메시지 무시:', message.type);
}
return false;
}
try {
const bridge = window.ReactNativeWebView;
if (!bridge?.postMessage) {
if (isDev) {
console.warn('[WebViewBridge] 브릿지 없음, 전송 실패:', message.type);
}
return false;
}
bridge.postMessage(JSON.stringify(message));
if (isDev) {
console.log('[WebViewBridge] 앱으로 전송:', message.type);
}
return true;
} catch (error) {
console.error('[WebViewBridge] 전송 실패:', error);
return false;
}
};
🤖 Prompt for AI Agents
In `@frontend/src/utils/webviewBridge.ts` around lines 29 - 45, The
postMessageToApp function returns true whenever isInAppWebView() is true even if
window.ReactNativeWebView is missing or postMessage wasn't called; modify
postMessageToApp to explicitly check for the bridge (e.g., const bridge =
window.ReactNativeWebView) before attempting to call bridge.postMessage, log and
return false if bridge is undefined, then call bridge.postMessage inside the try
and return true only after a successful call; keep the existing try/catch around
the actual postMessage call and ensure console/process logs reference
message.type and the error when returning false.

@seongwon030 seongwon030 merged commit 3216680 into main Jan 25, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend 📈 release 릴리즈 배포

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments