Skip to content

[release] FE v1.1.19#1106

Merged
oesnuj merged 87 commits intomainfrom
develop-fe
Jan 25, 2026
Merged

[release] FE v1.1.19#1106
oesnuj merged 87 commits intomainfrom
develop-fe

Conversation

@oesnuj
Copy link
Member

@oesnuj oesnuj commented Jan 25, 2026

📋 개요

  • 동아리 상세 페이지 고도화 및 앱-웹 브릿지 연동 최적화

이번 릴리즈는 동아리 상세 페이지의 전반적인 UX 개선과 안정적인 앱-웹 통신(WebView Bridge) 기반 마련을 목표로 합니다.

특히 기기별 Safe Area 대응 문제와 파편화되어 있던 공유 로직을 통합하여, 앱 내 웹뷰 환경에서도 네이티브 앱과 같은 매끄러운 사용자 경험을 제공하고자 합니다.



✨ 주요 변경 사항

1. 동아리 상세 페이지 UX/UI 고도화

  • 기기별 Safe Area 대응 체계 구축

    • 기존 env(safe-area-inset-top) 이 WebView 환경에서 일관되게 동작하지 않던 문제(0으로 반환 등)를 해결
    • 앱에서 직접 주입하는 CSS 변수 --rn-safe-top 방식 도입
  • 모바일/태블릿 전용 탑바(ClubDetailTopBar) 도입

    • 앱 환경에 최적화된 헤더 레이아웃 구성
    • 알림 설정 토글 기능 구현
  • 상세 페이지 레이아웃 개선

    • 모바일 환경에서 하단 푸터와의 여백(60px) 확보로 가독성 향상
    • useScrollTo 훅 도입
      • 탭 전환 시 헤더 높이를 고려한 정교한 스크롤 이동 처리

2. WebView Bridge 시스템 인프라 구축

  • 통신 로직 중앙화 (webviewBridge.ts)

    • postMessage 통신 규격을 타입 안전하게 정의
    • requestShare, requestNavigateBack 등 액션 헬퍼 함수로 통신 로직 추상화
  • 앱-웹 UI 동기화

    • 웹뷰 진입 시 초기 알림 설정 상태 동기화
    • 뒤로가기 동작 최적화로 웹·네이티브 간 이질감 최소화

3. 공유하기 기능 개선 및 통합

  • 플랫폼별 최적화 공유 로직

    • WebView: 앱 브릿지를 통한 네이티브 공유 라이브러리 호출
    • Web (Mobile): 브라우저 표준 Web Share API 활용
    • Desktop: 클립보드 링크 복사 폴백 지원
  • 데이터 포맷 통일

    • 공유 시 전달되는 텍스트 포맷을 일관성 있게 정리
    • 에러 처리 로직 강화

4. 기술 부채 해결 및 성능 최적화

  • 빌드 시스템 개선

    • 미사용 Webpack 의존성 제거
    • Vite 기반 프로젝트 구조에 맞춰 빌드 스크립트 정비
  • 타입 안정성 확보

    • API 반환 타입과 테마 정의 간 불일치로 발생하던 TypeScript 에러 일괄 수정
  • 이미지 로딩 최적화

    • 상세 페이지 피드 이미지 로딩 임계값 조정
    • 초기 렌더링 성능 개선



📦 변경 사항 요약

카테고리 주요 내용
Feature ClubDetailTopBar, WebViewBridge, 전용 헤더 구현
Fix Safe Area 패딩 대응, 타입 에러 수정, 뒤로가기 로직 개선
Refactor 공유 로직 통합(requestShare), useScrollTo 도입
Perf 이미지 프리로드 로직 최적화, 빌드 스크립트 정비
Docs README 전면 개편, 이미지 리소스 정리

seongwon030 and others added 30 commits January 22, 2026 03:11
- React Native WebView 환경 감지 시 `postMessage`를 통한 네이티브 공유 통신 로직 추가
- RN 환경에서 공유 시 URL이 텍스트에 포함되도록 페이로드 구성 (웹뷰 호환성 개선)
- 믹스패널 이벤트 트래킹에 `native_share` 메서드 케이스 추가
- 공유 미리보기를 위한 동아리 로고(`image`) 데이터 페이로드에 추가
- Web Share API에서 url 필드 제거하고 text에 URL 포함
- 모바일 웹/데스크탑/앱 모든 환경에서 "메시지 + URL" 순서로 통일
- 카카오톡 등 일부 플랫폼에서 URL만 공유되던 문제 해결
- Web Share API 실패 시 클립보드 복사로 폴백 처리
…-542

