HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
프론트엔드 스쿨 교안(1기)
/
📝
React(Front-end)
/
📝
11. React Router
📝

11. React Router

설치하기BrowserRouterRoute정확한 경로 설정 : exactComponent props 전달하기LinkSwitch중첩라우터Route 사용하여 페이지 경로 만들기ReactRouter V6가 되면서 달라진 문법들1. Routes2. exact가 사라지다3. element4. Route의 부모로 Routes5. 중첩된 라우터
 
💡
React Router v4/5 docs 기준입니다. v6은 2021년 11월에 나왔습니다.
 
React Router 코드
router.zip
2.8KB

설치하기

App을 보게되면 총 3개의 컴포넌트를 가지고있습니다. 그런데 이것들을 모두 다른 주제를 가지고있어 다른페이지에서 보여주고싶습니다.
notion image
따라서 지금까지 진행한 내용을 여러 주소로 나누고 각 주소별로 다른 컴포넌트를 사용하도록 해보겠습니다.
우리는 현재 3개의 컴포넌트를 사용하고 있습니다. 각각의 주소를 /hello, /resume, /time 으로 구성해 보겠습니다.
 
먼저 라우트 설정을 위해 react-router-dom 을 설치해 주겠습니다.
npm install react-router-dom@5.2.0
 
  • 우선 간단하게 먼저 실습해봅시다.
import React from "react"; import { BrowserRouter, Route } from "react-router-dom"; function App() { return ( <BrowserRouter> {/* 라우트를 감싸줍니다. */} <Route path="/" component={Index}/> <Route path="/one" component={One}/> <Route path="/two" component={Two}/> <Route path="/three" component={Three}/> </BrowserRouter> ); } function Index(){ return <h1>hello world0</h1> } function One(){ return <h1>hello world1</h1> } function Two(){ return <h1>hello world2</h1> } function Three(){ return <h1>hello world3</h1> } export default App;
notion image

BrowserRouter

우리는 라우팅을 위해 BrowserRouter라는 컴포넌트를 사용할 것입니다. 라우트가 동작할 부분에 감싸주면 됩니다.
그리고 각 주소별로 라우팅을 하기 위해 Route컴포넌트를 사용하겠습니다.
<Route path="주소" component={컴포넌트}/> 와 같은 방식으로 작성하면 됩니다. 아래 코드에 주석으로 간단하게 설명하고 넘어가겠습니다.
import React from 'react'; import {BrowserRouter, Route} from 'react-router-dom // 사용할 컴포넌트 추가하기 import Hello from './Components/Hello' import Time from './Components/Time' import Resume from './Components/Resume' function App() { return ( <BrowserRouter>{/* 라우트를 감싸줍니다. */} <Route path="/hello" component={Hello}/>{/* 각각 주소와 컴포넌트를 입력해 사용 */} <Route path="/time" component={Time}/> <Route path="/resume" component={Resume}/> </BrowserRouter> ); } export default App;
 
※ 현재 컴포넌트에 props는 전달하지 않습니다. 아래에서 props 전달하는 방법이 설명되있습니다.

Route

앞서 만든 라우트에서의 "/", 즉 메인페이지로 이동하면 아무것도 나오지 않습니다. 홈 화면을 만들기 위해 남겨뒀는데요. Components 폴더에 Home.js 파일을 하나 만들어두고 아래와 같이 작성해보겠습니다.
import React from 'react'; function Home(props) { return( <div> <h1>Home 화면!</h1> </div> ) } export default Home
Components/Home.js
 
App.js에도 라우트를 하나 추가하겠습니다.
import React from 'react'; import {BrowserRouter, Route} from 'react-router-dom' import Hello from './Components/Hello' import Time from './Components/Time' import Resume from './Components/Resume' import Home from './Components/Home'; function App() { return ( <BrowserRouter> <Route path="/" component={Home}/> <Route path="/hello" component={Hello}/> <Route path="/time" component={Time}/> <Route path="/resume" component={Resume}/> </BrowserRouter> ); } export default App;
src/App.js return에 Route 추가하기
 
이 상태에서 주소에 접속하면 홈 화면이 제대로 나옵니다!
notion image
다음 '/hello' 페이지로 이동해보겠습니다.
notion image
 
