Nav

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

이번 단계에서 할 일

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


피그마 디자인 분석

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

새로운 개념: NavLink

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

import { NavLink } from 'react-router'

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

STEP 1 — Nav.jsx 작성

// src/components/Nav.jsx
import { NavLink } from 'react-router'

const Nav = () => {
  // 메뉴 항목: 화면에 보일 이름과 이동할 해시를 함께 관리
  const links = [
    { label: 'Home',     hash: '#home' },
    { label: 'AboutMe',  hash: '#aboutme' },
    { label: 'Projects', hash: '#projects' },
  ]

  return (
    <nav className="nav">

      {/* 로고 영역 */}
      <div className="nav-logo">
        <svg width="30" height="37" viewBox="0 0 30 37" fill="none">
          <path d="M0 0 L10 37 L20 0 Z" fill="#000" />
          <path d="M10 0 L30 37 L20 0 Z" fill="#000" />
        </svg>
      </div>

      {/* 메뉴 목록 */}
      <ul className="nav-list">
        {links.map(({ label, hash }) => (
          <li key={label}>
            <NavLink
              to={hash}
              className={({ isActive }) =>
                `nav-item ${isActive ? 'nav-item--active' : ''}`
              }
            >
              {label}
            </NavLink>
          </li>
        ))}
      </ul>

    </nav>
  )
}

export default Nav

코드 설명

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

const links = [
  { label: 'Home',     hash: '#home' },
  { label: 'AboutMe',  hash: '#aboutme' },
  { label: 'Projects', hash: '#projects' },
]

{links.map(({ label, hash }) => (
  <li key={label}>...</li>
))}

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

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

NavLink — 활성 메뉴 자동 감지

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

예시:

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

조건부 표현식

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

STEP 2 — CSS 추가

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

/* src/index.css 에 추가 */

/* ── 네비게이션 ──────────────────────────── */

.nav {
  /* 로고와 메뉴를 좌우로 배치 */
  display: flex;
  align-items: center;
  justify-content: space-between;

  height: 99px;
  padding: 0 24px;
  background-color: #ffffff;
  border-bottom: 1px solid #f0f0f0;
}

/* 메뉴 목록: 가로로 나열 */
.nav-list {
  display: flex;
  gap: 8px;          /* 메뉴 간격 */
}

/* 메뉴 항목 기본 스타일 */
.nav-item {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 100px; /* pill 모양 (완전히 둥글게) */
  font-size: 16px;
  color: #1e1e1e;
  transition: background-color 0.2s; /* 배경색이 부드럽게 변함 */
}

/* 마우스 올리면 배경 표시 */
.nav-item:hover {
  background-color: #f5f5f5;
}

/* 선택된 메뉴 */
.nav-item--active {
  background-color: #f5f5f5;
}

브라우저 확인

저장 후 브라우저에서:

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

정리

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

댓글 남기기