[feature] 카카오톡 공유 및 web share api로 변경
- hideOn: 해더를 가릴 디바이스 타입을 설정합니다
- showOn: 해더를 보여줄 디바이스 타입을 설정합니다
- Vite 환경에서 SVG를 React 컴포넌트로 바로 import(`*.svg?react`)할 수 있도록 `vite-plugin-svgr` 플러그인 설치 및 설정
- TypeScript가 확장자를 인식할 수 있도록 타입 정의(`vite-env.d.ts`) 추가
- 앱 환경(`isInApp`)에서만 알림 버튼이 표시되도록 처리
- 앱 환경(React Native WebView)과 통신하기 위한 postMessage 래퍼 함수 구현
- 알림 구독/취소 및 뒤로가기 요청 기능
- 기존 헤더를 새로 구현된 MobileHeader로 교체
- 스크롤 인터랙션 및 탭 네비게이션 연동
- 스크롤 로직 공통화를 위한 useScrollTo 커스텀 훅 생성
- ScrollToTopButton 및 ClubDetailPage에 새로운 훅 적용
- 상세페이지 탭 전환 시 히스토리가 쌓이지 않도록 replace 옵션 적용하여 뒤로가기 동작 개선
[fix] 공유하기 웹뷰 브리징 제거
Copy link
Member

@seongwon030 seongwon030 left a comment

Choose a reason for hiding this comment

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

라스트댄스 3번째네요

[fix] 이미지가 정상적으로 불러와지지않는 문제 수정
oesnuj and others added 9 commits January 25, 2026 18:02
이유: 기존 env(safe-area-inset-top)가 WebView 환경에서 올바르게 동작하지 않는 문제를 해결하기 위해, React Native에서 직접 주입해주는 CSS 변수(--rn-safe-top)를 사용하도록 변경하여 기기별 노치 영역 대응을 보장함.
이유: ShareButton에 파편화되어 있던 React Native 통신 로직을 공통 유틸리티인 webviewBridge.ts로 통합하여, 통신 규격을 한곳에서 관리하고 컴포넌트의 책임을 단순화하기 위함.
…dge-MOA-570

[feature] 공유하기 웹뷰 브리지 복구
…-568

[fix] Webview 기기별 Safe Area 미적용 문제 해결 및 CSS 변수 기반 대응
…oading-MOA-536

[refactor] 활동사진을 최적화한다
@oesnuj
Copy link
Member Author

oesnuj commented Jan 25, 2026

라스트댄스 3번째네요

다음은 라스트댄스 4인가요? ㅋㅋ
거의 시리즈 영화물

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: 1

🤖 Fix all issues with AI agents
In `@frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx`:
- Around line 15-16: 현재 isRNWebView가 모듈 스코프에서 isInAppWebView()로 한 번만 평가되어 잘못된 값이
캐시될 위험이 있습니다; 이동할 위치는 ShareButton 컴포넌트 내부입니다 — 컴포넌트 렌더/마운트 시점에 isInAppWebView()를
평가하도록 isRNWebView를 ShareButton 내부로 옮기고(또는 성능을 위해 useMemo 또는 useState+useEffect로
래핑) 컴포넌트 외부의 모듈 스코프 참조를 제거하세요; 대상 식별자: isRNWebView, isInAppWebView(),
ShareButton.
♻️ Duplicate comments (1)
frontend/src/utils/webviewBridge.ts (1)

37-42: 옵셔널 체이닝으로 인한 잠재적 사일런트 실패

이전 리뷰에서 지적된 것처럼, window.ReactNativeWebView?.postMessage에서 ReactNativeWebView가 정의되지 않은 경우에도 return true가 실행됩니다. 명시적 존재 여부 확인이 필요합니다.

🧹 Nitpick comments (3)
frontend/src/pages/ClubDetailPage/components/ClubFeed/ClubFeed.tsx (1)

51-58: 변수 섀도잉 발생: index가 상태 변수와 map 콜백 파라미터에서 동일하게 사용됨

Line 22에서 선언된 index 상태 변수가 Line 51의 map 콜백 파라미터 index에 의해 가려집니다. 코드가 정상 동작하지만, 가독성과 유지보수성을 위해 구분되는 이름 사용을 권장합니다.

