[#52] React Router

2025. 4. 11. 15:22·LG 유플러스 유레카 SW/React
목차
  1. React Router란?
  2. 🛠️ 설치
  3. ✏️ 구현 방식
  4. ✨ <Outlet />
  5. ✨ children
  6. 중첩 라우팅(Nested Routing)
  7. <Link> 태그
  8. <NavLink> 태그
  9. NotFound 설정
  10. 📍 페이지 컴포넌트는 Page 접미사 붙이기
  11. 📁 실무용 폴더 구조
  12. Swipper
  13. 🛠️설치
  14. 🔥 React에서 사용법 (feat. autoplay)
  15. json-server
  16. 📁 React public 폴더

React Router란?

React에서 라우팅을 구현하기 위한 표준 라이브러리

웹 애플리케이션에서 여러 페이지를 쉽게 관리하고 내비게이션을 구현할 수 있게 해줌

 

🛠️ 설치

npm i react-router-dom

 

✏️ 구현 방식

1️⃣ createBrowserRouter + <RouterProvider>

import { createBrowserRouter, RouterProvider } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
  },
]);

export default function Router() {
  return <RouterProvider router={router} />;
}
  • React Router v6.4 이상부터 지원하는 새로운 방식
  • 라우팅 설정을 자바스크립트 객체 배열로 작성
  • 코드로 관리하기 때문에
    • 페이지 전환,
    • 로딩 처리(loader)
    • 에러 처리(errorElement)
    • 데이터 가져오기 (loader/action) 같은 고급 기능 쓰기 편함
  • 좀 더 구조적이고 대규모 앱에 어울림

✅ createBrowserRouter ➔ RouterProvider로 연결

 

2️⃣ <BrowserRouter> + <Routes>

import { BrowserRouter, Routes, Route } from "react-router-dom";

export default function Router() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
      </Routes>
    </BrowserRouter>
  );
}
  • 옛날부터 쓰던 전통적인 방식
  • JSX 안에서 직접 <Route>로 설정
  • 간단한 앱이나 페이지가 적을 때 편하고 직관적
  • 다만 페이지 많아지면 복잡해지고 유지보수가 힘들 수 있음

✅ <BrowserRouter> ➔ <Routes> ➔ <Route>로 트리 구조

 

✨ <Outlet />

  • 자식 라우트를 렌더링하는 자리
  • 부모 컴포넌트 안에 <Outlet />을 넣으면, 현재 매칭된 자식 경로의 컴포넌트가 표시됨
import React from "react";
import { Outlet } from "react-router-dom";

const Default = () => {
  return (
    <div>
      <Header />
      <Outlet />
      <Footer />
    </div>
  );
};

export default Default;

 

✨ children

부모 경로 안에 들어가는 자식 페이지 목록

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Default from "./layout/Default";
import AboutPage from "./pages/AboutPage";
import MainPage from "./pages/MainPage";
import ShopPage from "./pages/ShopPage";
import BlogPage from "./pages/BlogPage";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Default />, // 부모 컴포넌트
    children: [
      // 부모 안에 들어가는 자식 페이지들
      {
        path: "",
        element: <MainPage />,
      },
      {
        path: "about",
        element: <AboutPage />,
      },
      {
        path: "shop",
        element: <ShopPage />,
      },
      {
        path: "blog",
        element: <BlogPage />,
      },
    ],
  },
]);

export default function Router() {
  return <RouterProvider router={router} />;
}

 

중첩 라우팅(Nested Routing)

페이지 안에 페이지가 들어가는 구조

Router (루트 라우터)
 └─ Default (공통 레이아웃, 예: Header, Footer)
     └─ Outlet (여기에 자식들이 들어옴)
         └─ MainPage (메인 화면 레이아웃)
             └─ Outlet (여기에 다시 하위 자식들이 들어옴)
                 └─ MainSub1Page (메인 페이지의 서브 내용)
{
  path: "",
  element: <MainPage />,
  children: [
    {
      path: "",
      element: <MainSub1Page />,
    },
  ],
}
  • 부모 라우트의 Outlet 자리에 자식 라우트가 렌더링됨
