카테고리 없음

styled component & next.js14

meLR 2024. 2. 3. 20:13

 

styled component(SC)를 next.js에서 사용 하기위해 노력을 했다. 정확하게 말하면 next의 장점을 최대한 가져가면서 SC를 어떻게 사용할까…

 

우선은 공식 문서 부터 살펴보자

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

https://styled-components.com/docs/advanced#app-directory

 

next.js 처음 부분을 보면

"경고: 런타임 JavaScript를 필요로 하는 CSS-in-JS 라이브러리는 현재 서버 컴포넌트(Server Components)에서 지원되지 않습니다.

 

서버 컴포넌트에서 지원이 안된다라…

서버 컴포넌트를 스타일링하려면 CSS Modules 또는 CSS 파일을 출력하는 PostCSS 또는 Tailwind CSS와 같은 다른 솔루션을 사용하는 것을 권장합니다.

 

Css in Js를 권장하지 않는다라…

 

기본적으로 next는 css in js를 싫어한다는 것을 알수있다.

 

그래도 쓸려면 client component에서 사용해야하고 이는 그냥 사용해도 가능하지만 hydration 때문에 잠깐의 깜빡임이 생긴다. 이를 FOUC라고 한다.

https://github.com/styled-components/styled-components/issues/3856

그 문제를 해결하기위해 공식 문서에서는 registry 파일을 만들고 이를 root layout에 감싸줌으로써 해결한다.

 

이렇게 감싸주게 되면 서버측에서 SC를 확인하고 모은뒤 html에 주입하는 것을 확인할수있다.

//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 (
    
      {children}
    
  )
}

 

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

이 부분을 확인해보면 클라이언트일때는 그냥 children을 내보내고 클라이언트가 아닌 서버일때는 감싸준다. 이를 통해 한번더 서버측에서 SC를 확인하고 모은뒤 html에 주입하고 클라이언트 측에서는 그냥 아무런 가공없이 진행하는걸 알수있다.

 

이렇게 되면 스타일을 포함한 html이 서버에서 랜더링 되어서 화면에 보여지고 그외 SC는 hydration 되면서 그위에 한번더 덮어 씌워지는 느낌인거같다.

 


 

그리고 마지막 삽질은 styled component를 사용하면 무조건 “use client”를 사용해야한다.위 과정을 했다고 해서 “use client”를 안쓰는건 아니다. 여기서도 지원안한다고 딴거 쓰자는 토론의 장이 지속되는 중이다.

https://github.com/styled-components/styled-components/issues/4025

 


정리

styled component를 (SSR)서버사이드랜더링을 지원하게 만들수는 있지만 sever component에서는 쓸수없다. 즉 쓸려면 “use client”를 사용해야한다.

 

styled component를 사용하는데 hydration이 필요없는 서버 컴포넌트라면 next.js의 장점을 못살리는 문제를 일으킨다.

-> 다른 모던 CSS를 함께 사용하자...

 

잘못된 내용이 있다면 지적 부탁드립니다!