본문 바로가기
React

[React] 메뉴바로 페이지 전환하기

by teamnova 2025. 5. 21.
728x90

 

안녕하세요 오늘은 react-router-dom 을 사용하여 페이지 전환을 해보도록 하겠습니다. 

슬라이드 카드 만들기에 이어서 진행할 예정입니다. 

해당 게시글은 아래 링크에서 확인하실 수 있습니다. 

 

[React] 슬라이드 카드 UI 만들기

안녕하세요. 오늘은 리액트를 사용해 슬라이드 카드 UI를 만들어보겠습니다. 슬라이드 카드는 이미지, 텍스트 등을 한 화면에서 넘기며 보여줄 수 있는 방식으로, 포트폴리오, 프로젝트 소개, 리

stickode.tistory.com

 

 

1. react-router-dom 설치

먼저 리액트 라우터 돔을 설치합니다. 

Windows 개발 환경 기준 VS Code 의 터미널 단축키는 < Ctrl + ` > 입니다  

npm install react-router-dom

 

 

2. 페이지 만들기 (프로젝트 구조)

src 안에 /page 디렉토리를 생성합니다. 

총 4개의 페이지 (home, experiences, about, projects) 로 구성하고자 합니다. 

4개의 자바 스크립트 파일을 만들어줍니다. 

 

 

3. 상단 메뉴바 만들기 

기존 슬라이드 카드를 home 화면으로 삼도록 하겠습니다. 

App.js 파일에서 헤더를 추가해 상단 메뉴바 코드를 추가해줍니다

<header style={headerStyle}>
        <div style={{ fontWeight: "bold", fontSize: "20px" }}>
          <Link to="/" style={{ color: "white", textDecoration: "none" }}>
            Hiii It's mee !
          </Link>
        </div>
        <nav style={navStyle}>
          <Link to="/" style={{ color: "white", textDecoration: "none" }}>
            Home
          </Link>
          <Link to="/about" style={{ color: "white", textDecoration: "none" }}>
            About
          </Link>
          <Link
            to="/experience"
            style={{ color: "white", textDecoration: "none" }}
          >
            Experience
          </Link>
          <Link
            to="/projects"
            style={{ color: "white", textDecoration: "none" }}
          >
            Projects
          </Link>
        </nav>
      </header>

 

 

 

4. 라우터 

라우터(Router)란 "어떤 주소(URL)"에 따라 어떤 페이지나 화면을 보여줄지 결정해주는 시스템입니다.

데이터가 목적지까지 도달하도록 경로를 설정하고 전송하는 역할을 합니다.  

 

주소(URL) 보여줄 화면(페이지)
/ 홈 화면
/about About 소개 페이지
/projects 로그인 화면

 

라우터는 위 주소를 각각 분기처리하여 어떤 페이지를 렌더링할지 결정합니다. 

React 는 원래 "하나의 페이지에서 작동하는" Single Page Application (SPA)입니다. 

그러나 웹사이트는 주로 한 개 이상의 페이지가 필요한 경우가 훨씬 많습니다. 

이걸 가능하게 해주는 게 바로 <Router> 입니다. 

return 값 전체를 <Router> 로 감싸서 "라우팅 기반"으로 동작할 것임을 선언합니다.

 

 

전체 코드입니다 

App.js 

import "./App.css";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import Slider from "react-slick";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import About from "./pages/about.js";
import Experience from "./pages/experiences.js";
import Projects from "./pages/projects.js";

// 슬라이드 카드 데이터
const cardData = [
  {
    title: "1. Wall Sina",
    description:
      "The innermost wall, where the royal family and nobles reside.",
    image: "https://source.unsplash.com/random/800x400?city",
  },
  {
    title: "2. Wall Rose",
    description: "The middle wall, home to many of the general populace.",
    image: "https://source.unsplash.com/random/800x400?nature",
  },
  {
    title: "3. Wall Maria",
    description:
      "The outermost and largest wall, the first to fall during the Titans' initial attack.",
    image: "https://source.unsplash.com/random/800x400?space",
  },
];

// 커스텀 화살표
function PrevArrow(props) {
  return (
    <button
      onClick={props.onClick}
      style={{
        position: "absolute",
        left: "-60px",
        top: "50%",
        transform: "translateY(-50%)",
        zIndex: 10,
        padding: "12px 18px",
        fontSize: "20px",
        borderRadius: "50%",
        border: "none",
        backgroundColor: "rgba(0, 0, 0, 0.6)",
        color: "white",
        cursor: "pointer",
      }}
    >
      ←
    </button>
  );
}

function NextArrow(props) {
  return (
    <button
      onClick={props.onClick}
      style={{
        position: "absolute",
        right: "-60px",
        top: "50%",
        transform: "translateY(-50%)",
        zIndex: 10,
        padding: "12px 18px",
        fontSize: "20px",
        borderRadius: "50%",
        border: "none",
        backgroundColor: "rgba(0, 0, 0, 0.6)",
        color: "white",
        cursor: "pointer",
      }}
    >
      →
    </button>
  );
}

// App 컴포넌트
function App() {
  const settings = {
    dots: true,
    infinite: true,
    speed: 500,
    slidesToShow: 1,
    slidesToScroll: 1,
    nextArrow: <NextArrow />,
    prevArrow: <PrevArrow />,
  };

  const headerStyle = {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    padding: "20px 40px",
    backgroundColor: "#0d1b2a",
    color: "white",
  };

  const navStyle = {
    display: "flex",
    gap: "20px",
    alignItems: "center",
  };

  return (
    <Router>
      <header style={headerStyle}>
        <div style={{ fontWeight: "bold", fontSize: "20px" }}>
          <Link to="/" style={{ color: "white", textDecoration: "none" }}>
            Hiii It's mee !
          </Link>
        </div>
        <nav style={navStyle}>
          <Link to="/" style={{ color: "white", textDecoration: "none" }}>
            Home
          </Link>
          <Link to="/about" style={{ color: "white", textDecoration: "none" }}>
            About
          </Link>
          <Link
            to="/experience"
            style={{ color: "white", textDecoration: "none" }}
          >
            Experience
          </Link>
          <Link
            to="/projects"
            style={{ color: "white", textDecoration: "none" }}
          >
            Projects
          </Link>
        </nav>
      </header>

      <Routes>
        <Route
          path="/"
          element={
            <div style={{ padding: "50px", textAlign: "center" }}>
              <div className="slider-wrapper">
                <Slider {...settings}>
                  {cardData.map((card, index) => (
                    <div key={index} className="slide">
                      <div
                        className="slide-background"
                        style={{
                          backgroundImage: `url(${card.image})`,
                          height: "400px",
                          backgroundSize: "cover",
                          backgroundPosition: "center",
                          position: "relative",
                          borderRadius: "20px",
                          overflow: "hidden",
                        }}
                      >
                        <div
                          className="text-box"
                          style={{
                            position: "absolute",
                            top: "50%",
                            left: "50%",
                            transform: "translate(-50%, -50%)",
                            backgroundColor: "rgba(0,0,0,0.6)",
                            padding: "30px",
                            width: "80%",
                            maxWidth: "600px",
                            minWidth: "250px",
                            borderRadius: "20px",
                            textAlign: "center",
                            color: "white",
                          }}
                        >
                          <h2>{card.title}</h2>
                          <p>{card.description}</p>
                        </div>
                      </div>
                    </div>
                  ))}
                </Slider>
              </div>
            </div>
          }
        />
        <Route path="/about" element={<About />} />
        <Route path="/experience" element={<Experience />} />
        <Route path="/projects" element={<Projects />} />
      </Routes>
    </Router>
  );
}

export default App;

 

 

about.js 

About 코드입니다. experience, projects 도 같은 방식으로 작성하였습니다. 

function About() {
  return (
    <div style={{ padding: "50px", textAlign: "center" }}>
      <h1>About Page</h1>
      <p>이곳은 소개 페이지입니다.</p>
    </div>
  );
}

export default About;

 

 

 

 

시연 영상입니다