이전 작업에서 라우터를 분리해 정리를 했었다. 이제 실제로 어떤 컴포넌트를 어떤 경로에 보여줄지를 앱 전체 흐름 안에서 구현할 수있게 페이지 라우팅 설정을 해야 한다.
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;
이전처럼 화면에 문제가 없다면 잘 된 것이다. 보이는 부분에서 달라진 것은 없지만 좀 더 내부적으로는 완성형이 되어가고 있다고 본다. 아직 할 일은 많지만 많이 왔다. 👍
'STUDY > Project' 카테고리의 다른 글
Tailwind UI 적용하기 (0) | 2025.05.13 |
---|---|
Header 구성 변경 및 추가 - Sidebar (0) | 2025.05.12 |
반응형 내비게이션 - Navbar, lucide-react (0) | 2025.05.10 |
공통 Layout 컴포넌트 - Header, Footer, Layout (0) | 2025.05.09 |
React프로젝트에 Tailwind CSS 설치 및 설정 (0) | 2025.05.08 |