Skip to content

[FE] SISC1-198 [FEAT] 헤더 적용 및 토글 사이드바 전체 페이지 적용 - #81

Merged
DongEun02 merged 4 commits into
mainfrom
SISC1-198-FE-header-separate
Nov 12, 2025
Merged

DongEun02 merged 4 commits into
mainfrom
SISC1-198-FE-header-separate

Conversation

@DongEun02

@DongEun02 DongEun02 commented Nov 5, 2025 •

Copy link
Copy Markdown
Contributor

1) 작업한 이슈번호

SISC1-198

2) 변경 요약 (What & Why)

  • 무엇을 변경했는지: 헤더 추가 및 사이드바 변경(토글식 사이드바)
  • 왜 변경했는지(문제/목표):

3) 스크린샷/동영상 (UI 변경 시)

전/후 비교, 반응형(모바일/데스크톱) 캡쳐

  • Before:
  • After:
image image

4) 상세 변경사항 (전부 다)

  • 라우팅/페이지: Home.jsx에서 헤더에 들어가는 로그인/회원가입 버튼 삭제
  • 컴포넌트:
    • Header.jsx :
    • Sidebar.jsx : 기존의 사이드바 태그들을 삭제 후 햄버거 바와 로고를 분리하여 헤더로 옮겼습니다.
    • Layout.jsx : useLocation을 사용하여 홈페이지가 아닌 경우에만 margin-left를 주어 사이드바와 겹치지 않게 하였습니다.
  • 상태관리:
  • API 호출:
  • 스타일: Header.module.css, Sidebar.module.css, Home.module.css
  • 기타:

5) 참고사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 상단 헤더 추가: 메뉴 토글, 로고 및 제목으로 루트 이동 지원 및 접근성 개선
    • 헤더 스타일과 반응형 레이아웃 적용
  • 제거

    • 기존 페이지의 로그인/회원가입 버튼 및 관련 헤더 UI 제거
  • 개선 사항

    • 레이아웃 구조 재정비로 UI 일관성 향상
    • 사이드바를 외부 제어(isOpen) 방식으로 단순화하여 상태 관리 최적화

@DongEun02
DongEun02 requested a review from gxuoo as a code owner November 5, 2025 15:45
@coderabbitai

coderabbitai Bot commented Nov 5, 2025 •

Copy link
Copy Markdown

Walkthrough

헤더(UI)를 Header 컴포넌트로 분리하고 Layout이 사이드바 열림 상태를 관리하도록 변경했습니다. Sidebar는 내부 토글 상태를 제거하고 isOpen, isRoot props로 동작하도록 리팩터링되었으며, Home 페이지의 헤더 관련 UI/스타일이 제거되었습니다.

Changes

Cohort / File(s) 변경 내용
신규 Header 컴포넌트
frontend/src/components/Header.jsx, frontend/src/components/Header.module.css
새로운 Header 컴포넌트 추가: isRoot 기반 메뉴 버튼 조건부 렌더링, 로고/타이틀 클릭 시 내비게이션, onToggleSidebar 콜백 수용, 접근성 속성(aria-label, aria-expanded) 포함. CSS 모듈로 고정 헤더 스타일 추가.
Layout 통합 및 상태 관리
frontend/src/components/Layout.jsx
Header를 임포트하고 렌더링하도록 변경. 로컬 상태 isSidebarOpen 도입, onToggleSidebar 전달로 사이드바 열림/닫힘 관리. 메인 영역의 좌측 여백 및 전환 로직 조정.
Sidebar 리팩토링
frontend/src/components/Sidebar.jsx, frontend/src/components/Sidebar.module.css
내부 토글 상태·라우터 의존 제거; 시그니처가 ({ isOpen, isRoot })로 변경. 메뉴 섹션을 명시적 블록으로 단순화하고 isOpen에 따라 open/closed 클래스 적용. 사이드바 관련 일부 CSS 블록 삭제.
Home 페이지 정리
frontend/src/pages/Home.jsx, frontend/src/pages/Home.module.css
페이지에서 헤더 관련 UI 및 내비게이션 핸들러 제거. 헤더/로그인/회원가입 관련 CSS 선택자 삭제.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Header
    participant Layout
    participant Sidebar

    rect rgba(100,150,240,0.08)
    User->>Header: 메뉴 버튼 클릭
    Header->>Layout: onToggleSidebar() 호출
    Layout->>Layout: isSidebarOpen 토글
    Layout->>Header: isOpen prop 갱신
    Layout->>Sidebar: isOpen prop 갱신
    Sidebar->>Sidebar: open/closed 클래스 적용
    end

    rect rgba(120,200,160,0.06)
    User->>Header: 브랜드(로고/타이틀) 클릭
    Header->>Header: useNavigate 호출 (경로 이동)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • 집중 검토 항목:
    • Sidebar.jsx: 접근성(aria-hidden/aria-expanded)·키보드 네비게이션 영향 검증
    • Layout.jsx & Header.jsx: prop/state 동기화와 루트 여부 처리 경계 케이스 확인
    • CSS: 고정 헤더와 사이드바 전환이 다양한 뷰포트에서 겹치지 않는지 확인