import React from "react";
import { Outlet } from "react-router-dom";

const MainPage = () => {
  return (
    <div>
      <h2>MainPage</h2>
      <div>메인 페이지입니다.</div>
      <nav>
        <a href="">리스트1</a>
        <a href="">리스트2</a>
        <a href="">리스트3</a>
      </nav>
      <div>아래는 outlet 영역입니다.</div>
      <Outlet />
    </div>
  );
};

export default MainPage;

 

<Link> 태그

React Router에서 <a> 대신 쓰는 내부 페이지 이동용 컴포넌트

  • 새로고침 없이 SPA 방식으로 부드럽게 이동 가능
  • 속성으로 to="경로" 사용
import React from "react";
import { Link } from "react-router-dom";

const Header = () => {
  return (
    <header>
      <h1>
        <Link to={"/"}>로고</Link>
      </h1>
      <nav>
        <Link to={"/about"}>회사 소개</Link>
        <Link to={"/shop"}>쇼핑</Link>
        <Link to={"/blog"}>블로그</Link>
      </nav>
    </header>
  );
};

export default Header;

 

<NavLink> 태그

현재 경로와 일치하면 자동으로 클래스(class)를 추가해주는 Link

import { NavLink } from "react-router-dom";

<NavLink to="/about">회사 소개</NavLink>

➡️ 기본적으로 현재 URL이 to="/about"와 일치하면 class="active"가 자동으로 붙음

➡️ active 상태일 때 커스텀 스타일링 가능

<Link> <NavLink>
그냥 이동만 함 이동 + 현재 위치면 스타일 바꿔줌
강조 불가 강조 가능 (isActive)

 

🪄 NavLink의 active 스타일 적용 방법

1️⃣ 전역 CSS (index.css) 사용 시

<NavLink to={"/about"}>
  회사 소개
</NavLink>
/* index.css */
.active {
  color: red;
}

2️⃣ CSS 모듈 (Header.module.css) 사용 시

<NavLink
  className={({ isActive }) => (isActive ? styles.active : "")}
  to={"/about"}
>
  회사 소개
</NavLink>
/* Header.module.css */
.active {
  color: red;
}

👉🏻 NavLink는 기본 active 클래스를 붙여주지만 CSS 모듈은 파일마다 클래스 이름이 바뀌기 때문에 그걸 못 알아봄

👉🏻 클래스 이름으로 스타일 적용 불가

👉🏻 구조적으로 .hd > div 이런 식으로 접근하거나,

👉🏻 isActive로 styles.active를 직접 연결해줘야 함

항목 전역 CSs CSS 모듈
파일 이름 index.css Header.module.css
클래스 이름 .active (그대로) .active → 내부적으로 랜덤이름
NavLink 설정 그냥 NavLink className={({ isActive }) => (isActive ? styles.active : "")}
관리 방식 사이트 전체 공유 파일별로 스타일 독립

 

NotFound 설정

잘못된 경로로 접근했을 때, "404 Not Found" 같은 메시지를 보여주는 안전장치

  • 레이아웃 없이 NotFound만 띄우기 위해서는 라우트 최상단에서 path="*"로 따로 빼서 설정
  • path: "*" 는 모든 경로를 의미
  • 위에서 정의한 /, /about, /shop, /blog 에 일치하지 않는 모든 URL은 자동으로 NotFound 페이지로 이동
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Default from "./layout/Default";
import MainPage from "./pages/MainPage";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Default />,
    children: [
      {
        path: "/sub1",
        element: <MainPage />,
      },
    ],
  },
  {
    path: "*",
    element: <NotFound />,
  },
]);

export default function Router() {
  return <RouterProvider router={router} />;
}

 


