[Next.js] CSS도 SSR하기

Marullo·2020년 12월 5일
0

CSS 렌더링 방식

styled-component 덕분에 우리는 css를 js코드 안에 작성할 수 있게 되었다.
그러나, 브라우저가 인식할 수 있는 css는 inline-css, style태그, css file 뿐이다.

우리가 웹을 키면 js 코드가 동작해야만, css가 읽힌다. 따라서 css 즉각적으로 반영되지 않는다.

Next에서 CSS 렌더링 방식

next.js는 프로젝트를 빌드할 때, css파일을 따로 chunk 파일로 만들어둔다.
html과 js코드는 하나의 청크로 묶여서 빌드되지만, css만 따로 묶인다.

next는 (Static Generation의 경우) build 시점에, 의존된 js 코드와 html을 묶어, 미리 페이지들을 HTML 파일로 만들어 두고 있다가, REQ가 오면, 미리 그려진 html 파일을 넘겨주는 방식을 사용한다.

이후, 클라이언트 측에서, css chunk 파일을 네트워크 호출하여, css를 적용한다.
즉 css는 클라이언트 사이드에서 렌더링 되는 것이다.

로드되는 css 데이터가 많은 경우, 혹은 새로고침을 연타하는 경우, 혹은 네트워크가 느린 경우에
css가 적용되지 않은 날것의 html이 보여진 후, css chunk가 도착하면 제자리로 돌아가는 장면을 보게된다.


위의 사진과 같이, 도착한 DOC에는 날 것의 HTML만 있다.

이것을 방지하기 위해, 서버측에서 css까지 렌더링하자.

CSS도 서버에서 그리기

위와 같은 일은
NEXT에서 HTML을 빌드할 때, CSS파일이 HTML의 head 태그에 포함되지 않기 때문에 발생한다.

따라서, 우리는 entry point에 해당하는 html의 head에 css파일을 import 해주면 된다.
next의 경우, _document 라는 파일로, next가 빌드하는 문서구조를 커스터마이징 할 수 있다. _document파일은 next.js의 entry point가 된다고 보면 된다.

주의할 점은, _document는 서버에서만 동작하기 때문에, onClick과 같이 브라우저에서 동작하는 코드는 절대 돌아가지 않는다는 것이다. 만약 클라이언트 사이드에서 특정 컴포넌트의 상태를 유지하거나, 모든 페이지에서 동일한 헤더를 띄우고 싶다면 _APP파일을 만들어서 사용하면 된다.

코드는 next 예제에 나와있다.
https://github.com/vercel/next.js/blob/canary/examples/with-styled-components/pages/_document.js

import Document, { DocumentContext } from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}
profile
한국외대 중국어&컴공 복수전공 - 세미 전공자의 기술 블로그

0개의 댓글