Possibly related PRs

Suggested reviewers

  • gxuoo

Poem

🐰 폴짝, 새 헤더로 달려가요 —
사이드바는 살짝 열리고 닫히고,
Layout은 조용히 줄을 맞추네.
컴포넌트들 춤추며 빙글, 빙글 —
배포 전엔 당근 한 입! 🥕

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 주요 변경 사항(헤더 추가 및 토글 사이드바)을 정확히 요약하고 있습니다.
✨ 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 SISC1-198-FE-header-separate

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
frontend/src/components/Layout.jsx (1)

19-27: 선택적 리팩토링: CSS 모듈 사용을 고려하세요.

인라인 스타일이 작동하지만, 일관성을 위해 CSS 모듈로 추출하는 것을 권장합니다. 특히 paddingTop과 marginLeft 값은 유지보수성을 위해 CSS 변수나 모듈 클래스로 관리하는 것이 좋습니다.

예시:

Layout.module.css 파일을 생성하고:

.mainContent {
  display: flex;
  position: relative;
  padding-top: 90px;
  transition: margin-left 0.3s ease;
}

.mainContent.sidebarOpen {
  margin-left: 264px;
}

그리고 컴포넌트에서 사용:

+import styles from './Layout.module.css';

-<main
-  style={{
-    display: 'flex',
-    position: 'relative',
-    paddingTop: '90px',
-    marginLeft: isSidebarOpen && !isRoot ? '264px' : '0',
-    transition: 'margin-left 0.3s ease',
-  }}
->
+<main className={`${styles.mainContent} ${isSidebarOpen && !isRoot ? styles.sidebarOpen : ''}`}>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 907f62d and a1298aa.

📒 Files selected for processing (7)
  • frontend/src/components/Header.jsx (1 hunks)
  • frontend/src/components/Header.module.css (1 hunks)
  • frontend/src/components/Layout.jsx (1 hunks)
  • frontend/src/components/Sidebar.jsx (1 hunks)
  • frontend/src/components/Sidebar.module.css (0 hunks)
  • frontend/src/pages/Home.jsx (0 hunks)
  • frontend/src/pages/Home.module.css (0 hunks)
💤 Files with no reviewable changes (3)
  • frontend/src/pages/Home.module.css
  • frontend/src/pages/Home.jsx
  • frontend/src/components/Sidebar.module.css
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/src/components/Header.jsx (2)
frontend/src/pages/Home.jsx (1)
  • nav (7-37)
frontend/src/App.jsx (1)
  • App (15-34)
frontend/src/components/Layout.jsx (2)
frontend/src/components/Header.jsx (1)
  • Header (5-35)
frontend/src/components/Sidebar.jsx (1)
  • Sidebar (4-122)
🔇 Additional comments (3)
frontend/src/components/Layout.jsx (1)

2-18: 잘 구현되었습니다!

헤더와 사이드바 상태 관리가 깔끔하게 구현되었습니다. useState를 사용한 토글 로직과 Props 전달이 올바르게 작동합니다.

frontend/src/components/Header.jsx (1)

10-19: 훌륭한 접근성 구현입니다!

메뉴 버튼에 aria-label과 aria-expanded 속성을 올바르게 사용하여 스크린 리더 사용자를 위한 접근성이 잘 구현되었습니다.

frontend/src/components/Sidebar.jsx (1)

4-122: 훌륭한 리팩토링입니다!

상태를 부모 컴포넌트로 이동시키고 Props 기반 렌더링으로 변경한 것은 좋은 설계입니다. 컴포넌트가 더 재사용 가능하고 테스트하기 쉬워졌습니다. aria-hidden 속성과 NavLink의 활성/비활성 스타일링도 올바르게 구현되었습니다.

Comment thread frontend/src/components/Header.jsx Outdated
Comment on lines +25 to +32
<div className={styles.right}>
<button className={styles.login} onClick={() => nav('/login')}>
로그인
</button>
<button className={styles.signUp} onClick={() => nav('signup')}>
회원가입
</button>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

경로 표기 방식을 일관되게 유지하세요.

