우선은 css 라이브러리를 선택해야하는데 나중에 서버사이드 렌더링을 위한 프로젝트가 있을 때, 문제가 생길지도 몰라서 CSS-in-JS 는 피하고싶다.
그러면 선택지는 매우 줄어드는데 사실 가장 유명한건 tailwindCSS이다.
하지만 tailwindCSS도 방식이 마음에 들지 않는다... className에 css를 작성하는것, 쓰다보면 익숙해지겠지만 기존의 css가 아닌 새로운 키워드들을 학습해야한다.
대안으로 Css Modules, Sass 등이 있다.
CSS Modules vs Sass
- CSS Modules:
- 장점:
- 지역 범위 스타일링: 클래스 이름 충돌 방지
- 기존 CSS 문법 사용: 학습 곡선 낮음
- 컴포넌트 기반 개발에 적합
- 빌드 시 최적화: 사용하지 않는 스타일 제거 가능
- 단점:
- 동적 스타일링에 제한적
- 글로벌 스타일 관리가 복잡할 수 있음
- 테마 시스템 구현이 어려울 수 있음
- 사용 예:
.button {
background-color: blue;
color: white;
}
- Sass:
- 장점:
- 변수, 중첩, 믹스인 등 강력한 기능
- 대규모 프로젝트에 적합
- 광범위한 커뮤니티와 생태계
- 기존 CSS 지식 활용 가능
- 단점:
- 전처리기 필요: 빌드 과정 추가
- 과도한 사용 시 복잡해질 수 있음
- 컴포넌트 단위 스코핑이 기본적으로 제공되지 않음
- 사용 예:
$primary-color: blue;
.button {
background-color: $primary-color;
color: white;
}
일단 CSS Modules는 동적 스타일링에 제한적이고 테마 시스템 구현에 어려움이 있다는는 점에서 맘에 들지 않고,
Sass는 빌드 과정이 필요하고 컴포넌트 단위 스코핑이 기본적으로 제공되지 않는다는 점에서 맘에 들지 않는다.
그러면 무엇을 써야할까?
우선 styled-components나 emotion과 같은 CSS-in-JS 라이브러리를 피하려는 이유는 서버사이드 렌더링을 위해 라이브러리가 번들링되는 과정에서 문제가 생길 수 있기 때문이다.
그 대안을 더 찾아봤을 때, vanilla-extract, styleX 등의 라이브러리가 있었다.
styled-components, emotion vs vanilla-extract, styleX
- 런타임 성능:
- vanilla-extract/StyleX: 제로 런타임, 빌드 시 정적 CSS 생성
- styled-components/emotion: 런타임에 스타일 생성, 일부 성능 오버헤드 발생
- SSR 호환성:
- vanilla-extract/StyleX: 기본적으로 SSR과 완벽 호환
- styled-components/emotion: SSR 지원하나 추가 설정 필요
- 타입 안정성:
- vanilla-extract: TypeScript 기반, 강력한 타입 체크
- StyleX: TypeScript 지원, 타입 안정성 제공
- styled-components/emotion: TypeScript 지원하나 덜 강력함
- 학습 곡선:
- vanilla-extract: CSS 객체 문법, 비교적 익숙함
- StyleX: 새로운 문법, 학습 필요
- styled-components/emotion: 템플릿 리터럴 문법, 익숙한 CSS 작성 방식
- 동적 스타일링:
- vanilla-extract: 별도 런타임 API 필요
- StyleX: 조건부 스타일링 지원
- styled-components/emotion: 동적 스타일링 강점
- 커뮤니티/생태계:
- vanilla-extract: 성장 중인 커뮤니티
- StyleX: 비교적 새로움, 작은 커뮤니티
- styled-components/emotion: 큰 커뮤니티, 풍부한 생태계
- 테마 시스템:
- vanilla-extract: 강력한 내장 테마 시스템
- StyleX: 글로벌 테마 및 디자인 토큰 지원
- styled-components/emotion: ThemeProvider를 통한 테마 지원
- 개발 도구 지원:
- vanilla-extract/StyleX: 정적 분석 가능, 좋은 IDE 지원
- styled-components/emotion: 브라우저 개발 도구 지원, 일부 IDE 플러그인
- 빌드 프로세스:
- vanilla-extract/StyleX: 빌드 시 CSS 생성, 추가 빌드 단계 필요
- styled-components/emotion: 일반적인 JS 빌드 프로세스
- 성숙도:
- vanilla-extract/StyleX: 비교적 새로운 기술
- styled-components/emotion: 성숙하고 안정적인 기술
결론은 vanilla-extract가 가장 좋은 선택이라고 생각이 들었다.
vanilla-extract 설정
- 프로젝트에 vanilla-extract 설치
pnpm @packages/ui add -D vanilla-extract
pnpm @packages/ui add -D @vanilla-extract/rollup-plugin
rollup.config.js 파일에 플러그인 추가
...
import { vanillaExtractPlugin } from "@vanilla-extract/rollup-plugin";
...
export default defineConfig({
plugins: [
...
vanillaExtractPlugin()
...
],
});
스토리북 설정
이전 포스팅에서 현재 packages/ui는 라이브러리를 만들기위해 Rollup으로 구성했었다. 하지만 스토리북을 구성하던중 storybook을 실행하려면 webpack5나 vite를 사용해야한다.
왜냐면 storybook 7에서는 렌더러(예: React, Vue), 빌더(예: Webpack, Vite) 및 기본 설정을 추상화하여 통합을 더 쉽게 만들어주는 프레임워크 개념이 도입되었기 때문이다.
그래서 스토리북을 함께 사용하기 위해서는 번들러를 변경하던지, vite와 rollup을 함께 사용해야한다.
나는 packages/ui를 라이브러리 목적으로 만들것이기 때문에, 별도의 프로젝트를 만들어서 스토리북을 구성해야할 것 같다.
(모노레포... 할게 많네 ...)
우선 스토리북 설정은 조금 뒤로 미루고, 먼저 디자인 시스템 라이브러리를 구성해보자.