설치하기BrowserRouterRoute정확한 경로 설정 : exactComponent props 전달하기LinkSwitch중첩라우터Route 사용하여 페이지 경로 만들기ReactRouter V6가 되면서 달라진 문법들1. Routes2. exact가 사라지다3. element4. Route의 부모로 Routes5. 중첩된 라우터
React Router v4/5 docs 기준입니다. v6은 2021년 11월에 나왔습니다.
React Router 코드
설치하기
App을 보게되면 총 3개의 컴포넌트를 가지고있습니다.
그런데 이것들을 모두 다른 주제를 가지고있어 다른페이지에서 보여주고싶습니다.

따라서 지금까지 진행한 내용을 여러 주소로 나누고 각 주소별로 다른 컴포넌트를 사용하도록 해보겠습니다.
우리는 현재 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;

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;
Route
앞서 만든 라우트에서의 "/", 즉 메인페이지로 이동하면 아무것도 나오지 않습니다. 홈 화면을 만들기 위해 남겨뒀는데요. Components 폴더에 Home.js 파일을 하나 만들어두고 아래와 같이 작성해보겠습니다.
import React from 'react'; function Home(props) { return( <div> <h1>Home 화면!</h1> </div> ) } export default Home
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;
이 상태에서 주소에 접속하면 홈 화면이 제대로 나옵니다!

다음 '/hello' 페이지로 이동해보겠습니다.

잘 나온것 같은데 홈 화면이 같이 출력되었습니다. 이런 현상은 '/' 주소와 '/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;
/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;
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;
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;
홈을 클릭 : 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;
중첩라우터
하나의 경로에서 더 세부적으로 경로를 나눌 때 사용합니다. 라우팅이 되고 그 안에서 라우팅이 한 번 더 되는 형태입니다.
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;
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;
위에 있는 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;
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
실행해보세요!
React Router V6
React Router V4/5
ReactRouter V6가 되면서 달라진 문법들
공식문서
- 업데이트(버전 명시 안해주시면 버전 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> ); }