로그인 버튼은 절대 경로('/login')를 사용하지만, 회원가입 버튼은 상대 경로('signup')를 사용합니다. 동일한 레벨의 라우트이므로 일관성을 위해 둘 다 절대 경로를 사용하는 것이 좋습니다.

다음 diff를 적용하세요:

 <button className={styles.login} onClick={() => nav('/login')}>
   로그인
 </button>
-<button className={styles.signUp} onClick={() => nav('signup')}>
+<button className={styles.signUp} onClick={() => nav('/signup')}>
   회원가입
 </button>
📝 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
<div className={styles.right}>
<button className={styles.login} onClick={() => nav('/login')}>
로그인
</button>
<button className={styles.signUp} onClick={() => nav('signup')}>
회원가입
</button>
</div>
<div className={styles.right}>
<button className={styles.login} onClick={() => nav('/login')}>
로그인
</button>
<button className={styles.signUp} onClick={() => nav('/signup')}>
회원가입
</button>
</div>
🤖 Prompt for AI Agents
In frontend/src/components/Header.jsx around lines 25 to 32, the route usage is
inconsistent: the login button uses an absolute path ('/login') while the signup
button uses a relative path ('signup'); update the signup button to use the
absolute path '/signup' (i.e., change the nav call to navigate to '/signup') so
both buttons use consistent absolute route notation.

font-weight: 600;
font-size: 18.53px;
line-height: 120%;
letter-spacing: -3%;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

잘못된 CSS 문법을 수정하세요.

letter-spacing 속성에 -3%가 사용되었지만, 이는 유효하지 않은 CSS 문법입니다. letter-spacing은 길이 단위(px, em, rem 등)만 허용하며 퍼센트 값은 지원하지 않습니다. 브라우저가 이 속성을 무시하게 됩니다.

다음 diff를 적용하여 유효한 단위로 변경하세요:

 .title {
   font-weight: 600;
   font-size: 18.53px;
   line-height: 120%;
-  letter-spacing: -3%;
+  letter-spacing: -0.03em;
   color: white;
 }

 .login {
   border: none;
   border-right: 1px solid #a3a3a3;
   background: none;
   color: #ffffff;
   cursor: pointer;
   font-weight: 500;
   font-size: 16px;
   line-height: 120%;
-  letter-spacing: -3%;
+  letter-spacing: -0.03em;
   width: 90px;
 }

 .signUp {
   border: none;
   border-left: 1px solid #a3a3a3;
   background: none;
   color: #ffffff;
   cursor: pointer;
   font-weight: 500;
   font-size: 16px;
   line-height: 120%;
-  letter-spacing: -3%;
+  letter-spacing: -0.03em;
   width: 100px;
 }

Also applies to: 76-76, 89-89

🤖 Prompt for AI Agents
In frontend/src/components/Header.module.css at lines 39, 76 and 89, the
letter-spacing values use the invalid percentage unit (-3%); replace those
percent values with a valid CSS length unit (for example -0.03em or -3px) so the
property is recognized by browsers — update each occurrence to a concrete length
unit consistent with the design (choose em for scalable type or px for fixed
spacing).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
frontend/src/components/Sidebar.jsx (1)

18-27: 주석 처리된 코드 제거 필요

주석 처리된 "홈" 링크 코드는 데드 코드입니다. 필요 시 Git 히스토리에서 복원할 수 있으므로 제거하는 것이 좋습니다.

             <ul>
-              {/* <li>
-                <NavLink
-                  to="/"
-                  className={({ isActive }) =>
-                    isActive ? styles['active-link'] : styles['inactive-link']
-                  }
-                >
-                  홈
-                </NavLink>
-              </li> */}
               <li>
                 <NavLink
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1298aa and a120f55.

📒 Files selected for processing (4)
  • frontend/src/components/Header.jsx (1 hunks)
  • frontend/src/components/Header.module.css (1 hunks)
  • frontend/src/components/Layout.jsx (1 hunks)
  • frontend/src/components/Sidebar.jsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/src/components/Layout.jsx
  • frontend/src/components/Header.module.css
  • frontend/src/components/Header.jsx
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/Sidebar.jsx (3)
frontend/src/components/Header.jsx (2)
  • isRoot (7-7)
  • nav (8-8)
frontend/src/components/Layout.jsx (1)
  • isRoot (9-9)
frontend/src/pages/Attendance.jsx (1)
  • nav (15-15)
🔇 Additional comments (2)
frontend/src/components/Sidebar.jsx (2)

1-4: 상태 관리 제거 및 제어 컴포넌트로 리팩토링 완료

내부 상태와 불필요한 의존성을 제거하고 부모 컴포넌트로부터 isOpen, isRoot props를 받도록 변경한 것은 올바른 설계입니다. 관심사의 분리가 잘 이루어졌습니다.


