Vanilla-extract css 파헤쳐보기

원동휘·2024년 5월 8일

Front-end

목록 보기
1/2

서문

안녕하세요.

Next.js의 앱 라우터를 사용하면서 서버컴포넌트내에서 기존에 사용하던 Emotion을 사용하지못했고, 서버컴포넌트에서 사용할 수 있는 CSS 라이브러리를 사용할지 탐색하는 동안 저는 흥미로운 솔루션인 Vanilla-Extract CSS를 발견했습니다.

그렇게 vanilla-extract에 흥미를 가지게됐고 vanilla-extract에 대해서 정리해보고자 합니다.

vanilla-extract css란?

공식문서에서 핵심을 요약해서 설명하고있습니다.

Zero-runtime Stylesheets in TypeScript.
제로 런타임과 TS

Vanilla-Extract CSS는 TS 또는 JS 파일 내에서 CSS를 작성한 다음 빌드 시 순수 CSS로 컴파일할 수 있는 CSS-in-JS 라이브러리입니다.
이 방법은 TS의 강력한 기능을 활용하여 런타임 오버헤드 없이 유형이 안전하고 범위가 지정된 스타일을 제공합니다.

주요 기능은

  • 향상된 정적 유형 검사를 위한 긴밀한 TS 통합,
  • 성능 향상으로 이어지는 제로 런타임,
  • 충돌을 방지하기 위한 자동 범위 지정 스타일,
  • CSS 변수를 활용하는 동적 테마 시스템이 포함됩니다.

runtime css vs Zero-runtime css?

vanilla-extract의 핵심에 Zero-runtime css가 나오는데요.

runtime css가 무엇이고, Zero-runtime css가 무엇인지 짚고넘어가볼까요?

runtime css

runtime css의 대표적인 예시로 Styled-Components 또는 Emotion과 같은 기존 CSS-in-JS 솔루션이있습니다.

런타임에서 동작하기때문에 동적인 스타일링 환경을 제공하는 장점도 있지만 치명적인 단점이 있는데요

  • 스타일을 적용하는 데 필요한 JavaScript를 구문 분석하고 실행해야 하므로 런타임에 스타일을 삽입하면 페이지 로드 시간이 느려집니다.

  • 스타일을 동적으로 처리하기 위해 스타일 정의와 JavaScript 로직을 모두 포함해야 하기 때문에 번들 크기가 주로 증가합니다.

  • JavaScript 내에서 인라인으로 작성되고 런타임에 삽입된 스타일은 JavaScript 번들 크기를 크게 늘릴 수 있습니다. 이러한 증가는 다운로드 시간에 영향을 미치고 실행 속도를 느리게 하며 일반적으로 전반적인 성능을 저하시킵니다.

과거에는 성능상의 이유로 emotion에서 css modules로 전환한 경험도 있습니다.vanila-extract에 대한 글이므로 부연설명없이 넘어가도록 하겠습니다.

Zero-runtime css

Zero-runtime css의 대표적인 예시로 Vanilla Extract, Sttiches가 있습니다.

장점으로는

  • 빌드 타임 컴파일됨으로써 스타일은 JS 또는 TS를 사용하여 작성되지만 런타임이 아닌 "빌드 프로세스 중에" 정적 CSS 파일로 컴파일됩니다. 즉, 페이지가 로드되는 즉시 CSS를 제공할 수 있으므로 스타일을 적용하기 위해 JavaScript를 실행할 필요가 없습니다.

  • 스타일이 미리 CSS 파일로 컴파일되므로 런타임 시 스타일을 삽입하거나 관리하는 데 필요한 JS 코드가 없으므로 번들 크기가 크게 줄어들어 다운로드 시간이 향상되고 브라우저의 처리 부하가 줄어듭니다.

  • 성능 개선의 효과로 JS를 통해 스타일을 구문 분석하고 적용할 필요 없이 웹 페이지를 더 빠르고 효율적으로 렌더링할 수 있습니다. 이를 통해 동적 스타일의 일반적인 문제인 리플로우 및 다시 그리기가 줄어들어 전반적인 성능과 사용자 경험이 향상됩니다.

단점으로는
빌드 타임에 컴파일됨으로써 동적 스타일 지정에 대한 유연성이 부족하다는 단점이 있습니다.

이렇게 runtime css가 무엇이고, Zero-runtime css에 대해서 알아보았습니다.

vanilla-extract 설정

문법과, 사용법은 공식문서나 여타 다른문서에 너무 좋은내용이 많으니 next.js 14버전에서 vanilla-extract 설정하는법만 공유드리겠습니다.

$npm install @vanilla-extract/css
const {
  createVanillaExtractPlugin
} = require('@vanilla-extract/next-plugin');
const withVanillaExtract = createVanillaExtractPlugin();

/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/upload/:slug',
        destination: `${process.env.NEXT_PUBLIC_BASE_URL}/:slug`, // Matched parameters can be used in the destination
      },
    ]
  },
}

module.exports = withVanillaExtract(nextConfig);

vanilla-extract 장/단점

장점

  • 오류를 잡아주고, 자동완성이 잘됨으로써 TS의 장점을 그대로 활용 가능
  • CSS를 그대로쓰면서 그룹화로 가독성증가
  • TS와 완전히 통합되어 오류 검사 및 자동 완성 기능이 향상됩니다.
  • 빌드시 컴파일되므로 런타임 오버헤드가 없으므로 페이지 로드 시간이 빨라지고 JavaScript 번들 크기가 줄어듭니다.
  • Next.js의 서버컴포넌트 스타일 지원
  • Theme를 만드는 부분이 빌드타임/런타임을 유동적 선택
  • 디자인 시스템만들때 유용 > sprinkles
  • 로컬 범위 지정 스타일

단점

  • 스타일은 빌드시 컴파일되면 고정되므로 런타임 CSS-in-JS 라이브러리에 비해 동적 스타일링의 유연성이 떨어집니다.

다른 CSS 라이브러리와의 비교

vanilla-extract는 빌드 시 범위가 지정되고 유형이 안전한 스타일을 제공하여 런타임 오버헤드를 줄입니다. 향상된 코드 안정성을 위해 TypeScript와 긴밀하게 통합, 로컬 범위 지정 스타일이라는 장점이 있지만
실시간 동적 스타일링 기능이 부족하다는 단점이 있습니다.

vs Tailwind CSS

테일윈드와 비교해보면 CSS는 CSS 작성을 거의 하지 않고 신속한 UI 개발을 가능하게 하는 고도로 사용자 정의 가능한 장점이있는 유틸리티CSS 입니다. 하지만 단점으로는 많은 유틸리티 클래스를 외워야 하므로 부담스러울 수 있습니다. 본질적으로 범위가 지정되지 않아 주의 깊게 관리하지 않으면 스타일, 우선순위의 충돌이 발생할 수 있습니다.

vs StyledComponents

이렇게는 위에서 정리한 제로런타임과 런타임의 차이가 있겠네요!

vs CSS modules

기본적으로 로컬 범위의 CSS는 구성 요소 간에 스타일이 번지는(오염되는)것을 방지하는 데 도움이되는 유사점이 있고,

CSS modules의 단점으로는 기본 제공 테마 또는 동적 스타일 지정 기능을 제공하지 않고, TypeScript와의 긴밀한 통합이 부족합니다.

의견

Recipes -> sttiches에서 크게 영감을 받은 유형 안전 런타임 API로 다양한 스타일을 제작하세요.
Sprinkles -> Tailwind를 표방해 기본적으로 런타임이 없고 유형이 안전한 버전의 Tailwind, 스타일 시스템 등을 직접 구축하는 것과 같습니다.

공식문서에서 위와같이 설명하고 있고, 지속적인 발전을 이루며, 미래에 중요한 역할을 서버컴포넌트가 점점 많이 사용되면서 효율적이고 확장 가능한 스타일링 솔루션에 대한 필요성도 커지고 있습니다. Vanilla Extract의 컴파일 시간 접근 방식은 로드 시간에 스타일이 준비되고 최적화되도록 보장하여 특히 서버 렌더링 앱에서 성능을 향상시킬 수 있고, Updated도 며칠단위로 지속적인 업데이트가되고있습니다.

CSS in JS을 사용하실 예정이라면 Vanila Extract도 한번 고려해보시는게 어떨까요?

profile
front-end developer

1개의 댓글

comment-user-thumbnail
2024년 5월 22일

좋은 글이네요. 잘읽고갑니다.

답글 달기