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

hoon·2023년 5월 19일
0

도입 배경

이전 포스팅에 프로젝트를 진행하면서 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개의 댓글