14-137: 네비게이션 구조 및 링크 구현 양호

고정된 메뉴 섹션 구조와 NavLink의 isActive 콜백을 활용한 스타일링 패턴이 일관되고 명확합니다. 코드가 깔끔하게 정리되어 있습니다.

Comment on lines +8 to +13
<div
className={`${styles.homeSidebarMenu} ${
!isOpen && isRoot ? styles.closed : styles.open
}`}
aria-hidden={!isOpen}
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

className 조건 로직 오류

9-11번 줄의 조건식이 잘못되었습니다. 현재 로직은 다음과 같이 동작합니다:

  • 사이드바가 닫혀있고(isOpen=false) 루트가 아닌 페이지에서는 styles.open이 적용됨
  • 이는 의도와 반대되는 동작입니다

다음 diff를 적용하여 수정하세요:

       <div
         className={`${styles.homeSidebarMenu} ${
-          !isOpen && isRoot ? styles.closed : styles.open
+          isOpen ? styles.open : styles.closed
         }`}
         aria-hidden={!isOpen}
       >

또는 루트 페이지에서 특별한 동작이 필요한 경우 로직을 명확히 해주세요.

📝 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
<div
className={`${styles.homeSidebarMenu} ${
!isOpen && isRoot ? styles.closed : styles.open
}`}
aria-hidden={!isOpen}
>
<div
className={`${styles.homeSidebarMenu} ${
isOpen ? styles.open : styles.closed
}`}
aria-hidden={!isOpen}
>
🤖 Prompt for AI Agents
In frontend/src/components/Sidebar.jsx around lines 8 to 13, the conditional for
className is inverted: it currently applies styles.open when the sidebar is
closed on non-root pages. Change the condition to check !isRoot instead of
isRoot so the closed class is applied when the sidebar is closed AND the page is
not the root (i.e., use !isOpen && !isRoot ? styles.closed : styles.open); if
you actually need different behavior on the root page, make that logic explicit
and comment it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a120f55 and f921309.

📒 Files selected for processing (2)
  • frontend/src/components/Header.jsx (1 hunks)
  • frontend/src/components/Layout.jsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/Layout.jsx
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/Header.jsx (1)
frontend/src/components/Layout.jsx (1)
  • isRoot (9-9)
🔇 Additional comments (2)
frontend/src/components/Header.jsx (2)

1-29: 과거 리뷰 코멘트가 더 이상 유효하지 않습니다.

이전 리뷰에서 지적된 로그인/회원가입 버튼이 현재 코드에는 존재하지 않습니다. 해당 기능이 제거되었거나 다른 위치로 이동한 것으로 보입니다.


9-20: 접근성 구현이 잘 되어 있습니다.

메뉴 버튼에 aria-label과 aria-expanded 속성을 적절히 사용하여 스크린 리더 사용자를 위한 접근성을 잘 고려했습니다.

Comment on lines +21 to +24
<div className={styles.brand} onClick={() => nav('/')}>
<img className={styles.logo} src={Logo} alt="세종투자연구회 로고" />
<span className={styles.title}>세종투자연구회</span>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

브랜드 영역을 키보드로 접근 가능하도록 변경하세요.

현재 div 요소에 onClick 핸들러를 사용하고 있어 키보드 사용자가 탭 키로 접근하거나 엔터 키로 활성화할 수 없습니다. 버튼 또는 링크 요소를 사용해야 합니다.

다음 diff를 적용하여 접근성을 개선하세요:

-      <div className={styles.brand} onClick={() => nav('/')}>
+      <button
+        className={styles.brand}
+        onClick={() => nav('/')}
+        aria-label="홈으로 이동"
+      >
         <img className={styles.logo} src={Logo} alt="세종투자연구회 로고" />
         <span className={styles.title}>세종투자연구회</span>
-      </div>
+      </button>

참고: CSS에서 button 요소의 기본 스타일을 제거해야 할 수 있습니다:

.brand {
  background: none;
  border: none;
  cursor: pointer;
  /* 기존 스타일 유지 */
}
🤖 Prompt for AI Agents
In frontend/src/components/Header.jsx around lines 21 to 24, replace the
clickable div with a semantic, keyboard-focusable element (preferably a <button
type="button"> or an <a> if it navigates) so keyboard users can tab to and
activate the brand; keep the existing onClick={() => nav('/')} handler, add a
clear aria-label (e.g., aria-label="홈으로 이동"), and remove any JS-only key
handlers; update CSS to neutralize button defaults (background: none; border:
none; cursor: pointer;) so visual styling is preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant