Nextjs 14에서 CSS-in-JS 사용하기 최신 가이드

Nextjs 14에서 CSS-in-JS 사용하기 최신 가이드
Cozy CodingPosted On Jul 23, 20245 min read

CSS-in-JS

주의: Server Components에서는 런타임 JavaScript가 필요한 CSS-in-JS 라이브러리를 현재 지원하지 않습니다. 최신 React 기능인 Server Components 및 Streaming과 함께 CSS-in-JS를 사용하려면 라이브러리 저자가 React의 최신 버전을 지원해야 합니다. 동시 렌더링을 포함한 React의 최신 버전을 지원하는 최신 API를 처리하기 위해 React 팀과 협업 중입니다.

다음 라이브러리는 앱 디렉토리의 Client Components에서 지원됩니다 (알파벳 순서):

  • chakra-ui
  • kuma-ui
  • @mui/material
  • @mui/joy
  • pandacss
  • styled-jsx
  • styled-components
  • stylex
  • tamagui
  • tss-react
  • vanilla-extract

다음은 현재 지원 작업 중인 내용입니다:

  • 감정

알아두면 좋은 사실: 우리는 서로 다른 CSS-in-JS 라이브러리를 테스트하고 React 18 기능이나 앱 디렉토리를 지원하는 라이브러리에 대한 더 많은 예제를 추가할 예정입니다.

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

앱에서 CSS-in-JS 구성

CSS-in-JS를 구성하는 것은 세 가지 단계의 선택 프로세스입니다:

  • 렌더링 중에 모든 CSS 규칙을 수집하는 스타일 레지스트리.
  • 사용하려는 컨텐츠 앞에 규칙을 삽입하는 새로운 useServerInsertedHTML 훅.
  • 서버 사이드 렌더링 초기에 앱을 스타일 레지스트리로 감싸는 클라이언트 컴포넌트.

styled-jsx

클라이언트 컴포넌트에서 styled-jsx를 사용하려면 v5.1.0을 사용해야 합니다. 먼저 새 레지스트리를 생성하세요:

"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 }) {
  // 처음에만 스타일시트를 만들고 나중에 사용합니다
  // 참조: 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>;
}

그런 다음, 루트 레이아웃을 레지스트리로 감싸세요:

import StyledJsxRegistry from "./registry";

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

아래는 styled-components@6 이상을 구성하는 방법의 예시입니다:

먼저 next.config.js에서 styled-components를 활성화하세요.

module.exports = {
  compiler: {
    styledComponents: true,
  },
};

그런 다음, styled-components API를 사용하여 렌더 중에 생성된 모든 CSS 스타일 규칙을 수집하는 전역 레지스트리 컴포넌트를 만들고 해당 규칙을 반환하는 함수를 만드세요. 그런 다음 useServerInsertedHTML 훅을 사용하여 레지스트리에 수집된 스타일을 root layout의 head HTML 태그에 삽입하세요.

"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 }) {
  // 초기 상태를 lazy하게 선언하여 스타일시트를 한 번만 생성합니다.
  // 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>;
}

root layout의 children을 스타일 레지스트리 컴포넌트로 감싸세요:

import StyledComponentsRegistry from "./lib/registry";

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

여기에서 예시를 확인할 수 있어요.

알아 두면 좋은 점: 서버 렌더링 중에 스타일은 전역 레지스트리에 추출되어 HTML의 head에 플러시됩니다. 이렇게 함으로써 스타일 규칙이 사용될 수 있는 모든 내용보다 먼저 배치됩니다. 나중에 React의 다가올 기능을 사용하여 스타일을 삽입하는 위치를 결정할 수도 있습니다. 스트리밍 중에 각 청크에서 스타일이 수집되고 기존 스타일에 추가됩니다. 클라이언트 측 수화 작업이 완료된 후, styled-components가 일반적으로 작동하여 추가 동적 스타일을 삽입합니다. 우리는 스타일 레지스트리를 위한 클라이언트 컴포넌트를 트리의 맨 위에서 구체적으로 사용합니다. 이렇게 CSS 규칙을 추출하는 것이 더 효율적이기 때문입니다. 이렇게 함으로써 연속적인 서버 렌더링 시에 스타일을 다시 생성하는 것을 피하고, 서버 컴포넌트 페이로드에 보내지는 것을 막습니다. styled-components 컴파일의 개별 속성을 구성해야 하는 고급 사용 사례에 대해서는 Next.js styled-components API 참조를 읽어보시는 것이 좋습니다.