잘 나온것 같은데 홈 화면이 같이 출력되었습니다. 이런 현상은 '/' 주소와 '/hello'의 주소 사이에서 '/' 이 부분이 중첩되어 발생하는 현상입니다.
추가예시
Time 컴포넌트의 path를 “/hello/time”으로 수정해봅시다.
import React from 'react'; import {BrowserRouter, Route} from 'react-router-dom' import Hello from './Components/Hello' import Time from './Components/Time' import Resume from './Components/Resume' import Home from './Components/Home'; function App() { return ( <BrowserRouter> <Route path="/" component={Home}/> <Route path="/hello/" component={Hello}/> <Route path="/hello/time" component={Time}/> <Route path="/resume" component={Resume}/> </BrowserRouter> ); } export default App;
src/App.jsdp Route 수정하기
/hello/time 를 접속하면 /hello 와 /hello/time이 동시에 출력되게 됩니다. '/hello' 부분이 겹치기 때문이에요!
 

정확한 경로 설정 : exact

이를 방지하기 위해 Route에는 exact라는 props가 존재합니다. (Router도 컴포넌트!) 주소가 정확하게 일치했을 때만 동작하게 합니다. 이를 적용해 봅시다.
// 기존코드 import React from "react"; import { BrowserRouter, Route } from "react-router-dom"; import Hello from "./Components/Hello"; import Time from "./Components/Time"; import Resume from "./Components/Resume"; import Home from "./Components/Home"; function App() { return ( <BrowserRouter> <Route path="/" exact component={Home} /> <Route path="/hello/" exact component={Hello} /> <Route path="/hello/time" exact component={Time} /> <Route path="/resume" exact component={Resume} /> </BrowserRouter> ); } export default App;
src/App.js

Component props 전달하기

현재 props를 전달해야할 컴포넌트는 Hello와 Resume입니다. 컴포넌트에 props를 전달해봅시다.
1) Route의 render 속성 사용하여 props 전달하기
2) 자식으로 렌더하여 컴포넌트에 props 전달하기
import React from "react"; import { BrowserRouter, Route } from "react-router-dom"; import Hello from "./Components/Hello"; import Time from "./Components/Time"; import Resume from "./Components/Resume"; import Home from "./Components/Home"; function App() { return ( <BrowserRouter> <Route path="/" exact component={Home} /> <Route path="/hello" exact render={() => <Hello name="개리" />} /> <Route path="/time" exact component={Time} /> <Route path="/resume" exact> <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> </Route> </BrowserRouter> ); } export default App;
src/App.js
 

Link

<Link>
<Link to="/about">home</Link>
 
to 속성에는 접근할 경로가 들어갑니다. 문자열이나 객체의 형태로 경로를 넣어줄 수 있습니다.
문자열에 경우 html 태그의 <a> 의 속성 href 에 넣어준 값처럼 절대경로 또는 상대경로를 문자열의 형태로 작성해주면 됩니다.
객체로 넣어줄 경우 pathname, search, hash, state 프로퍼티의 값들을 넣어서 객체 형태로 작성합니다.
// Link 작성하는 방법 // 문자열 <Link to="/courses?sort=name" /> // 객체 <Link to={{ pathname: "/courses", search: "?sort=name", hash: "#the-hash", state: { fromDashboard: true } }} />
 
 
a태그를 쓰지않고 link 를 사용하는 이유가 뭘까요?
a태그는 클릭했을 경우, href에 설정해준 경로 이동과 동시에 페이지를 새로 불러오기때문에 페이지가 새로고침이 됩니다.
react-router-dom이 제공하는 Link의 경우 HTML5 History API를 사용해서 브라우저의 주소를 바꿔주는 것이기 때문에 페이지를 불러오지 않고, dom만 조작해서 페이지를 보여줍니다.
 
import React from "react"; import { BrowserRouter, Route, Link } from "react-router-dom"; import Hello from "./Components/Hello"; import Time from "./Components/Time"; import Resume from "./Components/Resume"; import Home from "./Components/Home"; function App() { return ( <BrowserRouter> <Link to="" style={{ margin: "0 5px" }}> 홈 </Link> <Link to="/time" style={{ margin: "0 5px" }}> 현재시간 </Link> <Link to="/hello" style={{ margin: "0 5px" }}> 안녕 </Link> <Link to="/Resume" style={{ margin: "0 5px" }}> 소개 </Link> <Route path="/" exact component={Home} /> <Route path="/hello" exact render={() => <Hello name="개리" />} /> <Route path="/time" exact component={Time} /> <Route path="/resume" exact> <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> </Route> </BrowserRouter> ); } export default App;
src / App.js에 link를 추가합니다
홈을 클릭 : localhost:3000/
현재시간을 클릭 : localhost:3000/time
소개를 클릭하면 : localhost:3000/resume
안녕을 클릭하면 : localhost:3000/hello
 

Switch

