Next.js로 정적 웹사이트 만들기 - 4. Routing 사용하기
지난 글에서 index.js와 post.js를 생성했었고 Routing을 사용하지 않고 URL로 직접 접근해서 화면을 확인했었다. 이번 글에서는 Next.js의 Routing을 사용하여 페이지 전환을 해보려고한다.
Next.js github에
Routing에 대한 설명이 잘 나와있다.
Next.js에서Route는pages디렉토리 경로에 작성한 파일명으로 생성된다. 그렇기 때문에, 파일명도 신경써서 잘 만들어야한다.
about.js 파일 생성
Routing 경로를 더 추가하기 위해 pages디렉토리에 about.js파일을 추가하고 다음과 같이 작성한다.
export default (props) => {
return (
<div>About</div>
);
}
about.js까지 생성하였다면 총 3개의 Routing이 생기게 되었다.
_app.js에 Link 컴포넌트 추가
그런 다음, 공통의 레이아웃이 작성된 _app.js에서 <header>엘리먼트 안에 <Link> 컴포넌트를 추가하여 생성한 Routing 연결해본다.
import React from 'react';
import App, { Container } from 'next/app';
import Head from 'next/head';
import Link from 'next/link';
const styles = {
layout: {
display: 'flex',
width: '100%',
height: '100%',
flexDirection: 'column',
},
header: {
height: 60,
},
main: {
flex: 1,
},
footer: {
height: 60,
},
divider: {
margin: '0 8px',
},
}
export default class RootApp extends App {
render() {
const { Component, ...other } = this.props;
return (
<Container>
<Head>
<title>Static Website</title>
</Head>
<div style={styles.layout}>
<header style={styles.header}>
<Link href="/"><a>Home</a></Link>
<span style={styles.divider}>|</span>
<Link href="/post"><a>Post</a></Link>
<span style={styles.divider}>|</span>
<Link href="/about"><a>About</a></Link>
</header>
<main style={styles.main}>
<Component {...other} />
</main>
<footer style={styles.footer}>Footer</footer>
</div>
</Container>
);
}
}
import Link from 'next/link'로 모듈을 import 해주고 <Link> 컴포넌트에 href Props 값으로 pages디렉토리에서 생성한 파일명을 작성해준다. 마지막으로 <Link>안에는 <a>를 추가해준다.
여기까지 작성되었다면 다음과 같은 화면이 보일 것이다.

한 번씩 눌러본다.

post.js에 Router 추가
다음으로, <button>엘리먼트 onClick을 이용해서 Routing을 해보는데, 이때 Next.js의 Router를 사용해본다.
먼저, <Link>와 Router의 큰 차이점은 클라이언트 사이드로 렌더링 하냐 안하냐에 있다.
Router.push를 사용하면 클라이언트 사이드로 렌더링을 한다.
import Router from 'next/router';
export default (props) => {
return (
<div>
First post page
<div>
<button onClick={() => Router.push('/')}>Home</button>
</div>
</div>
);
}
post.js에서 import Router from 'next/router'로 모듈을 import 해주고 <button>을 추가한 다음 onClick 속성에 Router.push('/')를 추가한다.
여기까지 작성되었다면 다음처럼 동작한다.

마찬가지로 about.js에도 추가해준다.
import Router from 'next/router';
export default (props) => {
return (
<div>
About
<div>
<button onClick={() => Router.push('/')}>Home</button>
</div>
</div>
);
}
URL Params(Query String) 전달
다음으로 Routing을 할 때, URL로 Parameter를 전달하여 각 페이지에서 전달받은 Parameter를 화면에 처리할 수 있도록 해본다.
Home버튼을 클릭 했을 때, 어떤 페이지에서Home으로 돌아왔는지 확인해보는 예제를 작성한다.
post.js에서 했던 것처럼 about.js에도 <button>엘리먼트를 추가하고 onClick속성에 Router.push를 추가한다.
그러고 나서 post.js와 about.js에 작성된 Router.push('/')를 각각 Router.push('/?history=post')와 Router.push('/?history=about')로 변경해준다.
post.js
import Router from 'next/router';
export default (props) => {
return (
<div>
First post page
<div>
<button onClick={() => Router.push('/?history=post')}>Home</button>
</div>
</div>
);
}
about.js
import Router from 'next/router';
export default (props) => {
return (
<div>
About
<div>
<button onClick={() => Router.push('/?history=about')}>Home</button>
</div>
</div>
);
}
이렇게 작성된 페이지에서 Home 버튼을 클릭하여 Home경로로 가게 됐을 경우, URL에는 Query String이 붙게 되었고, index.js에 전달되는 props에 console.log(props)로 로그를 확인해보면 Develop Console에 다음처럼 보이게 된다.

props에 router 오브젝트가 전달되는데, router 오브젝트 안에서 전달된 query를 확인할 수 있다.
이것을 활용해서 index.js에서 어떤 페이지로부터 넘어왔는지 확인해본다.
index.js
const styles = {
from: {
color: 'red',
},
};
export default (props) => {
const { router } = props;
return (
<div>
Home
{
router.query.history ? (
<div style={styles.from}>
From the {router.query.history}
</div>
) : null
}
</div>
);
}
화면을 확인해본다.

as 속성으로 URL Params 숨기기
URL Params가 URL에 보이는 것이 맘이 편하지 않다면 Next.js에서는 숨길 수 있는 방법이 있다.
as속성을 이용하는 것인데, <Link href="/?history=post" as="/">로 사용하거나 Router.push("/?history=post", '/')로 사용할 수 있다.
post.js와 about.js에 가서 다음과 같이 바꿔준다.
post.js
import Router from 'next/router';
export default (props) => {
return (
<div>
First post page
<div>
<button onClick={() => Router.push('/?history=post', '/')}>Home</button>
</div>
</div>
);
}
about.js
import Router from 'next/router';
export default (props) => {
return (
<div>
About
<div>
<button onClick={() => Router.push('/?history=about', '/')}>Home</button>
</div>
</div>
);
}
다시 화면을 확인해본다.

아까와는 다르게 URL에 Query String이 붙지 않고 history가 전달된 것을 확인할 수 있다.
하지만 이 방법에서 문제점을 찾으라고 한다면, 새로고침을 했을 때 전달받은
router오브젝트에query가 비어있으므로From the문구가 보이지 않게 된다.
withRouter 사용
다음으로 withRouter를 사용해볼 것인데, 이 녀석은 Router의 HOC로써 컴포넌트에서 router props를 전달받을 수 있도록 해준다.
History 예제를 위해서 root 경로에 components 디렉토리를 만들고 하위에 History.js 파일을 생성한다.
그런 다음, History.js에는 다음과 같이 작성한다.
History.js
import React, { Component } from 'react';
import { withRouter } from 'next/router';
const styles = {
history: {
color: 'red',
},
};
class History extends Component {
render() {
const { router } = this.props;
return router.query.history ? (
<div style={styles.history}>
{router.query.history}
</div>
) : null;
}
}
export default withRouter(History);
import { withRouter } from 'next/router'로 모듈을 import 시키고 withRouter(History)로 Component를 감싸게 되면 props로 router를 전달받을 수 있게 된다.
index.js는 다음과 같이 변경한다.
index.js
import History from '../components/History';
export default (props) => {
return (
<div>
Home
<History />
</div>
);
}
작성한 후에 화면을 확인한다.

index.js에서 <History>로 router를 props으로 전달하지 않지만 <History>컴포넌트에서 HOC로 withRotuer를 사용했기 때문에 props로 router오브젝트를 전달받은 것을 볼 수 있다.

Next.js로 정적 웹사이트 만들기 목차
