ReactNextCentral

CSS-in-JS

Published on
Next.js에서 CSS-in-JS 라이브러리 사용하기
Table of Contents
경고

런타임 JavaScript가 필요한 CSS-in-JS 라이브러리는 현재 서버 컴포넌트에서 지원되지 않습니다. 서버 컴포넌트 및 스트리밍과 같은 새로운 리액트 기능과 함께 CSS-in-JS를 사용하려면 라이브러리 제작자가 동시성 렌더링을 포함하여 리액트의 최신 버전을 지원해야 합니다.

Next.js는 현재 리액트 서버 컴포넌트 및 스트리밍 아키텍처를 지원하는 CSS와 자바스크립트를 처리하기 위한 상위 API에 대한 리액트 팀과 함께 작업하고 있습니다.

다음 라이브러리는 app 디렉토리 내의 클라이언트 컴포넌트에서 지원됩니다.

다음은 현재 지원 작업 중입니다.

다양한 CSS-in-JS 라이브러리를 테스트 중이며 리액트 18 기능 및/또는 app 디렉토리를 지원하는 라이브러리에 대한 예제를 더 추가할 예정입니다.

서버 컴포넌트를 스타일링하려면 CSS 모듈 또는 PostCSS나 Tailwind CSS와 같은 CSS 파일을 출력하는 다른 솔루션을 사용하는 것이 좋습니다.

app에서 CSS-in-JS 구성하기

CSS-in-JS를 구성하는 것은 세 단계의 선택 과정을 포함합니다.

  1. 렌더링 중 모든 CSS 규칙을 수집하는 스타일 레지스트리
  2. 해당 규칙을 사용할 수 있는 콘텐츠 이전에 규칙을 주입하는 새로운 useServerInsertedHTML
  3. 초기 서버 측 렌더링 중 앱을 스타일 레지스트리로 감싸는 클라이언트 컴포넌트

styled-jsx

클라이언트 컴포넌트에서 styled-jsx를 사용하려면 v5.1.0이 필요합니다. 먼저 새로운 레지스트리를 만듭니다:

app/registry.tsx
'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'

export default function StyledJsxRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // 스타일시트는 지연 초기 상태로 한 번만 생성
  // x-ref: https://reactjs.org/docs/\
  // hooks-reference.html#lazy-initial-state
  const [jsxStyleRegistry] = 
    useState(() => createStyleRegistry())

  useServerInsertedHTML(() => {
    const styles = jsxStyleRegistry.styles()
    jsxStyleRegistry.flush()
    return <>{styles}</>
  })

  return <StyleRegistry registry={jsxStyleRegistry}>
    {children}
  </StyleRegistry>
}
JavaScript
app/registry.js
'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'

export default function StyledJsxRegistry({ children }) {
  // 스타일시트는 지연 초기 상태로 한 번만 생성
  // x-ref: https://reactjs.org/docs/\
  // hooks-reference.html#lazy-initial-state
  const [jsxStyleRegistry] 
    = useState(() => createStyleRegistry())

  useServerInsertedHTML(() => {
    const styles = jsxStyleRegistry.styles()
    jsxStyleRegistry.flush()
    return <>{styles}</>
  })

  return <StyleRegistry registry={jsxStyleRegistry}>
    {children}
  </StyleRegistry>
}

그런 다음 레지스트리로 루트 레이아웃을 감싸십시오.

app/layout.tsx
import StyledJsxRegistry from './registry'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledJsxRegistry>{children}</StyledJsxRegistry>
      </body>
    </html>
  )
}
JavaScript
app/layout.js
import StyledJsxRegistry from './registry'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <StyledJsxRegistry>{children}</StyledJsxRegistry>
      </body>
    </html>
  )
}

여기에서 예제를 확인하세요.

Styled Components

다음은 styled-components@6 또는 그 이후 버전을 설정하는 방법의 예입니다.

먼저 styled-components API를 사용하여 렌더링 중 생성된 모든 CSS 스타일 규칙을 수집하는 전역 레지스트리 컴포넌트와 해당 규칙을 반환하는 함수를 생성합니다. 그런 다음 useServerInsertedHTML 훅을 사용하여 레지스트리에 수집된 스타일을 루트 레이아웃의 <head> HTML 태그에 주입합니다.

lib/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
}) {
  // 스타일시트는 지연 초기 상태로 한 번만 생성
  // 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>
  )
}

루트 레이아웃의 children을 스타일 레지스트리 컴포넌트로 감싸세요.

app/layout.tsx
import StyledComponentsRegistry from './lib/registry'

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

여기에서 예제를 확인하세요.

  • 서버 렌더링 중에 스타일은 전역 레지스트리로 추출되어 HTML의 <head>에 삽입됩니다. 이렇게 하면 스타일 규칙이 해당 규칙을 사용할 수 있는 내용보다 앞에 배치됩니다. 앞으로는 리액트의 새로운 기능을 사용하여 스타일을 주입할 위치를 결정할 수 있습니다.
  • 스트리밍 중 각 청크의 스타일은 수집되어 기존 스타일에 추가됩니다. 클라이언트 측 수화가 완료되면 styled-components는 평상시대로 이를 수행하고 추가 동적 스타일을 주입합니다.
  • 스타일 레지스트리의 경우 트리의 최상위에서 클라이언트 컴포넌트를 특별히 사용하는 이유는 이 방법으로 CSS 규칙을 추출하는 것이 더 효율적이기 때문입니다. 이렇게 하면 후속 서버 렌더링에서 스타일을 다시 생성하는 것을 방지하고 서버 컴포넌트 페이로드에 포함되지 않게 합니다.