📌 디렉토리 구조

0. src/index.js
1. src/App.js
- 애플리케이션의 최상위 컴포넌트 (이 파일 기준으로 전체 화면 렌더링)
2. api
- 외부 API와 통신하는 함수들을 모아놓는 폴더
3. component
4. page
5. router
- 페이지의 경로를 정의하는 라우터 설정 파일들 (최상위 라우터 : root.js)
6. layout
- 페이지 공통 구조 정의 (헤더/푸터/사이드바 등)
1. App.js
- 애플리케이션의 최상위 컴포넌트.
ReactDOM이 이 파일을 기준으로 전체 화면을 렌더링함
- 경로 : src/App.js
import { RouterProvider } from "react-router-dom"
import root from "./router/root"
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
<RouterProvider router={root}/>
);
}
export default App;
2. root.js
- 앱 전체 페이지(컴포넌트)들의 경로를 정의하는 최상위 라우터 설정 파일.
createBrowserRouter()를 통해 어떤 경로(path)에는 어떤 컴포넌트를 보여줄 것인지를 결정하는 역할을 함
- 경로 : src/router/root.js
import { Suspense, lazy } from "react";
import testRouter from "./testRouter";
import { createBrowserRouter } from "react-router-dom";
import BasicLayout from "../layout/BasicLayout";
const Loading = <div>Loading....</div>
const Main = lazy(() => import("../page/MainPage"))
const TestIndex = lazy(() => import("../page/test/IndexPage"))
const root = createBrowserRouter([
{
path: "",
element: <BasicLayout/>,
children: [
{
index: true,
element: <Suspense fallback={Loading}><Main /></Suspense>
},
{
path: "test",
element: <Suspense fallback={Loading}><TestIndex /></Suspense>,
children: testRouter()
}
]
}
]);
export default root;
3. BasicLayout.js
- 페이지 공통 구조 정의 (헤더/푸터/사이드바 등)
- 경로 : src/layout/BasicLayout.js
import { Container } from "react-bootstrap"
import BasicMenu from "../component/BasicMenu"
import { Outlet } from "react-router-dom";
const BasicLayout = () => {
return (
<>
<BasicMenu/> {}
<Container> {}
<Outlet/> {}
</Container>
</>
);
}
export default BasicLayout;
- 내비게이션 바 컴포넌트
- 경로 : src/component/BasicMenu.js
import { Link } from "react-router-dom";
const BasicMenu = () => {
return (
<nav className="text-end mt-3">
<Link to={'/test'} className="me-3 text-decoration-none text-dark">테스트</Link>
<Link to={'/mypage'} className="me-3 text-decoration-none text-dark">내 정보</Link>
<Link to={'/login'} className="me-5 text-decoration-none text-dark">로그인</Link>
</nav>
);
}
export default BasicMenu;
5. testRouter.js
- '/test' 경로와 관련된 설정을 정의할 라우터 설정 파일
- 경로 : src/router/testRouter.js
import { Suspense, lazy } from "react";
import { Navigate } from "react-router-dom";
const Loading = <div>Loading...</div>
const TestList = lazy(() => import("../page/test/ListPage"))
const TestRead = lazy(() => import("../page/test/ReadPage"))
const testRouter = () => {
return [
{
path: "",
element: <Navigate replace to="list"/>
},
{
path: "list",
element: <Suspense fallback={Loading}><TestList/></Suspense>
},
{
path: "read",
element: <Suspense fallback={Loading}><TestRead/></Suspense>
}
]
}
export default testRouter;
6. test/IndexPage.js
- '/test' 경로의 메인 화면
- 경로 : src/page/test/IndexPage.js
import { useCallback } from "react";
import { Button, Col, Row } from "react-bootstrap";
import { useNavigate, Outlet } from "react-router-dom";
const IndexPage = () => {
const navigate = useNavigate()
const handleClickList = useCallback(() => {
navigate({ pathname:'list' })
})
const handleClickRead = useCallback(() => {
navigate({ pathname:'read' })
})
return (
<Row>
<Col className="mt-5">
<div className="mb-3">
<h3 className="mb-2">test 메인</h3>
<Button onClick={handleClickList} className="me-3">List</Button>
<Button onClick={handleClickRead}>Read</Button>
</div>
<Outlet/> {}
</Col>
</Row>
)
}
export default IndexPage;
7. test/ListPage.js
- '/test' 경로의 하위 페이지1
- 경로 : src/page/test/ListPage.js
const ListPage = () => {
return (
<div className="text-primary">
<div>test 리스트 페이지</div>
<div>내용입니다</div>
</div>
)
}
export default ListPage;
8. test/ReadPage.js
- '/test' 경로의 하위 페이지2
- 경로 : src/page/test/ReadPage.js
const ReadPage = () => {
return (
<div className="text-danger">
<div>test 리드 페이지</div>
<div>내용입니다</div>
</div>
)
}
export default ReadPage;
결과