본문 바로가기
STUDY/Project

페이지 라우팅 설정하기

by Y.Choi 2025. 5. 11.
728x90
반응형

 

이전 작업에서 라우터를 분리해 정리를 했었다. 이제 실제로 어떤 컴포넌트를 어떤 경로에 보여줄지를 앱 전체 흐름 안에서 구현할 수있게 페이지 라우팅 설정을 해야 한다.

Layout을 라우팅에 적용하고 각 경로에서 알맞은 페이지가 보이게 하는 것이다.

 

 

| 페이지 라우팅 설정

a) 레이아웃에 children 대신 Outlet 적용

 

frontend/src/Components/Layout.js


import Header from "./Header";
import Footer from "./Footer";
import { Outlet } from 'react-router-dom';

export default function Layout() {
  return (
    <div className="flex flex-col min-h-screen">
      <Header />
      <main className="flex-1 container mx-auto p-4">
        <Outlet />
      </main>
      <Footer />
    </div>
  );
}

 

<Outlet />은 React Router 전용의 children을 대체하는 역할로, 라우팅을 통해 들어온 자식 페이지를 자동으로 이 위치에서 렌더링을 해준다.

children은 일반 컴포넌트에서 쓰이고 단순한 레이아웃 컴포넌트에서는 충분히 역할을 하지만 라우팅 구조와 함께 사용되는 Layout에서는 <Outlet />을 써야 한다. 자식 컴포넌트를 자동으로 넣어주고, 중첩된 자식들이 있다면 <Outlet /> 없이는 표시 되지 않기 때문이다.

정리하면, children은 부모 컴포넌트가 자식 컴포넌트를 직접 감쌀 때 전달되고, Outlet은 React Router가 현재 경로에 맞는 컴포넌트를 내부에 넣어주는 역할을 한다.

 

 

2) 라우트에 공통으로 레이아웃 적용하기

 

이제, 지금까지 만든 공동 Layout 컴포넌트를 모든 페이지에 적용하려면 routes/index/js에서 최상위 <Route>의 element로 Layout을 지정하고 그 안에 으로 페이지들이 들어오도록 설정 하면 된다.

 

frontend/src/routes/index.js

import React from 'react';
import { Routes, Route } from 'react-router-dom';
import AuthRoutes from './authRoutes';
import PostRoutes from './postRoutes';
import DashboardRoutes from './dashboardRoutes';
import Layout from '../components/Layout';

const AppRoutes = () => {
  return (
    <Routes>
      {/** 공통 Layout */}
      <Route path="/" element={<Layout />}>
        {AuthRoutes}
        {DashboardRoutes}
        {PostRoutes}
      </Route>
    </Routes>
  );
};

export default AppRoutes;

 

 

그리고 이전에 테스트 해봤던 HomePage.js에서는 Layout을 다시 빼준다. 이미 라우터에서 Layout이 모든 페이지의 공통 상위 구조로 적용되어 있기 때문이다. 수정해주지 않으면 Layout이 중첩으로 들어가게 된다.

 

frontend/src/Pages/HomePage.js

import React, { useEffect, useState, useContext } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { AuthContext } from '../context/AuthContext';

const HomePage = () => {
  const [posts, setPosts] = useState([]);
  const { user, logout } = useContext(AuthContext);

  useEffect(() => {
    const fetchPosts = async () => {
      try {
        const res = await axios.get('http://localhost:5000/api/posts');
        setPosts(res.data);
      } catch (err) {
        console.error(err);
      }
    };
    fetchPosts();
  }, []);

  return (
    <>
      <header style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <h1>📋 게시판</h1>
        <div>
          {user ? (
            <>
              <span>{user.username}님</span>
              <button onClick={logout} style={{ marginLeft: '10px' }}>로그아웃</button>
            </>
          ) : (
            <Link to="/login"><button>로그인</button></Link>
          )}
        </div>
      </header>

      <ul>
        {posts.map(post => (
          <li key={post._id}>
            <Link to={`/posts/${post._id}`}>{post.title}</Link> — {post.author.username}
          </li>
        ))}
      </ul>
    </>
  );
};

export default HomePage;

 

 

이전처럼 화면에 문제가 없다면 잘 된 것이다. 보이는 부분에서 달라진 것은 없지만 좀 더 내부적으로는 완성형이 되어가고 있다고 본다. 아직 할 일은 많지만 많이 왔다. 👍

728x90
반응형