리액트 라우트를 사용하면서 Routes.js 파일을 여러번 개선하였다. 그 과정을 정리하고자 한다.
이 글의 코드 개선은 짧은 경험에서 나온 결과물이므로 정답이 아닐 수 있습니다. 더 좋은 방법이 있거나 잘못된 방향으로 코드 개선이 이루어졌다면 그에 관한 소중한 의견 부탁드립니다.
<Router>
<Switch>
<Route exact path="/Home" component={Home}></Route>
<Route exact path="/Signup" component={Signup}></Route>
<Route exact path="/Login" component={Login}></Route>
<Route exact path="/ItemList" component={ItemList}></Route>
<Route exact path="/ItemDetail" component={ItemDetail}></Route>
</Switch>
</Router>
경로에 따라 보여지는 컴포넌트를 다르게 하는 기본적인 리액트 라우트 라이브러리의 기능을 구현한 코드이다.
<Router>
<Header />
<AsideMenu />
<Switch>
<Route exact path="/Home" component={Home}></Route>
<Route exact path="/Signup" component={Signup}></Route>
<Route exact path="/Login" component={Login}></Route>
<Route exact path="/ItemList" component={ItemList}></Route>
<Route exact path="/ItemDetail" component={ItemDetail}></Route>
</Switch>
<Footer />
</Router>
많은 웹 페이지에는 Header와 Footer가 존재한다. 혹은 사이드 메뉴가 있는 경우도 있다. 이런 공통 컴포넌트는 해당 사이트 내에서 라우팅을 할 때 공통적으로 항상 보여지는 컴포넌트로 위 코드와 같이 분리하여 항상 보여지는 식으로 할 수 있다.
const HIDE_ASIDE_MENU = ["/Login", "/Signup"];
const aside = HIDE_ASIDE_MENU.includes(window.location.pathname) ? null : <AsideMenu />;
class Routes extends Component {
render() {
return (
<Router>
<Header />
{aside}
<Switch>
<Route exact path="/Home" component={Home}></Route>
<Route exact path="/Signup" component={Signup}></Route>
<Route exact path="/Login" component={Login}></Route>
<Route exact path="/ItemList" component={ItemList}></Route>
<Route exact path="/ItemDetail" component={ItemDetail}></Route>
</Switch>
<Footer />
</Router>
);
}
}
하지만 경우에 따라 공통 컴포넌트를 숨기고 싶은 경우도 있다. 만약 로그인 페이지와 회원가입 페이지에서는 사이드 메뉴 AsideMenu를 숨기고 싶을 때 위와 같이 코드를 작성할 수 있다. 만약 추가적인 변경사항이 있을 경우 HIDE_AISDE_MENU
변수를 수정하기만 하면 된다.
const HIDE_ASIDE_MENU = ["/Login", "/Signup", "/ItemCart"];
const aside = HIDE_ASIDE_MENU.includes(window.location.pathname) ? null : <AsideMenu />;
class Routes extends Component {
render() {
return (
<Router>
<Header />
{aside}
<Switch>
<Route exact path="/Home" component={Home}></Route>
<Route exact path="/Signup" component={Signup}></Route>
<Route exact path="/Login" component={Login}></Route>
<Route exact path="/ItemList" component={ItemList}></Route>
<Route exact path="/ItemDetail" component={ItemDetail}></Route>
<Route exact path="/ItemCart" component={ItemCart}></Route>
<Route exact path="/Payment" component={Payment}></Route>
<Route component={NotFound} />
</Switch>
<Footer />
</Router>
);
}
}
추가적으로 다른 페이지도 추가하고 마지막으로 404 페이지를 구현한 코드이다. 사용자가 주소이름을 잘못 입력하거나 어떠한 이유로 잘못된 path로 접근하려고 할 경우 NotFound
라는 컴포넌트가 Switch
내에서 보여진다. 이는 위에서부터 차례대로 해당하는 페이지가 있는지 탐색한 후 일치하는 경로가 없을 때 마지막으로 NotFound
페이지가 보이는 것이다. 이 컴포넌트에서 404 NOTFOUND에 대한 페이지 구성을 하면 될 것이다.
라우트가 받는 값에 대해 이전 글에서 조금 다룬 적이 있다. 라우터가 받는 histoyr, location, match의 내부 값들 중 아래 세 가지 값을 살펴보자.
location.pathname
match.path
match.url
이 세가지 이름만 보면 다 비슷해 보인다. 콘솔창에 값을 찍어보는 것이 가장 정확할 것이다. 그래서 현재 진행중인 마켓컬리 클론 팀 프로젝트에서 한번 찍어보았다!
console.log(`location.pathname: ${this.props.location.pathname}`);
console.log(`match.path: ${this.props.match.path}`);
console.log(`match.url: ${this.props.match.url}`);
하지만 결과는 처참히 같았다. 그러나 아직 방심하긴 이르다. 우리에겐 구글이 있다.
location.pathname
: 현재 브라우저상의 위치를 알려준다. 즉 /ItemDetail
이라는 위치를 나타낸다.match
에서는 해당 Route와 직접적으로 관계된 값만 보여준다. match.path
에서는 /ItemDetail/:id
와 같이 동적 라우팅을 구현했을 때 location.pathname
과 차이가 나타나게 된다. match.url
에서는 그 동적 라우팅에서 id의 값이 주어져있다면 /ItemDetail/3
처럼 나타나게 된다. 즉, 내가 console.log
로 확인한 컴포넌트는 아직 동적 라우팅으로 구현된 페이지가 아니기에 똑같이 나타난 것이다. 정리하자면 아래와 같다.
location.pathname
: /path
match.path
: /path/:id
match.url
: /path/43