Conversation
- useIsMobile 훅 삭제 (useDevice와 중복) - 동일한 브레이크포인트(500px) 사용으로 기능 동일
- 회원탈퇴 탭 항목 삭제 - 관련 미구현 alert 로직 제거
…tion-MOA-414 [refactor] 중복된 디바이스 감지 훅을 통합한다
…tion-MOA-416 [feature] 회원 탈퇴 기능을 제거한다
[feature] 중앙동아리 문구에 학교명 추가
- 패치노트 배너 제거
- APP_STORE_LINKS 상수 추가 (iOS, Android, default) - getAppStoreLink 함수로 user-agent 기반 OS 판별 - iOS: itms-apps 스키마로 App Store 연결 - Android/기타: Google Play Store 연결
- javascript, data, vbscript 프로토콜 차단으로 XSS 방지 - 허용 프로토콜 화이트리스트 방식으로 변경
- 빈 URL 처리 테스트 - 악성 프로토콜 차단 테스트 (javascript, data, vbscript) - 외부 URL 이동 테스트 (https, http, itms-apps) - 내부 페이지 이동 테스트
- Given-When-Then 패턴 주석 추가 - renderHook을 beforeEach로 공통화하여 중복 제거
- eventName에 BANNER_CLICKED, APP_DOWNLOAD_BANNER_CLICKED 이벤트 추가 - 배너 클릭 시 bannerId, bannerName, linkTo/platform 로깅 - user-agent 기반 iOS/Android 스토어 링크 분기 - 앱 다운로드 배너 데이터 추가
- 악성 링크 테스트 4개 → 1개 (parameterized) - 외부 링크 테스트 3개 → 1개 (parameterized)
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | 요약 |
|---|---|
훅 변경 및 삭제frontend/src/hooks/useIsMobile.ts, frontend/src/hooks/useNavigator.ts, frontend/src/hooks/__tests__/useNavigator.test.ts |
useIsMobile 파일 삭제. useNavigator 외부 링크 판정 및 리다이렉트를 window.location.href 사용으로 변경하고 javascript:, data:, vbscript: 프로토콜 차단 추가. useNavigator용 테스트 추가. |
컴포넌트 - QuestionTitlefrontend/src/components/application/QuestionTitle/QuestionTitle.tsx |
useIsMobile 사용을 useDevice로 교체; React 임포트에서 useEffect 제거(대신 useLayoutEffect, useRef 유지). |
페이지 - AdminPage 사이드바frontend/src/pages/AdminPage/components/SideBar/SideBar.tsx |
"회원탈퇴" 메뉴 항목 및 관련 클릭 처리(alert 등) 제거. |
페이지 - MainPage 탭 레이블frontend/src/pages/MainPage/MainPage.tsx |
탭 레이블 및 초기 활성 탭 값을 '중앙동아리'에서 '부경대학교 중앙동아리'로 변경. |
배너 관련 변경frontend/src/pages/MainPage/components/Banner/Banner.tsx, frontend/src/pages/MainPage/components/Banner/bannerData.ts |
앱 다운로드 배너(이미지 및 id 추가) 삽입, 배너 클릭 핸들러 확장(배너 id/이름 파라미터, 앱스토어 링크 결정), 플랫폼 감지 및 Mixpanel 이벤트(APP_DOWNLOAD_BANNER_CLICKED, BANNER_CLICKED) 추적 추가. 기존 패치노트 배너 제거. |
상수 - 이벤트명 추가frontend/src/constants/eventName.ts |
USER_EVENT에 BANNER_CLICKED와 APP_DOWNLOAD_BANNER_CLICKED 이벤트 키 추가. |
Sequence Diagram(s)
mermaid
sequenceDiagram
autonumber
participant User as 사용자
participant Banner as Banner 컴포넌트
participant Track as Mixpanel (trackEvent)
participant NavHook as useNavigator
participant Browser as 브라우저 (window.location / 내비게이트)
User->>Banner: 배너 클릭 (bannerId, alt, linkTo)
Banner->>Track: trackEvent(BANNER_CLICKED or APP_DOWNLOAD_BANNER_CLICKED, meta)
alt linkTo == APP_STORE_LINK
Banner->>Banner: getAppStoreLink() (UA 기반)
Banner->>NavHook: navigateTo(storeLink)
else 외부 URL (http/https/itms-apps)
Banner->>NavHook: navigateTo(externalUrl)
else 내부 경로
Banner->>NavHook: navigateTo(internalPath)
end
NavHook->>NavHook: 검사 (차단 프로토콜? external?)
alt 차단 프로토콜 (javascript:, data:, vbscript:)
NavHook-->>Browser: 아무 동작 안함 (차단)
else 외부 URL
NavHook-->>Browser: window.location.href = url
else 내부 경로
NavHook-->>Browser: useNavigate(path)
end
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25분
- 혼합된 변경(훅 제거·대체, 내비게이션 보안 로직 변경, 분석 이벤트 추가, UI 레이블/아이템 변경, 테스트 추가)
- 리뷰 시 집중할 점:
- useDevice의 isMobile 동작이 기존 useIsMobile과 호환되는지 검증
- useNavigator의 외부 URL 판정 및 프로토콜 차단이 모든 보안 케이스를 커버하는지 확인
- Banner의 APP_STORE_LINK 처리 및 플랫폼 감지 로직(UA 기반)이 올바른지 검토
- useNavigator 테스트가 브라우저 전역(window.location) 복원/모킹을 안전하게 수행하는지 확인
Possibly related PRs
- [feature] 앱 출시 배너를 추가한다 #938 — 배너 기능, 네비게이션 및 이벤트 트래킹 관련 변경사항과 강한 연관성
- [refactor] 중복된 디바이스 감지 훅을 통합한다 #921 —
useIsMobile제거 및useDevice마이그레이션과 직접적 관련 - [feature] 회원 탈퇴 기능을 제거한다 #924 —
SideBar.tsx에서 "회원탈퇴" 항목 제거와 관련
Suggested reviewers
- lepitaaar
- Zepelown
- suhyun113
Pre-merge checks and finishing touches
❌ Failed checks (1 inconclusive)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Title check | ❓ Inconclusive | PR 제목 '[release] FE v1.1.8'은 버전 릴리스를 나타내지만, 변경 내용의 구체적인 주요 기능을 설명하지 않습니다. | 제목을 더 구체적으로 수정하여 주요 변경 사항을 명확히 하세요. 예: '[release] FE v1.1.8: useDevice 훅 전환 및 배너 기능 개선' |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✨ Finishing touches
- 📝 Generate docstrings
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
develop-fe
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
[feature] 앱 출시 배너를 추가한다
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
frontend/src/pages/MainPage/components/Banner/bannerData.ts (1)
17-23: 매직 스트링 'APP_STORE_LINK' 사용 개선 제안
linkTo: 'APP_STORE_LINK'는 실제 URL이 아닌 특수 식별자로 사용되고 있어 혼란을 줄 수 있습니다. 타입 안정성과 명확성을 위해 별도 필드나 타입 유니온 사용을 고려해 주세요.interface BannerItem { id: string; desktopImage: string; mobileImage: string; - linkTo?: string; + linkTo?: string; + isAppStoreLink?: boolean; alt: string; } const BANNERS: BannerItem[] = [ { id: 'app-release-december-2025', desktopImage: AppReleaseDesktopImage, mobileImage: AppReleaseMobileImage, - linkTo: 'APP_STORE_LINK', + isAppStoreLink: true, alt: '앱 다운로드 배너', },코딩 가이드라인에 따라 매직 값 대신 명시적인 상수나 타입을 사용하는 것이 좋습니다.
frontend/src/pages/MainPage/components/Banner/Banner.tsx (1)
48-64: 플랫폼 감지 로직 중복 - 리팩토링 권장플랫폼 감지 로직이
getAppStoreLink()(Line 24-30)와handleBannerClick(Line 56)에서 중복됩니다. 단일 함수로 추출하여 일관성을 유지하세요.+const getPlatform = (): 'ios' | 'android' => { + const userAgent = navigator.userAgent.toLowerCase(); + if (/iphone|ipad|ipod|macintosh/.test(userAgent)) { + return 'ios'; + } + return 'android'; +}; + const getAppStoreLink = (): string => { - const userAgent = navigator.userAgent.toLowerCase(); - - if (/iphone|ipad|ipod|macintosh/.test(userAgent)) { - return APP_STORE_LINKS.ios; - } - if (/android/.test(userAgent)) { - return APP_STORE_LINKS.android; - } - return APP_STORE_LINKS.default; + const platform = getPlatform(); + return APP_STORE_LINKS[platform] ?? APP_STORE_LINKS.default; };그리고
handleBannerClick에서:trackEvent(USER_EVENT.APP_DOWNLOAD_BANNER_CLICKED, { bannerId, bannerName, - platform: /iphone|ipad|ipod|macintosh/.test(navigator.userAgent.toLowerCase()) ? 'ios' : 'android', + platform: getPlatform(), });
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (2)
frontend/src/assets/images/banners/banner_desktop4.pngis excluded by!**/*.pngfrontend/src/assets/images/banners/banner_mobile4.pngis excluded by!**/*.png
📒 Files selected for processing (5)
frontend/src/constants/eventName.ts(1 hunks)frontend/src/hooks/__tests__/useNavigator.test.ts(1 hunks)frontend/src/hooks/useNavigator.ts(1 hunks)frontend/src/pages/MainPage/components/Banner/Banner.tsx(3 hunks)frontend/src/pages/MainPage/components/Banner/bannerData.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries withif/elseor IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling
Files:
frontend/src/constants/eventName.tsfrontend/src/hooks/__tests__/useNavigator.test.tsfrontend/src/hooks/useNavigator.tsfrontend/src/pages/MainPage/components/Banner/bannerData.tsfrontend/src/pages/MainPage/components/Banner/Banner.tsx
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
Use consistent return types for similar functions/hooks
Files:
frontend/src/constants/eventName.tsfrontend/src/hooks/__tests__/useNavigator.test.tsfrontend/src/hooks/useNavigator.tsfrontend/src/pages/MainPage/components/Banner/bannerData.tsfrontend/src/pages/MainPage/components/Banner/Banner.tsx
frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated components/HOCs
Separate significantly different conditional UI/logic into distinct components
Colocate simple, localized logic or use inline definitions to reduce context switching
Choose field-level or form-level cohesion based on form requirements when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling
Files:
frontend/src/pages/MainPage/components/Banner/Banner.tsx
🧠 Learnings (1)
📚 Learning: 2025-07-20T11:48:50.207Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 541
File: frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx:41-43
Timestamp: 2025-07-20T11:48:50.207Z
Learning: moadong 프로젝트는 Next.js가 아닌 순수 React + react-router-dom 기반의 CSR(Client-Side Rendering) SPA이므로, window 객체 사용에 대한 SSR 호환성 문제를 제기하지 않아야 합니다.
Applied to files:
frontend/src/hooks/__tests__/useNavigator.test.ts
🧬 Code graph analysis (1)
frontend/src/pages/MainPage/components/Banner/Banner.tsx (1)
frontend/src/constants/eventName.ts (1)
USER_EVENT(1-36)
🔇 Additional comments (6)
frontend/src/constants/eventName.ts (1)
5-9: LGTM!새로운 배너 이벤트 상수들이 기존 컨벤션을 잘 따르고 있습니다. Line 8-9에 불필요한 빈 줄이 있지만 사소한 부분입니다.
frontend/src/hooks/useNavigator.ts (2)
12-13: 보안 강화 - 잘 구현되었습니다.
javascript:,data:,vbscript:프로토콜을 대소문자 구분 없이 차단하여 XSS 공격 벡터를 효과적으로 방지합니다.
15-18: 외부 링크 동작 변경 확인 필요
window.open대신window.location.href를 사용하여 외부 링크가 새 탭이 아닌 현재 탭에서 열리도록 변경되었습니다. 앱스토어 링크(itms-apps)의 경우 이 동작이 적합하지만,http/https외부 링크도 동일하게 현재 탭에서 열리게 됩니다.이것이 의도된 UX 변경인지 확인해 주세요. 만약 일반 외부 링크는 새 탭에서 열어야 한다면 프로토콜별로 분기 처리가 필요합니다.
frontend/src/hooks/__tests__/useNavigator.test.ts (1)
1-104: LGTM! - 포괄적인 테스트 커버리지테스트가
useNavigator훅의 주요 시나리오를 잘 커버하고 있습니다:
- 빈/공백 링크 처리
- 악성 프로토콜 차단 (대소문자 포함)
- 외부 URL 네비게이션 (
http,https,itms-apps)- 내부 라우팅
window.location모킹과 복원이 적절하게 처리되었습니다.frontend/src/pages/MainPage/components/Banner/Banner.tsx (2)
21-31: macintosh 사용자를 iOS 앱스토어로 리다이렉트하는 것이 적절한지 확인 필요Mac 사용자(
macintosh)를 iOS 앱스토어(itms-apps)로 리다이렉트합니다. Mac에서는itms-apps프로토콜이 제대로 동작하지 않을 수 있으며, 사용자 경험이 저하될 수 있습니다.Mac 사용자에게는 웹 앱스토어 링크나 별도의 안내를 제공하는 것이 더 적절할 수 있습니다.
33-64: 배너 클릭 추적 및 앱스토어 링크 처리 - 잘 구현되었습니다.Mixpanel 이벤트 추적과 플랫폼별 앱스토어 링크 처리가 적절하게 구현되었습니다.
handleBannerClick이 배너 메타데이터(bannerId,bannerName)를 받아 추적에 활용하는 패턴이 좋습니다.
#️⃣연관된 이슈
📝작업 내용
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
릴리스 노트
버그 수정
UI 개선
신규 기능
동작 변경
✏️ Tip: You can customize this high-level summary in your review settings.