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 메시지가 잘 나타났나요?

results matching ""

    No results matching ""