[refactor] 헤더 구조 리펙토링 / 탭 활성 상태 추가 / 각종 UI 버그 수정#775
Conversation
- 포커스 시에 border 바꾸기 - 미디어 쿼리 올바르게 적용
- 기존의 DesktopHeader와 MobileHeader 컴포넌트를 통합하여 Header 컴포넌트로 리팩토링 - 메뉴 열기/닫기 기능을 useState로 관리 - 네비게이션 링크에 경로 추가 및 클릭 시 메뉴 닫기 기능 구현 - styled-components를 활용한 스타일링 적용
- Header 스타일 컴포넌트의 이름을 변경하고 구조를 개선 - 모바일 및 태블릿 뷰에 맞춘 스타일 조정 - 불필요한 스타일 제거 및 가독성 향상
- navigateToHome 함수를 handleHomeClick으로 변경하여 코드 간소화 - 이벤트 트래킹 방식을 속성으로 관리하도록 수정하여 가독성 향상 - 모바일 및 데스크탑 구분을 위한 device_type 속성 추가
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | 변경 요약 |
|---|---|
헤더 스타일 리팩토링 frontend/src/components/common/Header/Header.styles.ts |
기존 스타일명 및 컴포넌트명 변경(예: HeaderStyles→Header, HeaderContainer→Container, LogoButtonStyles→LogoButton), TextCoverStyles·IntroduceButtonStyles 등 제거, Nav, NavLink, MenuBar, MenuButton 신규 추가, 모바일 드로어 관련 스타일 컴포넌트 삭제, isScrolled 기반 그림자·전환·반응형 패딩/갭 적용 |
헤더 컴포넌트 통합 frontend/src/components/common/Header/Header.tsx |
Desktop/Mobile/Drawer 분리 컴포넌트 제거 및 단일 Header로 통합; isMenuOpen, isScrolled 상태 도입; useHeaderNavigation 연동; navLinks에 경로 추가 및 활성 상태 처리; SearchBox 조건 렌더링 및 MenuButton 토글 도입; 믹스패널 추적 호출 유지 |
SearchField 스타일 개선 frontend/src/components/common/SearchField/SearchField.styles.ts |
mediaQuery 도입, 포커스($isFocused) 기반 배경·테두리·필터·전환 추가, 반응형 폰트사이즈 및 모바일 규칙 정리 |
이벤트 상수 추가 frontend/src/constants/eventName.ts |
PATCH_NOTE_BUTTON_CLICKED: 'Patch Note Button Clicked' 신규 추가 |
헤더 네비게이션 훅 리팩토링 frontend/src/hooks/Header/useHeaderNavigation.ts |
useHeaderService → useHeaderNavigation으로 이름 변경; handleHomeClick 구현 변경(검색 리셋 로직 포함); handlePatchNoteClick 추가; handleMenuClick 제거; 공개 반환 인터페이스 갱신 |
모바일 메뉴 훅 제거 frontend/src/services/header/useMobileMenu.ts |
전체 useMobileMenu 훅(기본 export) 및 MobileMenuProp 인터페이스 제거(열기/닫기 상태·Escape 키 리스너·트래킹 로직 포함) |
스크롤 훅 추가 frontend/src/hooks/useScroll.ts |
페이지 스크롤 여부 반환하는 useScroll() 훅 신규 추가 |
Sequence Diagram(s)
sequenceDiagram
participant User
participant Header
participant Nav
participant useHeaderNavigation
participant useScroll
User->>Header: 페이지 진입 / 클릭
Header->>useScroll: 구독 시작
useScroll-->>Header: isScrolled 값을 반환
Header->>Header: 로고/네비게이션/검색/메뉴 버튼 렌더
rect rgb(235,245,255)
Note over User,Header: 메뉴 토글 및 네비게이션
User->>Header: MenuButton 클릭
Header->>Nav: isOpen 토글
Nav-->>User: 메뉴 열림/닫힘 (fixed, backdrop)
User->>Header: NavLink 클릭
Header->>useHeaderNavigation: 핸들러 호출 (home/introduce/club/patch-note)
useHeaderNavigation-->>Header: 라우트 이동 또는 외부링크/트래킹
end
User->>Header: 스크롤
Header->>useScroll: scroll 이벤트
useScroll-->>Header: isScrolled 업데이트
Header->>Header: 스타일 업데이트 (box-shadow 등)
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45분
특히 주의할 파일/영역:
frontend/src/components/common/Header/Header.tsx— 통합된 로직, isMenuOpen/isScrolled 상호작용, 트래킹 호출 위치frontend/src/components/common/Header/Header.styles.ts— 반응형 브레이크포인트, 고정된 Nav의 z-index/포지셔닝(태블릿 동작)frontend/src/hooks/Header/useHeaderNavigation.ts— 이벤트명 사용 및 외부 링크(open) 동작 확인 (PATCH_NOTE_BUTTON_CLICKED)frontend/src/services/header/useMobileMenu.ts제거로 인한 Escape 키 닫기 기능 누락 여부 확인frontend/src/components/common/SearchField/SearchField.styles.ts— 포커스 상태 시 시각적 변화와 접근성 영향
Possibly related issues
- [fix] MOA-240 모바일 헤더 버튼 UI 배치 문제 수정 및 전체 레이아웃 개선 #753 — 모바일 헤더 버튼 UI 배치 및 레이아웃 개선 관련: 본 PR은 모바일 메뉴/버튼 레이아웃을 Nav/MenuButton 방식으로 변경하는 수정사항을 포함하므로 관련될 가능성이 높습니다.
Possibly related PRs
- [style] 모바일 검색창 크기 키우기 #361 — 모바일 헤더 스타일/컴포넌트 변경 관련: Header.styles.ts와 모바일 헤더 구성에 겹침
- [refactor] Header 컴포넌트 리팩터링 - View와 service 로직 분리 및 선언 순서 개선 #340 — 헤더 구현·리팩토링 관련: Header.tsx 및 스타일 변경 이력과 직접 연관
- [feature] 소개페이지 임시 이미지로 대체 및 메뉴바 구현 #366 — 모바일 메뉴 구현(드로어 vs Nav) 충돌 가능성: useMobileMenu 삭제 및 Nav 기반 대체와 상충 가능
Suggested labels
🔨 Refactor
Suggested reviewers
- lepitaaar
- seongje973
- Zepelown
Pre-merge checks and finishing touches
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | PR 제목은 헤더 구조 리팩토링, 탭 활성 상태 추가, UI 버그 수정이라는 주요 변경사항들을 정확하게 반영하고 있습니다. |
| Linked Issues check | ✅ Passed | PR 변경사항들(헤더 구조 단순화, 반응형 처리 개선, 레이아웃/스타일 버그 수정, 활성 내비게이션 표시)이 MOA-240 이슈의 목표를 충족합니다. |
| Out of Scope Changes check | ✅ Passed | 모든 변경사항이 헤더 리팩토링, UI 버그 수정, 관련 훅과 스타일 개선에 집중되어 있으며 범위 내 변경입니다. |
| 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
fix/#753-header-layout-and-mobile-button-MOA-240
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.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
frontend/src/components/common/Header/Header.tsx (1)
57-68: 관리자 페이지에서는 메뉴 버튼을 숨기는 것이 좋습니다
/admin경로에서는 네비게이션과 검색을 숨기면서 메뉴 버튼만 노출되고, 버튼을 눌러도 아무 변화가 없어 혼란을 줍니다.!isAdminPage조건에 메뉴 버튼도 포함시키거나, 버튼 클릭 시 별도 동작을 정의해 주세요.- <Styled.MenuButton - onClick={toggleMenu} - isOpen={isMenuOpen} - aria-label={isMenuOpen ? '메뉴 닫기' : '메뉴 열기'} - > - <span /> - <span /> - <span /> - </Styled.MenuButton> + {!isAdminPage && ( + <Styled.MenuButton + onClick={toggleMenu} + isOpen={isMenuOpen} + aria-label={isMenuOpen ? '메뉴 닫기' : '메뉴 열기'} + aria-expanded={isMenuOpen} + > + <span /> + <span /> + <span /> + </Styled.MenuButton> + )}frontend/src/components/common/Header/Header.styles.ts (1)
20-26: 모바일 패딩 미디어 쿼리가 중복되었습니다
media.mobile블록이 두 번 선언돼 후속 블록이 앞의 설정을 즉시 덮어씁니다. 아마 두 번째는media.mini_mobile을 의도한 것으로 보이니, 각 브레이크포인트가 명확히 구분되도록 수정해 주세요.- ${media.mobile}{ - padding: 5px 20px; - } - - ${media.mobile}{ - padding: 5px 10px; - } + ${media.mobile} { + padding: 5px 20px; + } + + ${media.mini_mobile} { + padding: 5px 10px; + }
📜 Review details
Configuration used: CodeRabbit 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 selected for processing (4)
frontend/src/components/common/Header/Header.styles.ts(1 hunks)frontend/src/components/common/Header/Header.tsx(1 hunks)frontend/src/components/common/SearchField/SearchField.styles.ts(4 hunks)frontend/src/services/header/useHeaderService.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.
Files:
frontend/src/services/header/useHeaderService.tsfrontend/src/components/common/Header/Header.tsxfrontend/src/components/common/SearchField/SearchField.styles.tsfrontend/src/components/common/Header/Header.styles.ts
frontend/**/*.tsx
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.tsx: Abstract complex logic/interactions into dedicated components or higher-order 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.
Break down broad state management into smaller, focused hooks or contexts.
Use component composition instead of props drilling.
Files:
frontend/src/components/common/Header/Header.tsx
🧬 Code graph analysis (4)
frontend/src/services/header/useHeaderService.ts (2)
frontend/src/store/useSearchStore.ts (1)
useSearchStore(14-24)frontend/src/constants/eventName.ts (1)
EVENT_NAME(1-20)
frontend/src/components/common/Header/Header.tsx (1)
frontend/src/components/common/Header/Header.styles.ts (1)
Header(4-27)
frontend/src/components/common/SearchField/SearchField.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
media(8-14)
frontend/src/components/common/Header/Header.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
media(8-14)
- useHeaderService를 useHeaderNavigation으로 리네이밍 및 경로 변경 (services/header → components/common/Header) - 패치노트 외부 링크 클릭 핸들러 추가 (Notion 페이지 연결) - MenuButton의 span을 MenuBar styled-component로 분리 - PATCH_NOTE_BUTTON_CLICKED 이벤트 추적 추가
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
frontend/src/components/common/Header/Header.tsx (1)
26-34: 과거 리뷰 이슈가 해결되었습니다이전 리뷰에서 지적된 빈 핸들러 문제가 해결되었습니다.
handlePatchNoteClick이useHeaderNavigation훅에서 올바르게 구현되어 Notion 페이지로 이동하는 기능을 수행합니다.frontend/src/components/common/Header/useHeaderNavigation.ts (1)
11-18: 매직 넘버 제거 필수 (과거 리뷰 미해결)이전 리뷰에서 지적되었으나 여전히
window.innerWidth <= 700하드코딩이 남아있습니다. 이는 코딩 가이드라인의 "매직 넘버 금지" 원칙을 위반하며, 스타일에서 사용하는BREAKPOINT.mobile과 불일치하여 Mixpanel 트래킹 데이터가 부정확할 수 있습니다.다음 diff를 적용하여 공용 브레이크포인트 상수를 사용하도록 수정해주세요:
+import { BREAKPOINT } from '@/styles/breakpoint'; + const useHeaderNavigation = () => { const navigate = useNavigate(); const trackEvent = useMixpanelTrack(); const handleHomeClick = useCallback(() => { navigate('/'); useSearchStore.getState().resetSearch(); - // 속성으로 관리 trackEvent(EVENT_NAME.HOME_BUTTON_CLICKED, { - device_type: window.innerWidth <= 700 ? 'mobile' : 'desktop', + device_type: window.innerWidth <= BREAKPOINT.mobile ? 'mobile' : 'desktop', }); }, [navigate, trackEvent]);Based on coding guidelines
🧹 Nitpick comments (2)
frontend/src/components/common/Header/Header.tsx (1)
76-76: TODO 주석 처리 지원 가능동아리 관리자 프로필 추가에 대한 TODO가 남아있습니다.
이 기능 구현을 위한 이슈를 생성하거나 기본 구조를 제안해드릴까요?
frontend/src/components/common/Header/Header.styles.ts (1)
65-75: 브레이크포인트 상수화 권장
@media (max-width: 870px)가 하드코딩되어 있어 다른 곳에서 사용하는media헬퍼와 일관성이 떨어집니다. 이 값이 데스크탑/모바일 로고 전환 시점이므로,BREAKPOINT에 상수로 정의하거나 기존 브레이크포인트를 재사용하는 것을 권장합니다.다음과 같이 수정할 수 있습니다:
Option 1: 기존 tablet 브레이크포인트 재사용 (권장)
- @media (max-width: 870px) { + ${media.tablet} { .desktop-logo { display: none; }Option 2: 새로운 브레이크포인트 상수 정의
먼저
frontend/src/styles/breakpoint.ts에 추가:export const BREAKPOINT = { // ... 기존 값들 logo_switch: 870, };그리고
mediaQuery.ts에 추가:export const media = { // ... 기존 값들 logo_switch: `@media (max-width: ${BREAKPOINT.logo_switch}px)`, };그 후 이 파일에서:
- @media (max-width: 870px) { + ${media.logo_switch} {Based on coding guidelines
📜 Review details
Configuration used: CodeRabbit 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 selected for processing (5)
frontend/src/components/common/Header/Header.styles.ts(1 hunks)frontend/src/components/common/Header/Header.tsx(1 hunks)frontend/src/components/common/Header/useHeaderNavigation.ts(2 hunks)frontend/src/constants/eventName.ts(1 hunks)frontend/src/services/header/useMobileMenu.ts(0 hunks)
💤 Files with no reviewable changes (1)
- frontend/src/services/header/useMobileMenu.ts
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.
Files:
frontend/src/constants/eventName.tsfrontend/src/components/common/Header/Header.styles.tsfrontend/src/components/common/Header/useHeaderNavigation.tsfrontend/src/components/common/Header/Header.tsx
frontend/**/*.tsx
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.tsx: Abstract complex logic/interactions into dedicated components or higher-order 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.
Break down broad state management into smaller, focused hooks or contexts.
Use component composition instead of props drilling.
Files:
frontend/src/components/common/Header/Header.tsx
🧬 Code graph analysis (3)
frontend/src/components/common/Header/Header.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
media(8-14)
frontend/src/components/common/Header/useHeaderNavigation.ts (2)
frontend/src/store/useSearchStore.ts (1)
useSearchStore(14-24)frontend/src/constants/eventName.ts (1)
EVENT_NAME(1-21)
frontend/src/components/common/Header/Header.tsx (2)
frontend/src/components/common/Header/Header.styles.ts (1)
Header(4-27)frontend/src/constants/eventName.ts (1)
EVENT_NAME(1-21)
🔇 Additional comments (6)
frontend/src/constants/eventName.ts (1)
20-20: LGTM!패치노트 버튼 클릭 이벤트 상수가 올바르게 추가되었습니다. 기존 패턴을 따르고 있으며,
useHeaderNavigation훅에서 적절히 사용되고 있습니다.frontend/src/components/common/Header/useHeaderNavigation.ts (1)
30-36: LGTM!패치노트 핸들러가 올바르게 구현되어 새 탭에서 Notion 페이지를 열고 이벤트 트래킹을 수행합니다.
frontend/src/components/common/Header/Header.styles.ts (3)
4-27: LGTM!헤더와 컨테이너의 반응형 스타일이
media헬퍼를 사용하여 일관되게 구현되었습니다.max-width: 1100px설정으로 콘텐츠가 적절히 제한되어 1280px 이상 화면에서의 레이아웃 버그가 해결되었습니다.
77-98: LGTM!
Nav컴포넌트의 반응형 전환이 잘 구현되었습니다.isOpenprop을 활용한 모바일 메뉴의 슬라이드 애니메이션이 자연스럽고, 태블릿 이하에서 fixed 위치로 전환되는 로직이 적절합니다.
136-170: LGTM!햄버거 메뉴 버튼의 X 자 애니메이션이
MenuBar의 transform을 활용하여 매끄럽게 구현되었습니다.isOpen상태에 따른 각 bar의 회전과 투명도 변화가 자연스럽습니다.frontend/src/components/common/Header/Header.tsx (1)
61-72:location.pathname === link.path로직은 현 구조에서 정상 동작합니다
App.tsx에/introduce,/club-union,/patch-note하위에 중첩 Route 정의가 없으므로 활성 표시가 사라질 우려가 없습니다.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
frontend/src/hooks/Header/useHeaderNavigation.ts (1)
15-17: 디바이스 판별 상수화 필요
window.innerWidth <= 700매직 넘버는 스타일 계층의 브레이크포인트와 어긋나 Mixpaneldevice_type통계가 왜곡될 수 있습니다. 공용 브레이크포인트 상수를 가져와 동일한 기준을 쓰도록 수정해주세요.-import { useSearchStore } from '@/store/useSearchStore'; -import useMixpanelTrack from '@/hooks/useMixpanelTrack'; -import { EVENT_NAME } from '@/constants/eventName'; +import { useSearchStore } from '@/store/useSearchStore'; +import useMixpanelTrack from '@/hooks/useMixpanelTrack'; +import { EVENT_NAME } from '@/constants/eventName'; +import { BREAKPOINT } from '@/styles/breakpoint'; ... - device_type: window.innerWidth <= 700 ? 'mobile' : 'desktop', + device_type: + typeof window !== 'undefined' && window.innerWidth <= BREAKPOINT.mobile + ? 'mobile' + : 'desktop',As per coding guidelines.
📜 Review details
Configuration used: CodeRabbit 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 selected for processing (4)
frontend/src/components/common/Header/Header.styles.ts(1 hunks)frontend/src/components/common/Header/Header.tsx(1 hunks)frontend/src/hooks/Header/useHeaderNavigation.ts(2 hunks)frontend/src/hooks/useScroll.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/common/Header/Header.styles.ts
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.
Files:
frontend/src/hooks/useScroll.tsfrontend/src/components/common/Header/Header.tsxfrontend/src/hooks/Header/useHeaderNavigation.ts
frontend/**/*.tsx
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.tsx: Abstract complex logic/interactions into dedicated components or higher-order 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.
Break down broad state management into smaller, focused hooks or contexts.
Use component composition instead of props drilling.
Files:
frontend/src/components/common/Header/Header.tsx
🧠 Learnings (4)
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Applied to files:
frontend/src/components/common/Header/Header.tsx
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Applied to files:
frontend/src/components/common/Header/Header.tsxfrontend/src/hooks/Header/useHeaderNavigation.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Applied to files:
frontend/src/components/common/Header/Header.tsxfrontend/src/hooks/Header/useHeaderNavigation.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Applied to files:
frontend/src/hooks/Header/useHeaderNavigation.ts
🧬 Code graph analysis (2)
frontend/src/components/common/Header/Header.tsx (3)
frontend/src/components/common/Header/Header.styles.ts (1)
Header(4-31)frontend/src/hooks/useScroll.ts (1)
useScroll(3-16)frontend/src/constants/eventName.ts (1)
EVENT_NAME(1-21)
frontend/src/hooks/Header/useHeaderNavigation.ts (2)
frontend/src/store/useSearchStore.ts (1)
useSearchStore(14-24)frontend/src/constants/eventName.ts (1)
EVENT_NAME(1-21)
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (7)
frontend/src/components/common/Header/Header.styles.ts (7)
11-31: 매직 넘버를 명명된 상수로 교체하세요.헤더의 높이와 패딩 값들이 하드코딩되어 있습니다. 유지보수성과 일관성을 위해 이러한 값들을 명명된 상수로 정의하는 것이 좋습니다.
Based on learnings
파일 상단에 상수를 정의하세요:
const HEADER_HEIGHT = { DESKTOP: 62, TABLET: 56, } as const; const HEADER_PADDING = { DESKTOP: { vertical: 10, horizontal: 20 }, TABLET: { vertical: 10, horizontal: 20 }, MOBILE: { vertical: 5, horizontal: 20 }, MINI_MOBILE: { vertical: 5, horizontal: 10 }, } as const;그런 다음 이러한 상수를 스타일에 적용하세요:
height: 62px; - padding: 10px 20px; + height: ${HEADER_HEIGHT.DESKTOP}px; + padding: ${HEADER_PADDING.DESKTOP.vertical}px ${HEADER_PADDING.DESKTOP.horizontal}px;
39-51: 간격 값을 명명된 상수로 정의하세요.Container의 max-width와 gap 값들이 하드코딩되어 있습니다.
Based on learnings
const CONTAINER_MAX_WIDTH = 1100; const CONTAINER_GAP = { DESKTOP: 50, TABLET: 35, MOBILE: 30, MINI_MOBILE: 15, } as const;
57-57: 간격 값을 명명된 상수로 정의하세요.LeftSection의 gap 값(45px)을 명명된 상수로 정의하여 일관성을 유지하세요.
Based on learnings
91-107: 매직 넘버를 명명된 상수로 교체하세요.Nav의 gap, top position, border-radius 값들을 명명된 상수로 정의하세요. 특히
top: 56px는 태블릿 헤더 높이와 일치하므로 같은 상수를 재사용해야 합니다.Based on learnings
const NAV_GAP = 45; const NAV_BORDER_RADIUS = 20;그리고 top position은 이전에 정의한 HEADER_HEIGHT를 재사용하세요:
${media.tablet} { position: fixed; - top: 56px; + top: ${HEADER_HEIGHT.TABLET}px;
114-133: 매직 넘버와 색상 값을 명명된 상수로 정의하세요.NavLink의 font-size, padding, margin 값과 색상 값들을 명명된 상수로 정의하세요.
Based on learnings
const NAV_LINK = { FONT_SIZE: 14, PADDING: { vertical: 12, horizontal: 24 }, MARGIN_BOTTOM: 16, } as const; const COLORS = { ACTIVE: '#FF5414', DEFAULT: '#3A3A3A', } as const;
140-143: 매직 넘버를 명명된 상수로 교체하세요.MenuBar의 height, border-radius 값들을 명명된 상수로 정의하세요.
Based on learnings
153-180: 매직 넘버를 명명된 상수로 교체하세요.MenuButton의 크기와 transform offset 값들을 명명된 상수로 정의하세요. 특히
8.25pxtransform 값은 여러 곳에서 반복되므로 명명된 상수로 정의하는 것이 중요합니다.Based on learnings
const MENU_BUTTON = { WIDTH: { TABLET: 24, MOBILE: 20 }, HEIGHT: 18, TRANSFORM_OFFSET: 8.25, // Half of MenuBar spacing for X animation } as const;그런 다음 이 상수들을 적용하세요:
- width: 24px; - height: 18px; + width: ${MENU_BUTTON.WIDTH.TABLET}px; + height: ${MENU_BUTTON.HEIGHT}px; ${MenuBar}:nth-child(1) { transform: ${({ isOpen }) => - isOpen ? 'translateY(8.25px) rotate(45deg)' : 'none'}; + isOpen ? `translateY(${MENU_BUTTON.TRANSFORM_OFFSET}px) rotate(45deg)` : 'none'}; }
📜 Review details
Configuration used: CodeRabbit 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 selected for processing (2)
frontend/src/components/common/Header/Header.styles.ts(1 hunks)frontend/src/components/common/Header/Header.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/common/Header/Header.tsx
🧰 Additional context used
📓 Path-based instructions (1)
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.
Files:
frontend/src/components/common/Header/Header.styles.ts
🧠 Learnings (1)
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
🧬 Code graph analysis (1)
frontend/src/components/common/Header/Header.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
media(8-14)
suhyun113
left a comment
There was a problem hiding this comment.
PR 엄청 자세히 작성해주셔서 이해하기 쉬웠어요!
컴포넌트 구조 단순화로 코드량이 크게 감소한 것 같아서 좋았습니다ㅏ
자잘한 버그들이 많았는데, 다 수정해주신거 감사합니다!
훨씬 보기 좋고 깔끔해진 것 같아요~
수고 많으셨어요!!👍
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
frontend/src/components/common/Header/Header.styles.ts (2)
3-3: 불필요한 MSW 테스트 라이브러리 import를 제거하세요.프로덕션 스타일 파일에서 테스트용 MSW 라이브러리를 import하고 있으며,
e변수는 사용되지 않습니다.
52-78: 커스텀 브레이크포인트를 미디어 쿼리 헬퍼로 교체하고 로고 너비를 상수로 정의하세요.870px 커스텀 브레이크포인트는 다른 부분에서 사용하는
media헬퍼와 일관되지 않으며, 로고 너비 값들도 명명된 상수로 정의되어야 합니다.Based on learnings
🧹 Nitpick comments (3)
frontend/src/components/common/Header/Header.styles.ts (3)
26-44: 반응형 gap 값을 명명된 상수로 정의하는 것을 권장합니다.Container의 gap 값들(50px, 35px, 30px, 15px)이 반복적으로 사용되고 있습니다. 코딩 가이드라인에 따라 이를 명명된 상수로 추출하면 유지보수성이 향상됩니다.
파일 상단에 상수를 정의하세요:
const CONTAINER_GAP = { DEFAULT: 50, TABLET: 35, MOBILE: 30, MINI_MOBILE: 15, } as const;그리고 다음과 같이 적용하세요:
export const Container = styled.div` display: flex; align-items: center; justify-content: space-between; width: 100%; max-width: 1100px; margin: 0 auto; - gap: 50px; + gap: ${CONTAINER_GAP.DEFAULT}px; ${media.tablet} { - gap: 35px; + gap: ${CONTAINER_GAP.TABLET}px; } ${media.mobile} { - gap: 30px; + gap: ${CONTAINER_GAP.MOBILE}px; } ${media.mini_mobile} { - gap: 15px; + gap: ${CONTAINER_GAP.MINI_MOBILE}px; } `;Based on learnings
80-101: Nav의 고정 위치 값이 Header 높이와 동기화되는지 확인하세요.Line 87의
top: 56px는 Line 21의 Header tablet 높이와 일치해야 합니다. Header 높이가 변경될 경우 Nav 위치도 함께 업데이트되어야 하므로, 이 값을 상수로 추출하여 두 곳에서 공유하는 것을 권장합니다.다음과 같이 공유 상수를 정의할 수 있습니다:
const HEADER_HEIGHT = { DEFAULT: 62, TABLET: 56, } as const;그리고 Header와 Nav에서 참조하세요:
export const Header = styled.header<{ isScrolled: boolean }>` // ... - height: 62px; + height: ${HEADER_HEIGHT.DEFAULT}px; ${media.tablet} { - height: 56px; + height: ${HEADER_HEIGHT.TABLET}px; } `; export const Nav = styled.nav<{ isOpen: boolean }>` // ... ${media.tablet} { - top: 56px; + top: ${HEADER_HEIGHT.TABLET}px; } `;Based on learnings
103-127: 활성 상태 표시 로직이 잘 구현되었습니다.
isActiveprop을 통한 네비게이션 링크의 활성 상태 표시가 깔끔하고, 데스크톱과 모바일에서 각각 적절한 시각적 피드백을 제공하고 있습니다.참고: Line 109의 활성 색상
#FF5414와 Line 121의rgba(255, 84, 20, 0.08)를 테마 상수로 추출하면 일관성을 더 높일 수 있습니다.
📜 Review details
Configuration used: CodeRabbit 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 selected for processing (1)
frontend/src/components/common/Header/Header.styles.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.
Files:
frontend/src/components/common/Header/Header.styles.ts
🧠 Learnings (6)
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Define constants near related logic or ensure names link them clearly.
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
📚 Learning: 2025-07-19T05:09:10.702Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Applied to files:
frontend/src/components/common/Header/Header.styles.ts
🧬 Code graph analysis (1)
frontend/src/components/common/Header/Header.styles.ts (1)
frontend/src/styles/mediaQuery.ts (1)
media(8-14)
🔇 Additional comments (2)
frontend/src/components/common/Header/Header.styles.ts (2)
5-24: 헤더 전체 너비 적용 및 스크롤 상태 기반 스타일 처리가 잘 구현되었습니다.
width: 100%적용으로 헤더 잘림 문제가 해결되었고,isScrolledprop을 통한 box-shadow 조건부 적용이 깔끔합니다.
129-173: 햄버거 메뉴 애니메이션이 자연스럽게 구현되었습니다.
MenuBar를nth-child로 제어하여 햄버거 → X 전환 애니메이션을 처리한 방식이 효과적입니다.transform과opacity를 조합한 애니메이션 로직이 매끄럽습니다.
#️⃣연관된 이슈
📝작업 내용
헤더 컴포넌트 구조를 개선하고 반응형 처리를 CSS로 전환했습니다
주요 변경사항
1. 컴포넌트 구조 단순화 및 반응형 개선
기존 모바일 메뉴바를 DOM 조작 방식에서 CSS 기반 반응형으로 전환했습니다.
변경 내용
효과
2. 레이아웃 버그 수정
2-1. 헤더 너비 제한으로 인한 화면 잘림 현상
2-1. 헤더 레이아웃 개선
Container max-width로 콘텐츠 제한하여 해결
2-2. 검색창 내부 색상 불일치
2-3. 반응형 미적용으로 인한 네비게이션 버튼 누락
2-4. 모바일 메뉴바 레이아웃 미지정
3. 기능 추가
4. 파일 구조 개선
useHeaderService → useHeaderNavigation 변경
service/header→components/header옆으로 이동제거된 항목
5. 일관된 패딩 적용
@seongwon030 PR #773 과 동일하게 헤더에도 전역 패딩 적용
향후 계획
중점적으로 리뷰받고 싶은 부분(선택)
피드백, 칭찬, 궁금증 대환영
논의하고 싶은 부분(선택)
믹스패널 이벤트 이름이 통일되지 않아 이벤트 발생 위치를 파악하기 어렵고 네이밍도 쉽지 않네용
팀 차원에서 네이밍 규칙을 정립하면 좋을 것 같습니다.
🫡 참고사항
Summary by CodeRabbit
새로운 기능
개선 사항