본문 바로가기

Study

[Next.js 14] styled-component 사용 시 "className did not match" 에러

styled-component를 사용하는데 className did not match 에러가 발생했다.

 

에러 로그에도 나와 있듯이 서버에서 렌더링 된 className과 클라이언트에서 렌더링 된 className의 불일치로 인해 발생하는 에러였다.

위 에러로 인해서 첫화면 렌더링시에는 css가 안먹히다가 코드 수정 후 저장해 재렌더링 했을 경우에만 먹히는 이슈가 발생했다.

검색해보니 Next.js에서 styled-component를 사용하기 위해서 서버와 클라이언트의 스타일 일치를 보장하기 위한 추가 설정이 필요하다고 한다.

1. next.config.js 설정 추가

next.config.js 파일에 styledComponent 를 활성화해준다.

const nextConfig = {
  compiler: {
    styledComponents: true,
  },
}

module.exports = nextConfig

 

2. registry.tsx 파일 생성 후 글로벌 레지스트리 함수 추가

프로젝트 루트에 lib 폴더를 생성하고 lib폴더 내에 registry.tsx 파일 생성 후 아래 코드를 추가해준다.

아래 코드는 styled-component API를 사용하여 렌더링 중에 생성된 모든 CSS 스타일 규칙을 수집하는 글로벌 레지스트리 구성 요소와 해당 규칙을 반환하는 함수를 생성하는 코드로 공식 문서에 친절히 나와있다.

"use client"

import React, { useState } from "react"
import { useServerInsertedHTML } from "next/navigation"
import { ServerStyleSheet, StyleSheetManager } from "styled-components"

export default function StyledComponentsRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // Only create stylesheet once with lazy initial state
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())

  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement()
    styledComponentsStyleSheet.instance.clearTag()
    return <>{styles}</>
  })

  if (typeof window !== "undefined") return <>{children}</>

  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  )
}

3. 전역 layout.tsx 파일에 StyledComponentsRegistry 적용

2번 단계에서 만들었던 StyledComponentsRegistry를 import해와서 children을 감싸주면 모든 설정이 완료된다.

import React from "react"
import StyledComponentsRegistry from "../lib/registry"

export const metadata = {
  title: "Styled components",
  description: "Styled components Test",
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}

 

이렇게 모든 단계를 적용하고 나면 className did not match 에러가 사라지고 css도 정상적으로 먹히는 것을 확인 할 수 있다.

 

 

✨ 참고문서 ✨

https://nextjs.org/docs/app/building-your-application/styling/css-in-js#styled-components