React Router 개념
React에서 라우팅을 구현하기 위한 표준 라이브러리
웹 애플리케이션에서 여러 페이지를 쉽게 관리하고 내비게이션을 구현할 수 있게 해준다.
- 라우팅의 개념예를 들어:
- example.com/home → 서버의 home.html 파일 요청
- example.com/about → 서버의 about.html 파일 요청
- 웹 애플리케이션이 처음 로드될 때 필요한 모든 JavaScript를 다운로드
- URL이 변경되면 새로운 페이지를 서버에서 받아오는 대신, JavaScript가 브라우저의 히스토리 API를 사용하여 URL을 변경하고 화면에 표시되는 컴포넌트를 변경
- 페이지 전체를 다시 로드하지 않기 때문에 더 빠른 사용자 경험을 제공
특징
- 라우팅이란 웹 애플리케이션에서 URL에 따라 다른 콘텐츠를 사용자에게 보여주는 메커니즘
전통적인 웹 사이트와의 차이점
- 전통적인 웹사이트에서는 각 URL이 서버에 있는 다른 HTML 파일을 요청하는 방식으로 작동
1. **프로토콜(Protocol)**: `https://`
◦ HTTPS(Hypertext Transfer Protocol Secure)는 웹 브라우저와 웹 서버 간의 암호화된 통신을 제공하는 프로토콜
◦ 일반 HTTP와 달리 데이터가 암호화되어 전송되므로 보안이 강화된다.
2. **도메인(Domain)**: `heart-heart.org`
◦ 웹사이트의 주소를 나타내는 고유 식별자
◦ `.org`는 주로 비영리 단체나 기관을 위한 최상위 도메인(TLD)
◦ `heart-heart`는 도메인 이름으로, 해당 조직의 이름을 나타낸다.
3. **경로(Path)**: `/sponsor/regular`
◦ 웹사이트 내에서 특정 페이지나 리소스의 위치를 나타낸다.
◦ `/sponsor`는 후원 관련 페이지의 디렉토리를 나타낸다.
◦ `/regular`는 그 안의 '정기 후원' 관련 페이지를 나타낸다.
4. **쿼리 스트링(Query String)**:
◦ 제공된 URL에는 쿼리 스트링이 포함되어 있지 않지만, 일반적으로 `?` 다음에 오는 부분이다.
◦ 만약 쿼리 스트링이 있다면: `https://heart-heart.org/sponsor/regular?param1=value1¶m2=value2` 형태로 나타 나타낸다.
◦ 쿼리 스트링은 서버에 추가 정보를 전달하는 데 사용되며, 주로 검색 조건, 필터링, 페이지네이션 등에 활용된다.
5. **프래그먼트(Fragment)**:
◦ `#` 다음에 오는 부분
◦ 예: `https://heart-heart.org/sponsor/regular#section1`
◦ 페이지 내 특정 섹션으로 직접 이동할 때 사용
만약 이 URL에 쿼리 스트링이 있다면 (예: `https://heart-heart.org/sponsor/regular?type=monthly&amount=10000`), 이는 정기 후원 페이지에서 월간 후원 타입과 10,000원의 후원 금액을 지정하는 파라미터일 수 있다.
React Router 연결 순서
📁 새로운 리액트 파일을 만들기 위해서는 npm create vite@latest를 입력한다.
그 뒤 npm i를 입력해 추가 확장자들을 설치해준다.
⬇️ ⬇️ ⬇️
router를 이용하기 위해서 npm i react-router-dom axios json-server 를 입력해준다.
⬇️ ⬇️ ⬇️
routes폴더 - pages 폴더-AboutPage.jsx
🧠 리액트 함수 컴포넌트 단축어 rsc 또는 rafce 기억하자
import React from 'react';
const AboutPage = () => {
return <div>AboutPage</div>;
};
export default AboutPage;
페이지를 만들었으면 뭘 하냐? 연결! 연결해야한다.
⬇️ ⬇️ ⬇️
📁 App.jsx에서 연결
import React from 'react';
import AboutPage from './routes/pages/AboutPage';
const App = () => {
return (
<div>
<AboutPage />
</div>
);
};
export default App;
⬇️ ⬇️ ⬇️
📁 형제관계인 components폴더 생성 후 Header.jsx파일 만든다.
import React from 'react';
const Header = () => {
return (
<header>
<h1>로고</h1>
</header>
);
};
export default Header;
⬇️ ⬇️ ⬇️
📁 기존 css 파일 내용물 초기화 후 index.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
color: inherit;
}
color: inherit란 무엇인가?
부모 요소로부터 해당 속성의 계산값을 받아 사용
inherit - CSS: Cascading Style Sheets | MDN
inherit - CSS: Cascading Style Sheets | MDN
CSS inherit 키워드를 사용한 속성은 부모 요소로부터 해당 속성의 계산값을 받아 사용합니다. CSS all 단축 속성을 포함한 모든 속성에 사용할 수 있습니다.
developer.mozilla.org
⬇️ ⬇️ ⬇️
📁 Footer역시 만들어서 App.jsx에 연결해준다.
import React from 'react';
const Footer = () => {
return <footer>Footer</footer>;
};
export default Footer;
⬇️ ⬇️ ⬇️
import React from 'react';
import AboutPage from './routes/pages/AboutPage';
import Header from './components/Header';
import Footer from './components/Footer';
const App = () => {
return (
<div>
<Header />
<AboutPage />
<Footer />
</div>
);
};
export default App;
app.jsx에 각각 컴포넌트를 불러왔으면 import하는걸 잊지말자! 🙂
🤔 Router에 의해서 화면이 처리되는 방법은 어떻게 할까?
📁 router폴더에 index.jsx 파일 생성
import { RouterProvider } from 'react-router';
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter([여기에는 보통 배열이 들어간다. ]);
// 함수를 하나 만들어서 내보내야된다.
export default function Router() {
return <RouterProvider router={router} />;
}
createBrowserRouter란?
모든 ReactRouter 웹 프로젝트에 권장되는 라우터이다.
createBrowserRouter v6.30.0 | 반응 라우터
createBrowserRouter v6.30.0 | React Router
reactrouter.com
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import App from './App';
const router = createBrowserRouter([
{
path: '/',
element: <App />,
},
]);
// 함수 만들어서 내보내야한다.
export default function Router() {
return <RouterProvider router={router} />;
}
createBrowserRouter([...])
라우터 정보를 배열로 정의해서 라우터를 객체 기반으로 구성하고 있다.
배열 내부의 객체 [{path:'/', element:<App/>}]
path: '/' | 어떤 주소에서 | 사용자가 브라우저 주소창에 /로 접속했을 때 |
element: <App /> | 어떤 컴포넌트를 보여줄지 | <App /> 컴포넌트를 화면에 렌더링해줌 |
⬇️⬇️⬇️
main.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import Router from './router/index.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<Router />
</StrictMode>
);
app.jsx에서 일정한 레이아웃을 만드는게 필요하다.
⬇️⬇️⬇️
📁 일단 router폴더- layout폴더 - Default.jsx파일 생성
app.jsx에 있던
<Header />
<AboutPage />
<Footer />
을 Default.jsx에 옮긴다.
import React from 'react';
import { Outlet } from 'react-router-dom';
const Default = () => {
return (
<div>
<Header />
{/* Outlet은 라우터에 의해서 보여질 컴포넌트 */}
<Outlet />
<Footer />
</div>
);
};
export default Default;
<Outlet/>이 적혀있던 자리에 <App/>이 있었다. <App/>이 있을때는 화면이 렌더링이 안됭ㅆ다.
왜 그런것일까? <Outlet/>의 역할은 무엇일까?
Outlet이 하는 역할
<Outlet/>은 중첩 라우트에서 자식 컴포넌트를 보여주는 자리
ex: App이 Outlet으로 이동했을 때
const router = createBrowserRouter([
{
path: '/',
element: <Default />, // 여기에서 Outlet을 사용
children: [
{
index: true,
element: <App /> // 이게 Outlet 안에 들어가서 보여짐
}
]
}
]);
👉 이렇게 하면 /에 접속했을 때 Default 컴포넌트가 렌더링되고, 그 안에서 <Outlet /> 자리에 <App />이 나오는 것
그렇다면 왜 App을 바로 넣으면 안보이는걸가?
이전 코드에서는
{
path: '/',
element: <App /> // 이건 Default 없이 바로 App만 보여주는 구조
}
지금은
{
path: '/',
element: <Default />,
children: [
{ element: <App /> }
]
}
이제는 App이 자식 라우트여서 Default에서 <Outlet/>이 없으면 렌더링 위치가 없다! 그래서 화면에 안나오는 것이다.
App이 자식이면 반드시 Outlet이 필요하다! Outlet이 없으면 아무리 자식 설정을 해도 화면에 나오지 않는다.
⬇️⬇️⬇️
그 뒤 App.jsx 폴더 삭제 후 index.jsx 파일에
import { RouterProvider } from 'react-router';
import { createBrowserRouter } from 'react-router-dom';
import Default from './layout/Default';
const router = createBrowserRouter([{ path: '/', element: <Default /> }]);
// 함수를 하나 만들어서 내보내야된다.
export default function Router() {
return <RouterProvider router={router} />;
}
router를 새팅할때 대괄호를 만들어 path정보와 element정보를 만든다.
그 하위 옵션으로 path를 넣는 이유는? routes 폴더 안에 pages가 있어서 그러나? (위에서 설명함)
import { RouterProvider } from 'react-router';
import { createBrowserRouter } from 'react-router-dom';
import Default from './layout/Default';
const router = createBrowserRouter([{ element: <Default />, children:[{}] }]);
// 함수를 하나 만들어서 내보내야된다.
export default function Router() {
return <RouterProvider router={router} />;
}
import React from 'react';
import { Link } from 'react-router-dom';
const Header = () => {
return (
<header>
<h1>
<Link to={'/'}>로고</Link>
</h1>
<nav>
<Link to={'/about'}>회사소개</Link>
<Link to={'/shop'}>쇼핑</Link>
<Link to={'/'}>링크</Link>
</nav>
</header>
);
};
export default Header;
import React from 'react';
import { NavLink } from 'react-router-dom';
const Header = () => {
return (
<header>
<h1>
<NavLink to={'/'}>로고</NavLink>
</h1>
<nav>
<NavLink to={'/about'}>회사소개</NavLink>
<NavLink to={'/shop'}>쇼핑</NavLink>
<NavLink to={'/'}>링크</NavLink>
</nav>
</header>
);
};
export default Header;
Link랑 LinkNav의 차이점
import { RouterProvider } from 'react-router-dom';
import { createBrowserRouter } from 'react-router-dom';
import Default from './layout/Default';
import MainPage from './pages/MainPage';
import AboutPage from './pages/AboutPage';
import ShopPage from './pages/ShopPage';
import BlogPage from './pages/BlogPage';
// createBrowserRouter: 경로 설정할 수 있음
const router = createBrowserRouter([
{
element: <Default />,
children: [
{
path: '/',
element: <MainPage />,
},
{
path: '/about',
element: <AboutPage />,
},
{
path: '/shop',
element: <ShopPage />,
},
{
path: '/blog',
element: <BlogPage />,
},
],
},
// 404에러 페이지
{ path: '*', element: <MainPage /> },
]);
// 함수를 하나 만들어서 내보내야된다.
export default function Router() {
return <RouterProvider router={router} />;
}
NavLink는 Link와 비슷하다.
현재 경로와 Link에서 사용하는 경로가 일치하는 경우 특정 스타일 혹은 CSS클래스를 적용할 수 있는 컴포넌트이다.
NavLink에서 링크가 활성화되었을 때의 스타일을 적용할 때는 activeStyle 값을, CSS 클래스를 적용할 때는 activeClassName 값을 props로 넣어 주면 된다!
리액트를 다루는 기술 [개정판]: 13.6.4 NavLink
리액트를 다루는 기술 [개정판]: 13.6.4 NavLink
더북(TheBook): (주)도서출판 길벗에서 제공하는 IT 도서 열람 서비스입니다.
thebook.io
⬇️⬇️⬇️
📁 404페이지도 만들어 준다.
import React from 'react';
import { Link } from 'react-router-dom';
const NotFound = () => {
return (
<div>
NotFound
<h2>페이지 없요</h2>
<Link to={'/'}> 홈으로</Link>
</div>
);
};
export default NotFound;
⬇️⬇️⬇️
중첩된 라우터 구조
근데 또 하위 페이지를 설정할 수 있다.
import { RouterProvider } from 'react-router-dom';
import { createBrowserRouter } from 'react-router-dom';
import Default from './layout/Default';
import MainPage from './pages/MainPage';
import AboutPage from './pages/AboutPage';
import ShopPage from './pages/ShopPage';
import BlogPage from './pages/BlogPage';
import MainSub1Page from './pages/MainSub1Page';
// createBrowserRouter: 경로 설정할 수 있음
const router = createBrowserRouter([
{
element: <Default />,
children: [
{
path: '/',
element: <MainPage />,
// children안에 무언가를 넣으려면 컴포너느가 필요하낟.
children: [{ path: '', element: <MainSub1Page /> }],
},
{
path: '/about',
element: <AboutPage />,
},
{
path: '/shop',
element: <ShopPage />,
},
{
path: '/blog',
element: <BlogPage />,
},
],
},
// 404에러 페이지
{ path: '*', element: <MainPage /> },
]);
// 함수를 하나 만들어서 내보내야된다.
export default function Router() {
return <RouterProvider router={router} />;
}
import React from 'react';
const MainSub1Page = () => {
return (
<div>
<div>MainSub1Page</div>
<div>MainSub1Page</div>
<div>MainSub1Page</div>
<div>MainSub1Page</div>
<div>MainSub1Page</div>
<div>MainSub1Page</div>
</div>
);
};
export default MainSub1Page;
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Default from './layout/default';
import MainPage from './pages/MainPage';
import AboutPage from './pages/AboutPage';
import ShopPage from './pages/ShopPage';
import BlogPage from './pages/BlogPage';
import MainSub1Page from './pages/MainSub1Page';
import MainSub2Page from './pages/MainSub2Page';
const router = createBrowserRouter([
{
element: <Default />,
children: [
{
path: '/',
element: <MainPage />,
children: [
{ path: '/sub1', element: <MainSub1Page /> },
{ path: '/sub2', element: <MainSub2Page /> },
],
},
{ path: '/about', element: <AboutPage /> },
{ path: '/shop', element: <ShopPage /> },
{ path: '/blog', element: <BlogPage /> },
],
},
{ path: '*', element: <MainPage /> },
]);
// 함수 만들어서 내보내야한다.
export default function Router() {
return <RouterProvider router={router} />;
}
이렇게 화면에 있는 걸 누르면 화면 전환이 된다.
'💡 URECA > 🗒️ 스터디 노트' 카테고리의 다른 글
[URECA] 가위바위보 프로젝트 (0) | 2025.04.10 |
---|---|
[URECA] Day 49 React 복기 (0) | 2025.04.08 |
[URECA] Day 48 HTML, CSS 레이아웃 복습 (0) | 2025.04.07 |
[URECA] Day47 피그마 → HTML 변환 (0) | 2025.04.03 |
[URECA] Day 46 React 컴포넌트 (0) | 2025.04.02 |