📍 페이지 컴포넌트는 Page 접미사 붙이기

  • 컴포넌트 파일 많은 프로젝트에서는 Page 컴포넌트와 UI 컴포넌트를 명확히 구분하f는 게 중요
  • 폴더나 파일 이름만 봐도 바로 "아 얘는 페이지네" 파악 가능
  • 파일 찾기도 편하고, 유지보수도 쉬워짐
src/
  pages/
    AboutPage.jsx
    LoginPage.jsx
    ProductsPage.jsx
  components/
    Header.jsx
    Footer.jsx
    Card.jsx
    Button.jsx

페이지 컴포넌트 ➔ Page 붙이기 (AboutPage.jsx)

일반 UI 컴포넌트 ➔ 그냥 이름 (Button.jsx, Card.jsx)

 

📁 실무용 폴더 구조

페이지 단위로 폴더를 나누고, 관련 파일을 모아 관리하는 방식을 많이 쓴다 !

src/
├── pages/
│   ├── AboutPage/
│   │   ├── AboutPage.jsx         // 페이지 컴포넌트
│   │   ├── AboutPage.module.css  // 스타일 파일
│   │   ├── useAboutData.js       // 전용 훅 (데이터 가져오기 등)
│   │   ├── AboutService.js       // API 관련 함수
│   │   └── components/           // About 전용 하위 컴포넌트
│   │       ├── AboutCard.jsx
│   │       └── AboutCard.module.css
│   │

 

  • 관련 파일을 한 곳에 모아서 관리 ➔ 파일 찾기 쉬움
  • 기능별로 나누니까 확장성이 좋음 ➔ 기능 추가할 때 깔끔
  • 리팩토링할 때 폴더 단위로 이동/삭제/추가가 쉬움
  • 팀원끼리 컨벤션 통일 ➔ 협업하기 편함

 

 

Swipper

슬라이더(캐러셀)를 쉽게 만들 수 있는 라이브러리

🛠️설치

npm install swiper

https://swiperjs.com/get-started

 

Swiper - The Most Modern Mobile Touch Slider

Swiper is the most modern free mobile touch slider with hardware accelerated transitions and amazing native behavior.

swiperjs.com

 

🔥 React에서 사용법 (feat. autoplay)

  • pages/MainPage.jsx
import React from "react";
import { Outlet } from "react-router-dom";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, Pagination, Navigation } from "swiper/modules";

const MainPage = () => {
  return (
    <div>
      <h2>MainPage</h2>
      <div>
        <Swiper
          slidesPerView={3} // 한번에 보이는 슬라이드 수
          spaceBetween={30} // 슬라이드 사이 간격(px)
          centeredSlides={true} // 활성화된 슬라이드 가운데로 정렬
          autoplay={{
            delay: 2500, // 지정된 ms마다 자동으로 다음 슬라이드 이동
            disableOnInteraction: false, // 사용자가 슬라이드를 터치하거나 드래그했을 때 autoplay 동작 제어
          }}
          pagination={{ // 페이지네이션 추가
            clickable: true,
          }}
          navigation={true} // 좌우 화살표 버튼 추가
          modules={[Autoplay, Pagination, Navigation]}
          className="silder" // 커스텀 스타일링을 위해 클래스명 부여
        >
          <SwiperSlide>
            <div>
              <img src="/img/Img_bg1.jpg" alt="" />
            </div>
          </SwiperSlide>
          <SwiperSlide>Slide 2</SwiperSlide>
          <SwiperSlide>Slide 3</SwiperSlide>
          <SwiperSlide>Slide 4</SwiperSlide>
          <SwiperSlide>Slide 5</SwiperSlide>
          <SwiperSlide>Slide 6</SwiperSlide>
          <SwiperSlide>Slide 7</SwiperSlide>
          <SwiperSlide>Slide 8</SwiperSlide>
          <SwiperSlide>Slide 9</SwiperSlide>
        </Swiper>
      </div>
      <nav>
        <a href="">리스트1</a>
        <a href="">리스트3</a>
        <a href="">리스트3</a>
      </nav>
      <div>아래는 outlet 영역입니다.</div>
      <Outlet />
    </div>
  );
};

