Zero Run Time CSS 도구들은 왜 컴포넌트 선언 형식이 아닐까?

CSR(Client-Side Rendering) 환경에서 Styled Components와 같은 컴포넌트 선언 형식의 스타일링 도구에 익숙했던 저는, SSR(Server-Side Rendering) 환경으로 넘어오면서 새로운 도전에 직면했습니다.

가장 까다로웠던 점 중 하나는 스타일링 컨벤션의 변화였습니다. CSR에서는 런타임에서 스타일을 동적으로 처리하는 도구가 자연스러웠지만, SSR에서는 초기 렌더링 성능과 스타일의 안정성이 더 중요한 요소로 떠올랐습니다.

이 과정에서 정적 스타일링 도구가 SSR 환경에 더 적합하다는 것을 알게 되었고, 동시에 컴포넌트 선언 방식을 지원하는 도구를 찾기 위해 고민했습니다. 그러던 중 컴포넌트 선언 방식과 정적 스타일링의 장점을 동시에 제공하는 Stitches 란 도구를 찾게 되었지만, 안타깝게도 개발이 중단된 상태라 선택지에서 제외할 수밖에 없었습니다.

이 경험을 통해 문득 이런 궁금증이 생겼습니다.

"정적 스타일 도구들은 왜 컴포넌트 선언 형식을 따르지 않을까?"

컴포넌트 선언 형식의 스타일링 도구와 정적 스타일 도구의 철학

프론트엔드 개발 환경에서 스타일링 도구는 꾸준히 발전해왔습니다. 특히 emotion, styled-components 같은 도구들은 컴포넌트 기반 개발 패턴에 적합하도록 설계되었습니다.

그러나 최근 SSR이 주목받으며 Vanilla Extract, Tailwind CSS와 같은 도구들은 Zero Run Time(런타임 최소화) 철학을 중심으로 설계되어 컴포넌트 선언 형식 대신 정적 스타일 관리 방식을 채택하고 있습니다.

컴포넌트 선언 방식은 스타일과 구조를 하나의 컴포넌트로 결합하여 유지보수성을 높이는 데 도움을 줍니다. 반면, 정적 스타일 도구는 글로벌 스코프에서 스타일을 관리하며 스타일 중복 제거와 최적화에 유리합니다.

이 글에서는 각 방식의 내부 동작 방식을 분석하고, Zero Run Time CSS 도구들이 컴포넌트 선언 방식을 채택하지 않는 이유를 탐구해보겠습니다.


컴포넌트 선언 방식의 동적 스타일링 도구(Emotion, Styled-Components)

1. 내부 동작 방식

emotionstyled-components는 동적 스타일링 도구로서, CSS-in-JS 패턴을 기반으로 작동합니다. 동작 흐름은 다음과 같습니다:

  1. 함수 호출
    • styled 또는 css 함수가 호출되면, 런타임에서 스타일 규칙이 문자열 형태로 생성됩니다.
    • 예: styled.div가 호출될 때, css 규칙이 생성됨.
  2. 스타일 문자열 생성 및 해싱
    • 각 스타일 규칙에 대해 고유한 해시를 생성합니다. 이는 클래스명이 중복되지 않도록 보장합니다.
    • 예: color: red;.css-123abc { color: red; }
  3. 스타일 삽입
    • 생성된 스타일은 <style> 태그를 통해 DOM에 삽입됩니다.
    • 이 과정은 컴포넌트가 렌더링될 때 동적으로 발생하므로 런타임 비용이 발생합니다.

2. 장점과 한계

  • 장점
    • 컴포넌트 단위로 스타일을 관리하여 높은 모듈성과 재사용성을 제공합니다.
    • 동적으로 props를 기반으로 스타일을 변경할 수 있습니다.
  • 한계
    • 런타임에서 스타일을 생성하고 삽입하므로 성능 부하가 발생할 수 있습니다.
    • SSR 환경에서 초기 렌더링 시 스타일이 제대로 적용되지 않거나, Flicker 현상이 발생할 위험이 있습니다.

정적 스타일링 도구(Vanilla Extract, Tailwind CSS)

1. 내부 동작 방식

정적 스타일링 도구는 빌드 타임에 스타일을 미리 생성하여 런타임 비용을 줄이는 데 초점을 맞춥니다.

  1. CSS 규칙의 미리 컴파일
    • Vanilla Extract는 CSS-in-TypeScript 방식을 활용하여, TypeScript에서 작성된 스타일 규칙을 정적 CSS 파일로 컴파일합니다.
    • 예: style({ color: 'red' }).css-abc123 { color: red; }
  2. 전역 클래스 관리
    • CSS 클래스명은 고유한 네이밍 규칙에 따라 미리 생성되며, 글로벌 스코프에서 관리됩니다.
  3. Zero Run Time
    • 스타일이 미리 생성되므로 런타임에서는 추가적인 CSS 생성 및 DOM 삽입 작업이 없습니다.
    • 예: Tailwind CSS는 빌드 시 필요한 유틸리티 클래스만 포함된 CSS 파일을 생성합니다.

2. 장점과 한계

  • 장점
    • 런타임 비용이 거의 없어 성능 최적화에 유리합니다.
    • SSR 환경에서도 Flicker 현상이 발생하지 않습니다.
  • 한계
    • 컴포넌트 단위의 스타일 정의가 어렵고, 글로벌 스코프에서 스타일을 관리해야 합니다.
    • 동적 스타일링이 어렵기 때문에 특정 유스케이스에서 불편할 수 있습니다.

결론. Zero Run Time CSS 도구들은 왜 컴포넌트 선언 형식이 아닐까?

Zero Run Time CSS 도구들은 성능 최적화와 빌드 타임 스타일 생성에 초점을 맞춥니다. 이러한 철학은 컴포넌트 단위로 스타일과 구조를 결합하는 방식과 근본적으로 상충됩니다. 글로벌 스코프에서 스타일을 관리함으로써 중복 제거와 최적화를 극대화하고, 런타임 비용을 제거하는 방향으로 설계된 것입니다.

반면, 컴포넌트 선언 방식의 도구들은 동적 스타일링과 컴포넌트화의 이점을 제공하며, 런타임 비용을 감수하더라도 개발자 경험을 중시합니다. 따라서, 두 방식은 각각의 철학과 장단점에 따라 선택됩니다. Zero Run Time CSS 도구들이 컴포넌트 선언 방식을 채택하지 않는 것은, 런타임 비용 최소화라는 핵심 목표를 유지하기 위한 자연스러운 결과입니다.

"최적의 도구 선택은 프로젝트의 요구사항과 환경에 따라 달라진다."

이를 기억하며, 각 스타일링 도구의 철학과 동작 방식을 이해하고 적합한 도구를 선택하는 것이 중요합니다.