기존 Route에 exact 를 사용하여도 되지만, exact 의 경우 Route마다 각각 설정을 해줘야합니다. <Switch>로 Route들을 감싸주면 첫번째로 매칭되는 path (아래 코드에서는 “/”) 를 가진 컴포넌트를 렌더링시키기 때문에 가장 상단에 컴포넌트에만 exact 를 작성합니다.
import React from "react"; import { BrowserRouter, Route, Switch, Link } from "react-router-dom"; import Hello from "./Components/Hello"; import Time from "./Components/Time"; import Resume from "./Components/Resume"; import Home from "./Components/Home"; function App() { return ( <BrowserRouter> <Link to="" style={{ margin: "0 5px" }}> 홈 </Link> <Link to="/time" style={{ margin: "0 5px" }}> 현재시간 </Link> <Link to="/hello" style={{ margin: "0 5px" }}> 안녕 </Link> <Link to="/Resume" style={{ margin: "0 5px" }}> 소개 </Link> <Switch> <Route path="/" exact component={Home} /> <Route path="/hello" render={() => <Hello name="개리" />} /> <Route path="/time" component={Time} /> <Route path="/resume"> <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> </Route> </Switch> </BrowserRouter> ); } export default App;
src / App.js에 switch 추가합니다.
 

중첩라우터

하나의 경로에서 더 세부적으로 경로를 나눌 때 사용합니다. 라우팅이 되고 그 안에서 라우팅이 한 번 더 되는 형태입니다.
import React from "react"; import { BrowserRouter, Route, Switch, Link } from "react-router-dom"; import Hello from "./Components/Hello"; import Time from "./Components/Time"; import ResumeRouter from "./Components/ResumeRouter"; import Home from "./Components/Home"; function App() { return ( <BrowserRouter> <Link to="" style={{ margin: "0 5px" }}> 홈 </Link> <Link to="/time" style={{ margin: "0 5px" }}> 현재시간 </Link> <Link to="/hello" style={{ margin: "0 5px" }}> 안녕 </Link> <Link to="/resume" style={{ margin: "0 5px" }}> 소개 </Link> <Switch> <Route path="/" exact component={Home} /> <Route path="/hello" render={() => <Hello name="개리" />} /> <Route path="/time" component={Time} /> <Route path="/resume" children={ResumeRouter} /> </Switch> </BrowserRouter> ); } export default App;
src / App.js
import React from "react"; import { Route, Switch } from "react-router-dom"; import Resume from "./Resume"; const resumeId = ({ match }) => { console.log(match); return ( <> <div>path : {match.path}</div> </> ); }; const ResumeRouter = () => { return ( <Switch> <Route exact path="/resume/"> <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> </Route> <Route path="/resume/1" component={resumeId}></Route> <Route path="/resume/2" component={resumeId}></Route> <Route path="/resume/3" component={resumeId}></Route> </Switch> ); }; export default ResumeRouter;
src / Components / ResumeRouter.js
 
위에 있는 ResumeRouter와 같은 결과를 가집니다.
다른 점은 Route가 Route와 연결된 컴포넌트에 자동으로 전달하는 값인 match 사용의 유무입니다. 아래 코드에서는 path를 지정할 때 /resume/ 라고 작성하지 않고 props로 전달되는 match 값을 사용하였습니다.
import React from "react"; import { Route, Switch } from "react-router-dom"; import Resume from "./Resume"; const resumeId = ({ match }) => { console.log(match); return ( <> <div>path : {match.path}</div> </> ); }; const ResumeRouter = ({ match }) => { console.log("render"); return ( <Switch> {/* <Route exact path="/resume "></Route> */} <Route exact path={match.path} component={resumeId}></Route> <Route path={`${match.path}/1`} component={resumeId}></Route> <Route path={`${match.path}/2`} component={resumeId}></Route> <Route path={`${match.path}/3`} component={resumeId}></Route> </Switch> ); }; export default ResumeRouter;
src / Components / ResumeRouter.js

Route 사용하여 페이지 경로 만들기

  • Home Page : /
  • Product Detail Page : /products/:id
    • ex) /products/1 , /products/2, /products/3, /products/4
  • Cart Page : /cart
  • Coupon Page : /users/coupon
  • Question Page : /users/question
  • Notice Page : /users/notice
  • User Page : /users
 
실행해보세요!
routerHW.zip
2.1KB
 
React Router V6
React Router
React Router v6 is here. React Router v6 takes the best features from previous versions-and its sister project, Reach Router-in our smallest and most powerful package yet.
React Router
https://reactrouter.com/docs/en/v6
React Router
 