♻️ 변수명 변경 제안
-          {feed.map((f, index) => (
-            <Styled.PhotoItem key={`${f}-${index}`} onClick={() => open(index)}>
+          {feed.map((f, idx) => (
+            <Styled.PhotoItem key={`${f}-${idx}`} onClick={() => open(idx)}>
               <Styled.PhotoImage
                 src={f}
-                alt={`활동사진 ${index + 1}`}
-                loading={index < loadingThreshold ? 'eager' : 'lazy'}
+                alt={`활동사진 ${idx + 1}`}
+                loading={idx < loadingThreshold ? 'eager' : 'lazy'}
               />
             </Styled.PhotoItem>
           ))}
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx (2)

122-127: 인라인 스타일 대신 styled-components 활용 고려

display 토글을 위해 인라인 스타일을 사용하고 있습니다. 프로젝트가 styled-components를 사용하므로, 일관성을 위해 스타일드 컴포넌트로 처리하는 것을 고려해 보세요. 현재 방식은 컴포넌트를 마운트 상태로 유지하여 상태 보존에는 유리하지만, 리소스 사용 측면에서는 고려가 필요합니다.

♻️ 스타일드 컴포넌트 활용 예시
+ // ClubDetailPage.styles.ts에 추가
+ export const TabPanel = styled.div<{ $visible: boolean }>`
+   display: ${({ $visible }) => ($visible ? 'block' : 'none')};
+ `;
  <Styled.TabContent>
-   <div style={{ display: activeTab === TAB_TYPE.INTRO ? 'block' : 'none' }}>
+   <Styled.TabPanel $visible={activeTab === TAB_TYPE.INTRO}>
      <ClubIntroContent {...clubDetail.description} />
-   </div>
-   <div style={{ display: activeTab === TAB_TYPE.PHOTOS ? 'block' : 'none' }}>
+   </Styled.TabPanel>
+   <Styled.TabPanel $visible={activeTab === TAB_TYPE.PHOTOS}>
      <ClubFeed feed={clubDetail.feeds} clubName={clubDetail.name} />
-   </div>
+   </Styled.TabPanel>
  </Styled.TabContent>

25-26: TOP_BAR_HEIGHT 매직 넘버 관리 고려

TOP_BAR_HEIGHT = 50이 하드코딩되어 있습니다. ClubDetailTopBar의 실제 CSS 높이와 동기화가 필요하며, 값이 변경될 경우 두 곳을 모두 수정해야 합니다. 공유 상수 파일로 추출하거나 CSS 변수를 활용하는 것을 고려해 보세요.

Comment on lines +15 to +16
const isRNWebView = isInAppWebView();

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

isRNWebView가 모듈 스코프에서 평가되어 잠재적 문제 발생 가능

isInAppWebView()가 모듈 로드 시점에 한 번만 평가됩니다. 환경이 완전히 준비되기 전에 모듈이 로드되면 잘못된 값이 캐시될 수 있습니다. 컴포넌트 내부에서 평가하거나 useMemo를 사용하는 것이 더 안전합니다.

🔧 컴포넌트 내부로 이동 제안
- const isRNWebView = isInAppWebView();
- 
  const MOADONG_BASE_URL = 'https://www.moadong.com/club/';

  const ShareButton = ({ clubId }: ShareButtonProps) => {
    const { isMobile } = useDevice();
    const { data: clubDetail } = useGetClubDetail(clubId);
    const trackEvent = useMixpanelTrack();
+   const isRNWebView = isInAppWebView();

    if (!clubDetail) return;
🤖 Prompt for AI Agents
In `@frontend/src/pages/ClubDetailPage/components/ShareButton/ShareButton.tsx`
around lines 15 - 16, 현재 isRNWebView가 모듈 스코프에서 isInAppWebView()로 한 번만 평가되어 잘못된
값이 캐시될 위험이 있습니다; 이동할 위치는 ShareButton 컴포넌트 내부입니다 — 컴포넌트 렌더/마운트 시점에
isInAppWebView()를 평가하도록 isRNWebView를 ShareButton 내부로 옮기고(또는 성능을 위해 useMemo 또는
useState+useEffect로 래핑) 컴포넌트 외부의 모듈 스코프 참조를 제거하세요; 대상 식별자: isRNWebView,
isInAppWebView(), ShareButton.

Copy link
Collaborator

@suhyun113 suhyun113 left a comment

Choose a reason for hiding this comment

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

릴리즈 합시당

@oesnuj oesnuj merged commit bfe0f8b into main Jan 25, 2026
3 checks passed
@oesnuj oesnuj added 💻 FE Frontend 📈 release 릴리즈 배포 labels Jan 25, 2026
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.

4 participants

Comments