Type something to search...

03. Nav.jsx — 네비게이션 바

이번 단계에서 할 일

상단 네비게이션 바를 만듭니다. 클릭한 메뉴가 회색 pill 배경으로 바뀌는 기능도 구현합니다.


피그마 디자인 분석

1
┌──────────────────────────────────────────────────┐
2
│ [로고] ┌──────┐ │
3
│ │ Home │ AboutMe Projects │ 높이: 99px
4
│ └──────┘ │
5
└──────────────────────────────────────────────────┘
요소
전체 높이99px
배경색#ffffff
활성 메뉴 배경#f5f5f5, 둥근 pill 모양
텍스트 색#1e1e1e
폰트 크기16px

React Router의 NavLink<a> 태그처럼 링크를 만들지만, 현재 URL과 일치하면 자동으로 active 상태를 알려줍니다.

1
import { NavLink } from 'react-router'
2
3
<NavLink
4
to="#home"
5
className={({ isActive }) =>
6
`nav-item ${isActive ? 'nav-item--active' : ''}`
7
}
8
>
9
Home
10
</NavLink>
  • to → 이동할 경로 (href 대신 to 를 씁니다)
  • className → 함수를 전달하면 { isActive } 를 받아 동적 클래스 설정 가능
  • isActive → 현재 URL이 to 와 일치하면 true, 아니면 false

STEP 1 — Nav.jsx 작성

src/components/Nav.jsx
1
import { NavLink } from 'react-router'
2
3
const Nav = () => {
4
// 메뉴 항목: 화면에 보일 이름과 이동할 해시를 함께 관리
5
const links = [
6
{ label: 'Home', hash: '#home' },
7
{ label: 'AboutMe', hash: '#aboutme' },
8
{ label: 'Projects', hash: '#projects' },
9
]
10
11
return (
12
<nav className="nav">
13
14
{/* 로고 영역 */}
15
<div className="nav-logo">
16
<svg width="30" height="37" viewBox="0 0 30 37" fill="none">
17
<path d="M0 0 L10 37 L20 0 Z" fill="#000" />
18
<path d="M10 0 L30 37 L20 0 Z" fill="#000" />
19
</svg>
20
</div>
21
22
{/* 메뉴 목록 */}
23
<ul className="nav-list">
24
{links.map(({ label, hash }) => (
25
<li key={label}>
26
<NavLink
27
to={hash}
28
className={({ isActive }) =>
29
`nav-item ${isActive ? 'nav-item--active' : ''}`
30
}
31
>
32
{label}
33
</NavLink>
34
</li>
35
))}
36
</ul>
37
38
</nav>
39
)
40
}
41
42
export default Nav

코드 설명

객체 배열 + 구조 분해 { label, hash }

1
const links = [
2
{ label: 'Home', hash: '#home' },
3
{ label: 'AboutMe', hash: '#aboutme' },
4
{ label: 'Projects', hash: '#projects' },
5
]
6
7
{links.map(({ label, hash }) => (
8
<li key={label}>...</li>
9
))}

배열 요소가 객체이므로 { label, hash } 로 구조 분해하여 label(화면에 보일 텍스트)과 hash(이동할 위치)를 꺼냅니다.

key={label} 은 왜 필요한가요? React가 목록에서 각 항목을 구별하기 위해 필요합니다. 없으면 경고가 나옵니다.

1
<NavLink
2
to={hash}
3
className={({ isActive }) =>
4
`nav-item ${isActive ? 'nav-item--active' : ''}`
5
}
6
>
7
{label}
8
</NavLink>
  • to={hash} → 이동할 URL (예: #home)
  • className함수를 전달하면 React Router가 { isActive } 를 자동으로 넣어줍니다
  • isActivetrue'nav-item--active' 클래스 추가

예시:

1
현재 URL: #home
2
Home → isActive = true → className="nav-item nav-item--active"
3
AboutMe → isActive = false → className="nav-item "
4
Projects → isActive = false → className="nav-item "

조건부 표현식

1
`nav-item ${isActive ? 'nav-item--active' : ''}`
  • `백틱` 안에서 ${} 로 JavaScript 표현식을 씁니다
  • isActive ? A : BisActivetrue 면 A, false 면 빈 문자열

STEP 2 — CSS 추가

src/index.css 하단에 추가합니다.

1
/* src/index.css 에 추가 */
2
3
/* ── 네비게이션 ──────────────────────────── */
4
5
.nav {
6
/* 로고와 메뉴를 좌우로 배치 */
7
display: flex;
8
align-items: center;
9
justify-content: space-between;
10
11
height: 99px;
12
padding: 0 24px;
13
background-color: #ffffff;
14
border-bottom: 1px solid #f0f0f0;
15
}
16
17
/* 메뉴 목록: 가로로 나열 */
18
.nav-list {
19
display: flex;
20
gap: 8px; /* 메뉴 간격 */
21
}
22
23
/* 메뉴 항목 기본 스타일 */
24
.nav-item {
25
display: inline-block;
26
padding: 8px 16px;
27
border-radius: 100px; /* pill 모양 (완전히 둥글게) */
28
font-size: 16px;
29
color: #1e1e1e;
30
transition: background-color 0.2s; /* 배경색이 부드럽게 변함 */
31
}
32
33
/* 마우스 올리면 배경 표시 */
34
.nav-item:hover {
35
background-color: #f5f5f5;
36
}
37
38
/* 선택된 메뉴 */
39
.nav-item--active {
40
background-color: #f5f5f5;
41
}

브라우저 확인

저장 후 브라우저에서:

  1. 상단에 로고와 메뉴 3개가 보입니다
  2. 현재 URL 위치에 따라 메뉴에 회색 배경이 생깁니다
  3. 메뉴 클릭 → 해당 섹션으로 스크롤됩니다

정리

개념사용 목적
NavLink현재 URL과 일치하는 링크에 active 상태 자동 적용
to이동할 경로 지정 (href 대신 사용)
isActiveNavLink의 활성 여부를 className 함수로 전달
map메뉴 배열을 <li> 목록으로 변환
구조 분해{ label, hash } 로 객체에서 필요한 값만 꺼내기