export default MainPage;
  • Main.jsx
    • Swiper 전역 스타일 import (한 번만 import해서, 전역에서 슬라이더 쓸 수 있도록 함)
// Import Swiper styles
import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";

https://swiperjs.com/demos#autoplay

 

Swiper Demos

Swiper is the most modern free mobile touch slider with hardware accelerated transitions and amazing native behavior.

swiperjs.com

 

📚 onSwiper + useRef로 Swiper 직접 조작하는 방법

onSwiper로 Swiper 인스턴스를 useRef에 저장하고, 직접 만든 버튼으로 슬라이드를 제어

useRef() 빈 그릇 만들기 (null로 시작)
onSwiper Swiper가 완성될 때 인스턴스를 ref에 담아줌
버튼 조작 slidePrev(), slideNext() 등 메서드 호출로 직접 이동

ex)

import { useRef } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";

export default function CustomSwiper() {
  const swiperRef = useRef(null); // Swiper 인스턴스 담을 ref 생성

  return (
    <div>
      <Swiper
        onSwiper={(swiper) => (swiperRef.current = swiper)} // Swiper가 준비되면 ref에 담기
        slidesPerView={1}
        spaceBetween={10}
      >
        <SwiperSlide>Slide 1</SwiperSlide>
        <SwiperSlide>Slide 2</SwiperSlide>
        <SwiperSlide>Slide 3</SwiperSlide>
      </Swiper>

      {/* 직접 만든 커스텀 버튼 */}
      <button onClick={() => swiperRef.current.slidePrev()}>Prev</button>
      <button onClick={() => swiperRef.current.slideNext()}>Next</button>
    </div>
  );
}

 

 

json-server

  • 가짜 백엔드를 빠르게 만들어주는 도구
  • db.json 파일 하나로 GET, POST, PUT, DELETE 요청을 테스트할 수 있음
  • 서버가 준비되지 않았을 때, 프론트엔드 개발을 빠르게 시작할 수 있게 도와줌
  • 복잡한 백엔드 코드 없이도 API처럼 사용 가능

 

🛠️ 설치

npm install -D json-server concurrently
명령어 의미
-D 개발용(DevDependencies) 으로 설치 (배포할 때 제외)
json-server 가짜 API 서버를 만들어주는 툴
concurrently 여러 개의 스크립트를 동시에 실행할 수 있게 해주는 툴 (Vite 개발 서버와 json-server를 동시에 실행할 때 필요)

🪄 package.json 수정

  "scripts": {
    "watch:json-server": "json-server db.json --port 3000", //db.json 파일을 읽어서 3000번 포트에서 서버 실행
    "watch:vite": "vite", // Vite 개발 서버 실행
    "watch:react": "react-scripts start", // Create React App 기반 React 서버 실행
    "dev": "concurrently npm:watch:*", // 위의 watch:* 명령어들을 동시에 실행 (vite + json-server 둘 다 켜기)
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },

✍🏻 db.json 작성

프로젝트의 root(최상단) 경로에 작성

{
  "products": [
    {
      "id": 1,
      "title": "14K/18K 허니 벌집2 헥사곤 심플 반지",
      "img": "image1.jpg",
      "price": 185000,
      "category": "new",
      "discount": 5
    },
    {
      "id": 2,
      "title": "14K/18K 마닐드 하트 드롭 큐빅 원터치 귀걸이",
      "img": "image2.jpg",
      "price": 126250,
      "category": "top",
      "discount": 31
    },
    {
      "id": 3,
      "title": "14k 데일리 심플 볼귀걸이 시리즈",
      "img": "image3.jpg",
      "price": 30000,
      "category": "top",
      "discount": 45
    },
	// ... 생략
  ]
}

↪️ 실행

npm run dev

 

 

