[next.js] styled-components 미적용 에러

Dora_ bang·2023년 10월 26일
1

오류일지

목록 보기
3/3

오늘은 구글신의 힘을 빌려 오류해결이 아닌 공식문서를 찾아보고 에러를 해결해봤다!!!

오늘 발생한 에러는 next.js에서 styled-components를 사용했을 때 발생하는 에러다.

그러면 오늘의 에러를 해결해보자~!




발생원인

next.js는 첫 화면은 ssr로 화면을 렌더하지만, 그 이후 페이지 이동 시 csr로 렌더링되기 때문이다. 그렇기 때문에 새로고침이나 페이지 이동 시에 서버에서 받은 해시+클래스명과 클라이언트에서 받은 해시+클래스명이 달라 발생하는 오류였다.

구글링에서 찾은 해결 방법은 이러했다.


해결법_1

  1. 스타일 컴포넌트 바벨 플러그인 설치
npm i babel-plugin-styled-components

  1. .babelrc 설정

루트 폴더에 .babelrc 파일 생성 후, 아래와 같이 설정 코드를 넣어주면 된다.

{
  "presets": ["next/babel"],
  "plugins": ["babel-plugin-styled-components"]
}

라고 나와있다.

그리고 열심히 단계에 따라 작업을 진행했으나, next.js에서 무수히 많은 오류를 뱉어냈고,,,

next.js와 충돌을 일으키는 것 같았다,,☆

그래서 바벨 커스텀 설정 파일 삭제 후, next.js 공식문서에서 열심히 리서치한 결과는 다음과 같았다.



해결법_2

next.js에서는 tailwindCSSCSS Module, postCSS와 같이 CSS 파일을 출력하는 라이브러리를 권장하는 듯 하다.

CSS-in-JS 방식인 styled-components의 v.6 이상은 아래와 같은 방식으로 사용하라고 나와있다.


  1. styled-components API를 사용하여 전역 레지스트리 구성요소를 만든 뒤, useServerInsertedHTML hook을 사용하여 레지스트리에 수집된 스타일은 레이아웃의 HTML 태그에 삽입해준다.
// utils/registry.tsx

'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>
  )
}

  1. 위에서 만든 스타일 레지스트리 구성요소를 루트 레이아웃에 감싸주기
// app/layout.tsx

import StyledComponentsRegistry from './utils/registry'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}

그러면 완성~!~!


오늘도 파란만장하게 다양한 에러들을 마주했지만 ㅎㅎ,, 다행히도 잘 해결할 수 있었다 ㅎㅎ

0개의 댓글