일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 자바
- 객체 비교
- 컬렉션 타입
- 다형성
- NestedFor
- GRANT VIEW
- 참조형변수
- 메소드오버로딩
- 제네릭
- 예외미루기
- Java
- abstract
- 대덕인재개발원
- 정수형타입
- 추상메서드
- 컬렉션프레임워크
- 한국건설관리시스템
- 오라클
- 사용자예외클래스생성
- 어윈 사용법
- oracle
- 인터페이스
- EnhancedFor
- 집합_SET
- 환경설정
- 자동차수리시스템
- 예외처리
- cursor문
- 생성자오버로드
- exception
- Today
- Total
거니의 velog
(4) React-Router 2 본문
(6) 하위 경로의 설정과 <Outlet>
* 일반적으로 웹에서는 특정한 모듈에 접근했을 때의 기본적인 화면은 대시보드(Dashboard)와 같은 여러 상태를 한 눈에 볼 수 있는 화면이나 목록 페이지를 보여주는 것이다. 예제에서는 '/todo/list' 대신에 '/todo/' 경로의 링크만을 남겨두었는데, 이렇게 하는 이유는 모듈의 이름 자체가 하나의 경로가 된다는 원칙을 세우고 새로운 모듈들의 개발 방식을 통일하기 위함이다.
* 프로젝트의 pages 폴더에 todo 폴더를 생성해 두고 위의 경로에는 존재하지 않는 IndexPage.js 파일을 추가한다. IndexPage.js는 BasicLayout을 이용해서 전체적인 레이아웃이 적용된 가운데서 다시 Todo와 관련된 메뉴나 화면을 구성한다.
* 개발에 앞서 BasicLayout에서 영역을 알아보기 위해 설정한 padding이나 flex 관련 설정을 조정한다.
import React from "react";
import BasicMenu from "../components/menus/BasicMenu";
const BasicLayout = ({ children }) => {
return (
<>
{/* 기존 헤더 대신 BasicMenu */}
<BasicMenu />
{/* space-y-1 변경, md:space-x-1 변경 */}
<div className="bg-white my-5 w-full flex flex-col space-y-1 md:flex-row md:space-x-1 md:space-y-0">
{/* md:w-4/5 변경, py-5 변경 */}
<main className="bg-sky-300 md:w-4/5 lg:w-3/4 px-5 py-5">
{children}
</main>
{/* md:w-1/5 변경, flex 추가, py-5 변경 */}
<aside className="bg-green-300 md:w-1/5 lg:w-1/4 px-5 flex py-5">
<h2 className="text-2xl md:text-4xl">Sidebar</h2>
</aside>
</div>
</>
);
};
export default BasicLayout;
* todo 폴더의 IndexPage에서는 '/todo/' 이하 메뉴에서 필요한 하위 메뉴를 보여주고 하위 페이지들의 화면을 보여주는 <Outlet> 설정을 추가한다.
import React from "react";
import BasicLayout from "../../layouts/BasicLayout";
import { Outlet } from "react-router-dom";
const IndexPage = () => {
return (
<BasicLayout>
<div className="w-full flex m-2 p-2 ">
<div className="text-xl m-1 p-2 w-20 font-extrabold text-center underline">
LIST
</div>
<div className="text-xl m-1 p-2 w-20 font-extrabold text-center underline">
ADD
</div>
</div>
<div className="flex flex-wrap w-full">
<Outlet />
</div>
</BasicLayout>
);
};
export default IndexPage;
* IndexPage를 보면 React-Router의 <Outlet>이 적용된 것을 볼 수 있다. <Outlet>은 중첩적으로 라우팅이 적용될 때 기존 컴포넌트의 구조를 유지할 수 있는데 이를 통해서 '/todo/list'와 같이 하위 경로에 맞는 페이지 컴포넌트를 제작할 때 IndexPage의 구조가 유지될 수 있게 된다. <Outlet>을 활용하면 좀 더 세밀한 레이아웃의 재사용 단위를 구성할 수 있다.
* IndexPage에는 LIST, ADD와 같이 링크를 위한 <div>들을 생성해 두었다. 이 링크는 IndexPage를 사용하는 모든 컴포넌트에 공통으로 사용할 수 있다. Todo 기능과 관련된 라우팅 설정을 위해 router/root.js에 '/todo' 관련 경로를 추가한다.
import React, { Suspense, lazy } from "react";
import { createBrowserRouter } from "react-router-dom";
const Loading = <div>Loading...</div>;
const Main = lazy(() => import("../pages/MainPage"));
const About = lazy(() => import("../pages/AboutPage"));
const TodoIndex = lazy(() => import("../pages/todo/IndexPage"));
const root = createBrowserRouter([
{
path: "",
element: (
<Suspense fallback={Loading}>
<Main />
</Suspense>
),
},
{
path: "about",
element: (
<Suspense fallback={Loading}>
<About />
</Suspense>
),
},
{
path: "todo",
element: (
<Suspense fallback={Loading}>
<TodoIndex />
</Suspense>
),
},
]);
export default root;
* 브라우저에서 확인해 보면 BasicLayout의 메뉴를 통해서 '/todo/;로 접근할 때 todo/IndexPage 컴포넌트가 출력되는 것을 확인할 수 있다.
(7) todo/list 경로 처리
* <Outlet>을 활용하면 중첩적인 라우팅 처리 설정 시 레이아웃을 유지할 수 있는데 이를 확인하기 위해서 'todo/list'와 같이 중첩적인 경로를 처리해 보겠다. 먼저, 프로젝트의 pages/todo 폴더에 ListPage.js 파일을 추가한다.
import React from "react";
const ListPage = () => {
return (
<div className="p-4 w-full bg-white">
<div className="text-3xl font-extrabold">Todo List Page component</div>
</div>
);
};
export default ListPage;
* ListPage 컴포넌트는 별도의 레이아웃에 대한 처리 없이 필요한 내용만으로 작성된 것을 확인할 수 있다. 이런 방식으로 실제 페이지들을 구성하면 공통적인 메뉴나 레이아웃 없이 코드를 독립적으로 제작할 수 있게 된다.
[1] React-Router의 중첩 라우팅
* React-Router는 하나의 경로 설정에서 children 속성을 이용해서 하위로 중첩적인 경로를 지정할 수 있다. router/root.js 파일을 아래와 같이 수정한다.
import React, { Suspense, lazy } from "react";
import { createBrowserRouter } from "react-router-dom";
const Loading = <div>Loading...</div>;
const Main = lazy(() => import("../pages/MainPage"));
const About = lazy(() => import("../pages/AboutPage"));
const TodoIndex = lazy(() => import("../pages/todo/IndexPage"));
const TodoList = lazy(() => import("../pages/todo/ListPage"));
const root = createBrowserRouter([
{
path: "",
element: (
<Suspense fallback={Loading}>
<Main />
</Suspense>
),
},
{
path: "about",
element: (
<Suspense fallback={Loading}>
<About />
</Suspense>
),
},
{
path: "todo",
element: (
<Suspense fallback={Loading}>
<TodoIndex />
</Suspense>
),
children: [
{
path: "list",
element: (
<Suspense fallback={Loading}>
<TodoList />
</Suspense>
),
},
],
},
]);
export default root;
* 위의 설정을 적용하면 브라우저에서 'todo/list'로 접근할 경우 <Outlet> 부분이 ListPage 컴포넌트로 처리되는 것을 확인할 수 있다.
(8) 중첩 라우팅의 분리와 리다이렉션(Redirection)
* 위와 같이 하나의 라우팅 설정에 children 속성을 이용해서 중첩적인 라우팅 설정을 적용할 수 있지만 페이지가 많아지면 root.js 파일이 너무 복잡해지는 단점이 있다. 그렇기 때문에 이럴 떄는 별도의 함수에 children 속성값에 해당하는 설정을 반환하는 방식이 좀 더 알아보기 수월하다.
* router 폴더에 todoRouter.js 파일을 추가하고 '/todo/' 하위의 설정들을 반환하도록 함수를 작성한다(일반적으로 리액트에서 파일의 이름은 컴포넌트를 제외하면 소문자로 작성한다).
import React, { Suspense, lazy } from "react";
const Loading = <div>Loading...</div>;
const TodoList = lazy(() => import("../pages/todo/ListPage"));
const todoRouter = () => {
return [
{
path: "list",
element: (
<Suspense fallback={Loading}>
<TodoList />
</Suspense>
),
},
];
};
export default todoRouter;
* todoRouter.js 파일은 기존의 root.js 파일의 설정 일부를 별도의 파일로 분리하고 설정을 반환하도록 한 것이다. 기존의 '/todo/' 와 관련된 children 설정을 담고 있는 라우팅 설정은 todoRouter를 호출하는 형태로 수정한다.
import React, { Suspense, lazy } from "react";
import { createBrowserRouter } from "react-router-dom";
import todoRouter from "./todoRouter";
const Loading = <div>Loading...</div>;
const Main = lazy(() => import("../pages/MainPage"));
const About = lazy(() => import("../pages/AboutPage"));
const TodoIndex = lazy(() => import("../pages/todo/IndexPage"));
const root = createBrowserRouter([
{
path: "",
element: (
<Suspense fallback={Loading}>
<Main />
</Suspense>
),
},
{
path: "about",
element: (
<Suspense fallback={Loading}>
<About />
</Suspense>
),
},
{
path: "todo",
element: (
<Suspense fallback={Loading}>
<TodoIndex />
</Suspense>
),
children: todoRouter(),
},
]);
export default root;
* 수정된 부분을 보면 '/todo/' 경로와 관련된 설정은 todoRouter() 를 이용하도록 변경된 것을 볼 수 있다.
[1] 리다이렉션 처리
* todoRouter 내에, 경로에 대한 설정을 추가하긴 하지만 '/todo/' 경로로 접근하는 경우 자동으로 '/todo/list'를 바라볼 수 있도록 처리해 주면 <Outlet> 설정을 유지한 상태에서 사용이 가능하다. React-Router에는 <Nevigate>의 replace 속성을 이용해서 특정 경로로 진입 시에 자동으로 리다이렉션을 처리할 수 있다.
* todoRouter.js에서 '/todo/' 이하의 경로가 지정되지 않았을 때 동작하는 빈 경로의 설정을 아래와 같이 추가한다.
import React, { Suspense, lazy } from "react";
import { Navigate } from "react-router-dom";
const Loading = <div>Loading...</div>;
const TodoList = lazy(() => import("../pages/todo/ListPage"));
const todoRouter = () => {
return [
{
path: "list",
element: (
<Suspense fallback={Loading}>
<TodoList />
</Suspense>
),
},
{
path: "",
element: <Navigate replace to="list" />,
},
];
};
export default todoRouter;
* 추가된 설정으로 인해 브라우저에서 'Todo' 메뉴를 선택하거나 '/todo/' 경로를 호출하는 경우 자동으로 '/todo/list'로 이동되는 것을 확인할 수 있다.
(9) URL Params 사용하기
* 예제가 완성된다면 목록 페이지에서 조회 페이지로 이동할 때 경로가 변경된다. 최근 웹에서는 주로 경로의 마지막에 고유한 식별번호를 사용하는 것이 일반적이다. 예제에서는 특정한 번호의 Todo를 조회할 경우 '/todo/read/33'과 같은 경로로 이동하는 방식을 적용한다. React-Router는 경로에 필요한 데이터가 있을 때는 ' : '을 활용한다.
[1] 페이지 추가
* pages/todo 폴더 내에 조회할 때 사용할 ReadPage.js 파일을 추가한다.
import React from "react";
const ReadPage = () => {
return (
<div className="text-3xl font-extrabold">Todo Read Page Component</div>
);
};
export default ReadPage;
* router/todoRouter.js 에는 ReadPage 컴포넌트에 대한 경로 설정을 추가한다.
import React, { Suspense, lazy } from "react";
import { Navigate } from "react-router-dom";
const Loading = <div>Loading...</div>;
const TodoList = lazy(() => import("../pages/todo/ListPage"));
const TodoRead = lazy(() => import("../pages/todo/ReadPage"));
const todoRouter = () => {
return [
{
path: "list",
element: (
<Suspense fallback={Loading}>
<TodoList />
</Suspense>
),
},
{
path: "",
element: <Navigate replace to="list" />,
},
{
path: "read/:tno",
element: (
<Suspense fallback={Loading}>
<TodoRead />
</Suspense>
),
},
];
};
export default todoRouter;
* 추가된 'read/:tno'의 부분에서 ' : '은 경로의 일부를 변수로 사용하기 위한 설정으로 브라우저에서 특정한 번호를 조회하는 용도로 사용한다. 브라우저에서 '/todo/read/33'과 같은 경로를 호출하면 ReadPage 컴포넌트가 실행되는 것을 확인할 수 있다(마지막의 번호는 식별자의 의미를 가진다).
'SpringBoot_React 풀스택 프로젝트' 카테고리의 다른 글
(6) 스프링 부트와 API 서버 1 (0) | 2024.02.26 |
---|---|
(5) React-Router 3 (0) | 2024.02.26 |
(3) React-Router 1 (0) | 2024.02.26 |
(2) 개발 환경설정 (0) | 2024.02.26 |
(1) 들어가며 (1) | 2024.02.26 |