Next.js 도입시 스타일링 이슈 해결하기

hoon·2023년 5월 19일

도입 배경

이전 포스팅에 프로젝트를 진행하면서 Next.js를 도입하게된 이유에 대해서 설명하였다. Next.js는 서버 사이드 렌더링(SSR)을 지원하여 초기 페이지 로딩 속도를 향상시키고, SEO에 유리한 구조를 제공하는 등 많은 장점을 갖춘 프레임워크이다.하지만, Next.js를 도입하면서 가장 큰 문제는 클라이언트 사이드에서만 동작하는 라이브러리와의 호환성이다. 그 중에서도 CSS-in-JS 라이브러리인 styled-components를 사용하면서 발생한 스타일링 이슈를 이 글에서는 자세히 다루어보자.

문제 상황

기존 프로젝트에서는 React와 styled-components를 이용해 개발했었다. 하지만 Next.js를 도입한 후, 서버 사이드에서 렌더링된 페이지는 스타일이 제대로 적용되지 않는 문제가 발생했다.

문제 원인

Next.js와 styled-components를 함께 사용할 때, 서버 사이드 렌더링과 클라이언트 사이드 렌더링 간에 스타일 순서 불일치 문제가 발생할 수 있다. 이는 Next.js가 페이지를 서버에서 렌더링할 때 스타일이 제대로 적용되지 않은 채로 HTML을 클라이언트로 전달하기 때문에 발생하는 문제이다.

해결 방법

이 문제를 해결하기 위해서는 Next.js와 styled-components가 서버 사이드 렌더링 시에도 스타일을 제대로 적용할 수 있도록 설정을 조정해야 한다._document.js 파일을 수정하여, 서버에서 페이지를 렌더링할 때 styled-components의 스타일을 수집하도록 하였다.

// pages/_document.js
import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components'; // styled-components 패키지에서 제공하는 도구로, 서버에서 스타일을 수집

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    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();
    }
  }
}
  1. 먼저 ServerStyleSheet를 생성한다. 이것은 styled-components가 서버 사이드에서 스타일을 수집하기 위해 제공하는 클래스이다.

  2. 원래의 renderPage 함수를 저장하고, 새로운 renderPage 함수를 제공한다. 이 새로운 함수는 App 컴포넌트를 렌더링하면서 그 안에 있는 모든 styled-components 스타일을 수집한다.

  3. 원래의 getInitialProps 함수를 호출하여 기본 문서 속성을 가져온다.

  4. getStyleElement 메소드를 이용해서 수집된 스타일을 HTML 스타일 태그로 변환한다.

  5. 이 스타일 태그와 기본 문서 속성을 합친 새로운 문서 속성을 반환한다. 이 반환된 속성은 최종적으로 클라이언트에 전송될 HTML 문서에 적용된다.

마지막으로 seal 메소드를 호출해서 더 이상 스타일을 수집하지 않도록 한다.

이렇게 설정하면, 서버에서 페이지를 렌더링할 때 styled-components의 스타일을 수집하여 초기 HTML과 함께 전달한다. 이를 통해 서버 사이드 렌더링에서도 styled-components의 스타일이 제대로 적용되도록 할 수 있다.

또한, 이 문제를 해결하기 위해 .babelrc 파일에 styled-components 플러그인을 추가한다.

// .babelrc
{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

이렇게 설정하면, Next.js와 styled-components를 함께 사용하여도 서버 사이드 렌더링 시에 스타일이 제대로 적용된다.

profile
프론트엔드 학습 과정을 기록하고 있습니다.

0개의 댓글