React Router V4/5
React Router: Declarative Routing for React
Learn once, Route Anywhere
React Router: Declarative Routing for React
https://v5.reactrouter.com/
React Router: Declarative Routing for React
 

ReactRouter V6가 되면서 달라진 문법들

공식문서
React Router
We are actively working on a backwards compatibility layer that implements the v5 API on top of the v6 implementation. This will make upgrading as smooth as possible. You'll be able to upgrade to v6 with minimal changes to your application code. Then, you can incrementally update your code to the v6 API.
React Router
https://reactrouter.com/docs/en/v6/upgrading/v5
React Router
 
  • 업데이트(버전 명시 안해주시면 버전 Up 됩니다.)
npm install react-router-dom

1. Routes

Switch는 사라지고 Routes가 Switch를 대체합니다.
 
기존 코드
<Switch> <Route path="/" exact component={Home} /> <Route path="/time" component={Time} /> </Switch>
 
v6코드
<Routes> <Route path="/" exact component={Home} /> <Route path="/time" component={Time} /> </Routes>
 
 

2. exact가 사라지다

V6부터는 exact가 기본으로 Route에 되어있어서 더 이상 exact props를 작성하지 않아도 정확한 경로로 이동이 가능합니다.
 
기존 코드
<Route path="/" exact component={Home} /> <Route path="/time" exact component={Time} />
 
v6코드
<Route path="/" component={Home} /> <Route path="/time" component={Time} />
 

3. element

Route에 컴포넌트를 전달할 때 children이나 component를 사용하였지만, v6부터는 element를 사용하여 컴포넌트를 전달해야 합니다.
Route와 연결된 컴포넌트에게 필요한 props를 전달할 때도 기존코드와 같이 전달하지 않고 기존 JSX문법을 사용해서 전달해주면 됩니다.
기존코드
<Route path="/" exact component={Home} /> <Route path="/hello" render={() => <Hello name="개리" />} /> <Route path="/time" component={Time} /> <Route path="/resume"> <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> </Route>
 
v6코드
<Route path="/" element={<Home />} /> <Route path="/hello" element={<Hello name="개리" />} /> <Route path="/time" element={<Time />} /> <Route path="/resume" element={ <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> } ></Route>
 

4. Route의 부모로 Routes

기존에 v5에서는 swtch로 Route를 감싸는 것은 선택사항이었다면 v6에서 switch의 대체 역할인 Routes는 반드시 Route를 감싸야하며 반드시 Route는 Routes의 직속자식이어야 합니다.
 
기존코드
<Route path="/" exact component={Home} /> <Route path="/hello" exact render={() => <Hello name="개리" />} /> <Route path="/time" exact component={Time} />
 
v6코드
<Routes> <Route path="/" element={<Home />} /> <Route path="/hello" element={<Hello name="개리" />} /> <Route path="/time" element={<Time />} /> </Routes>
 

5. 중첩된 라우터

 
v6코드
방법1 /resume/ 다음에 더 상세 경로를 지정할 때 아래와 같이 Route안에 Route 형태로 작성하면 됩니다.
element로 전달되는 컴포넌트에는 리액트 라우터에서 제공하는 <Outlet/> 컴포넌트를 return해주어야 합니다.
import React from "react"; import { BrowserRouter, Route, Routes, Link, useParams, Outlet, } from "react-router-dom"; import Resume from "./Components/Resume"; const ResumeId = () => { return ( <> <Outlet /> </> ); }; function App() { return ( <BrowserRouter> <Routes> <Route path="resume/*" element={<ResumeId />}> <Route path="" element={ <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> } ></Route> </Route> </Routes> </BrowserRouter> ); } export default App;
 
방법2 직접기재해줍니다.
const ResumePage = () => { return ( <div> <Routes> <Route path=":id" element={<ResumeId />}></Route> <Route path="/" element={ <Resume hello="Hello" name="개리" hobby="게임" food="고기" color="blue" /> } ></Route> </Routes> </div> ); }; const ResumeId = () => { const a = useParams(); return ( <> <div>{a.id}</div> </> ); }; function App() { return ( <BrowserRouter> <Link to="" style={{ margin: "0 5px" }}> 홈 </Link> <Link to="/time" style={{ margin: "0 5px" }}> 현재시간 </Link> <Link to="/hello" style={{ margin: "0 5px" }}> 안녕 </Link> <Link to="/Resume" style={{ margin: "0 5px" }}> 소개 </Link> const ResumeId = () => { const a = useParams(); return ( <> <div>{a.id}</div> </> ); }; </BrowserRouter> ); }