서버사이드 렌더링 SSR

✔️ 사전 렌더링(pre-rendering)이란?

Next.js는 모든 페이지를 사전 렌더링(pre-rendering)을 하는데

  • 더 좋은 퍼포먼스를 내고
  • 검색엔진최적화(SEO)에도 효율적이다.
    • SEO: Search Engine Optimization의 약자로 검색 엔진 최적화를 의미한다. 메타 태그를 이용해 description, keywords, author, subject, classification 등의 정보를 표기할 수 있으며, 검색엔진은 이런 정보를 적극적으로 활용한다.

pre-rendering: 미리 HTML들을 만들어 두는 것?!



✔️ 사전 렌더링(pre-rendering)의 종류

📌 정적 생성SSR의 차이점은, 언제 `HTML`을 생성하는가?

  • 유저가 요청하기 전에 미리 페이지를 만들어도 상관없다면 정적 생성을 적용
    • 예시) 마케팅 페이지, 블로그 게시물, 도움말 문서 등

1) 정적 생성

  • 프로젝트가 빌드하는 시점HTML 파일들이 생성됨
  • (생성된 HTML을) 모든 요청에 재사용
  • 퍼포먼스 이유로, Next.js는 정적 생성을 권고
  • 정적 생성된 페이지들은 CDN에 캐시된다
  • getStaticProps / getStaticPaths


✔️ Custom Error Page 404

next.js는 자주 사용하는, 서버에서 렌더링 할 필요가 없는 에러 페이지인 404, 500 페이지를 기본적으로 제공한다 하지만 디자인 또는 정보를 추가하고 싶을 경우 수정 가능하다

  • pages > 404.ts 파일 생성
  • 빌트 타임에 정적 생성된다.
import type { NextPage } from "next";
import { Icon } from "semantic-ui-react";
import styled from "styled-components";

const Error404: NextPage = () => {
  return (
    <ErrorWrap>
      <img alt='logo' src='/images/web_logo.png' />
      <Icon name='warning circle' color='red' />
      404: 페이지를 찾을 수 없습니다!
    </ErrorWrap>
  );
};

export default Error404;


✔️ Custom Error Page 500

  • 공식문서
  • pages > _error.ts 파일 생성
    • 이 페이지는 정적으로 최적화되어 있진 않다
    • 에러 발생 시 에러의 로그 등을 서버쪽으로 보내야 하는 경우가 필요하기 떄문
  • npm build && npm start
function Error({ statusCode }) {
  return (
    <p>
      {statusCode
        ? `An error ${statusCode} occurred on server`
        : "An error occurred on client"}
    </p>
  );
}

Error.getInitialProps = ({ res, err }) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode };
};

export default Error;



2) Server-side Rendering(SSR, Dynamic Rendering)

  • 매 요청 마다 HTML을 생성(되기 때문에 퍼포먼스가 떨어질 순 있다)
  • CDN에 캐시되지 않기 때문에 조금 느릴 순 있지만,
  • 서버를 통해 프리 렌더링이 된 페이지는 항상 최신 상태를 유지한다.
  • getServerSideProps
import type { NextPage } from "next";
import Head from "next/head";
import { getProduct } from "../api/api";

const ProductItem: NextPage = ({ item }: any) => {
  return (
    item && (
      <>
        <Head>
          <title>{item.name}</title>
          <meta name='descriprion' content={item?.description} />
        </Head>
        // ... 생략
      </>
    )
  );
};

export default ProductItem;

export async function getServerSideProps(context: any) {
  const id = context?.params.id;
  const data = await getProduct(Number(id));

  return {
    // ProductItem 컴포넌트의 props로 전달된다
    props: {
      item: data,
    },
  };
}