[React] 기본 구성 Root Router, Layout, Component 등 개념 정리

류넹·2025년 7월 17일

Front-End

목록 보기
9/10

📌 디렉토리 구조

0. src/index.js

  • React 앱을 브라우저에 연결해주는 진입점

1. src/App.js

  • 애플리케이션의 최상위 컴포넌트 (이 파일 기준으로 전체 화면 렌더링)

2. api

  • 외부 API와 통신하는 함수들을 모아놓는 폴더

3. component

  • 작은 단위의 UI 컴포넌트

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, // path: ""와 동일
                element: <Suspense fallback={Loading}><Main /></Suspense>
            },
            {
                path: "test",
                element: <Suspense fallback={Loading}><TestIndex /></Suspense>,
                children: testRouter() // '/test' 경로와 관련된 설정은 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;


4. BasicMenu.js

  • 내비게이션 바 컴포넌트
  • 경로 : 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;


결과

profile
학습용 커스터마이징 간단 개발자 사전

0개의 댓글