3-3. 404 페이지 완성하기
현재 주어진 주소에 알맞는 라우트가 없을 때, 우리는 NotFoundPage 라우트가 보여지도록 설정을 했었습니다. 지금은 아직 이 컴포넌트를 작성하지 않았기 때문에 지정되지 않은 주소로 들어가게 되면 다음과 같이 나타날 것입니다.

이 페이지를 다음 이미지처럼 간단하게 꾸며보겠습니다.

components/common 디렉토리에 NotFound 라는 함수형 컴포넌트를 만드세요.
src/components/common/NotFound/NotFound.js
import React from 'react';
import styles from './NotFound.scss';
import classNames from 'classnames/bind';
import Button from 'components/common/Button';
const cx = classNames.bind(styles);
const NotFound = ({onGoBack}) => (
<div className={cx('not-found')}>
<h2>
존재하지 않는 페이지입니다.
</h2>
<Button onClick={onGoBack} theme="outline">
돌아가기
</Button>
</div>
);
export default NotFound;
이 컴포넌트에서는 onGoBack 이라는 props 를 전달받아서 내부의 돌아가기 버튼에 클릭 이벤트를 연결해주었습니다.
이제 이 컴포넌트를 스타일링 하세요.
src/components/common/NotFound.scss
@import 'utils';
.not-found {
height: 100vh;
background: $oc-blue-6;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
h2 {
font-size: 1.5rem;
color: white;
font-weight: 400;
}
}
코드를 다 작성하셨다면, 이 컴포넌트를 NotFoundPage 에서 불러와서 렌더링해주면 됩니다.
src/pages/NotFoundPage.js
import React from 'react';
import NotFound from 'components/common/NotFound';
const NotFoundPage = ({history, staticContext}) => {
// staticContext 는 서버쪽에서만 존재합니다.
if (staticContext) {
staticContext.isNotFound = true;
}
return (
<NotFound onGoBack={history.goBack}/>
);
};
export default NotFoundPage;
해당 페이지 컴포넌트에선 리액트 라우터가 전달해주는 props 인 history 와 staticContext 를 받아옵니다.
history 의 내장함수인 goBack 함수를 NotFound 컴포넌트의 onGoBack 으로 넣어주세요.
staticContext 는 서버 렌더링을 하는 StaticRouter 를 사용 할 때만 존재하는 객체로서, 브라우저에선 존재하지 않습니다. 이 객체는, 렌더링을 한 후, 서버에 특정 정보를 전달해야 할 때 사용합니다.
우리는 NotFoundPage 가 렌더링 된다면, HTTP 상태를 404로 전달하도록 설정하기 위해서, staticContext 의 isNotFound 값을 true 로 설정해주었습니다.
이제, ssr.js 에서 렌더링을 하게 될 때 context 를 확인하여 HTTP 상태를 404 로 설정해보겠습니다.
src/ssr.js
(...)
const render = async (ctx) => {
(...)
// context 값을 빈 객체로 설정합니다.
const context = {};
// renderToString 은 렌더링된 결과물을 문자열로 만들어줍니다.
// 서버에서는 BrowserRouter 대신에 StaticRouter 를 사용합니다.
const html = ReactDOMServer.renderToString(
<Provider store={store}>
<StaticRouter location={url} context={context}>
<App/>
</StaticRouter>
</Provider>
);
// isNotFound 값이 true 라면
if(context.isNotFound) {
ctx.status = 404; // HTTP 상태를 404로 설정해줍니다
}
(...)
context 라는 비어있는 객체를 만들어서 StaticRouter 의 props 로 넣어주었습니다. 렌더링이 마치고 나서 만약에 NotFoundPage 가 렌더링 됐었으면 isNotFound 의 값이 true 로 됩니다. 이러한 경우에, ctx.status 값을 404 로 설정을 해주면 됩니다.
이제 리액트 어플리케이션을 다시 빌드하세요.
$ yarn build
$ yarn build:server
그 다음에, 크롬 개발자도구의 네트워크 탭을 열은 다음에 존재하지 않는 페이지로 이동한다면 다음과 같이 HTTP 상태가 404로 뜰 것입니다:

빨간색 404 Not Found 메시지가 잘 나타났나요?