📁 React public 폴더

  • 리액트가 빌드될 때 변환되지 않고 그대로 배포되는 파일을 저장하는 공간
  • Webpack이나 Vite 같은 번들러가 수정하거나 최적화하지 않고, 파일을 그대로 복사해서 결과물에 포함시킴
"있는 그대로 서버로 올라가는 파일들"을 넣는 곳

📍 특징

  • 변환(트랜스파일) : ❌ 없음
  • 압축(최적화) : ❌ 없음
  • 절대 경로로 접근 : ⭕ 가능

 

✅ 접근 방법

public 폴더에 hello.png가 있다고 치면

<img src="/hello.png" alt="Hello" />
  • /hello.png처럼 절대 경로로 접근
  • import 없이 바로 사용 가능
  • 상대 경로(../) 필요 없음

 

☁️ 사용되는 경우

  • favicon.ico: 브라우저 탭에 표시할 파비콘
  • robots.txt, sitemap.xml: 검색 엔진 최적화(SEO) 파일
  • 외부에서 직접 접근해야 하는 이미지, 동영상 같은 정적 파일
  • 프로젝트 빌드 크기를 줄이기 위해 대용량 파일을 분리할 때
728x90
반응형

'LG 유플러스 유레카 SW > React' 카테고리의 다른 글

[#54] React 쇼핑몰 - 성능 향상 + Hero 페이지 제작  (2) 2025.04.15
[#53] React 쇼핑몰 - 헤더 반응형으로 만들어보기  (1) 2025.04.14
[#51] 가위바위보 게임 (feat. React)  (0) 2025.04.10
[#50] React - useState  (5) 2025.04.09
[#49] React 설정  (1) 2025.04.08
  1. React Router란?
  2. 🛠️ 설치
  3. ✏️ 구현 방식
  4. ✨ <Outlet />
  5. ✨ children
  6. 중첩 라우팅(Nested Routing)
  7. <Link> 태그
  8. <NavLink> 태그
  9. NotFound 설정
  10. 📍 페이지 컴포넌트는 Page 접미사 붙이기
  11. 📁 실무용 폴더 구조
  12. Swipper
  13. 🛠️설치
  14. 🔥 React에서 사용법 (feat. autoplay)
  15. json-server
  16. 📁 React public 폴더
'LG 유플러스 유레카 SW/React' 카테고리의 다른 글
  • [#54] React 쇼핑몰 - 성능 향상 + Hero 페이지 제작
  • [#53] React 쇼핑몰 - 헤더 반응형으로 만들어보기
  • [#51] 가위바위보 게임 (feat. React)
  • [#50] React - useState
nueos
nueos
  • nueos
    nueos 공부 기록
    nueos
  • 전체
    오늘
    어제
    • 분류 전체보기 (191)
      • 해커톤 (1)
      • 네이버 BoostCamp (6)
      • LG 유플러스 유레카 SW (3)
        • React (21)
        • TypeScript (2)
        • JavaScript (2)
        • HTML+CSS (5)
        • Spring (7)
        • Java (6)
        • SQL (2)
        • Algorithm (8)
        • CX (6)
        • Git (2)
        • 프로젝트 (2)
        • 스터디 (9)
        • 과제 (8)
        • 특강 (1)
      • React (3)
      • Next (0)
      • Javascript (2)
      • HTML (2)
      • CSS (9)
      • Algorithm (6)
      • Database (0)
      • OS (13)
      • C++ (24)
      • Python (1)
      • jQuery (1)
      • Django (1)
      • Git (1)
      • 개발 지식 (3)
      • 정보 보안 (22)
      • 포렌식 (1)
      • 암호 (2)
      • 기타 (4)
      • 패스트캠퍼스 FE 프로젝트십 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    디지털혁신
    기술로바꾸는세상
    힙
    exhaustive search
    제주지역혁신플랫폼지능형서비스사업단
    스택
    큐
    Stack
    heap
    Queue
    완전 탐색
    제주해커톤
    디지랩챌린지
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
nueos
[#52] React Router
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.