pandacss는 styled-system 이라는 조금 특이한 폴더가 있다
panda는 빌드 타임에 css 파일을 생성하는데, 원칙적으로 스타일을 적용하기 위해서는 css variables를 써야 할 것이다
하지만 불편한 css variables를 쌩으로 쓰긴 어려운 점이 많다(그리고 css variables로 쓸거였으면 라이브러리를 쓸 이유가 없다)
그래서 pandacss는 마치 emotion처럼 className으로 변환해주는 css-in-js syntax를 제공해준다
import { css } from 'styled-system/css';
<div
className={css({
display: 'flex',
flexDirection: 'column',
fontWeight: 'semibold',
color: 'yellow.300',
textAlign: 'center',
textStyle: '4xl',
})}
>
//이렇게 변환됨
<div class="d_flex flex-d_column fw_semibold c_yellow.300 ta_center textStyle_4xl"/>
css 함수는, emotion에서도 사용하는 함수이다
하지만 둘의 차이는
emotion은 런타임 환경에서 스타일을 생성하는 함수
panda는 CSS-in-JS 문법(객체 또는 템플릿 리터럴)을 클래스 이름 문자열로 변환하기 위한 가벼운 런타임 함수
또한 파일의 위치도 다른데
emotion의 css는 @emotion 패키지 안에 위치하지만,
panda의 css는 유저의 로컬 폴더에 위치한다
pandacss가 빌드 타임에 스캐닝 및 파싱 과정을 마치면 root 위치에 styled-system이라는 폴더가 생성되는데, 해당 폴더에는 css 처럼 스타일을 적용하기 쉽게 해주는 함수와 타입들이 존재한다

결론
pandacss는 빌드 타임에 스타일을 생성하고, 런타임 환경에서는 styled-system의 함수들을 통해 스타일을 좀더 쉽고, type-safe하게 적용할 수 있게 도와준다
그래서 pandacss는 일반적인 component library(emotion 같은 라이브러리를 사용하는 패키지들) 빌드 방식이랑은 조금 다르다.
공식 문서에서는 4가지 방법을 알려주는데, 여기에서 npm 배포를 고려하지 않은(모노레포에서만 사용 가능) 방법을 제외하면 2가지 방법이 있다
가장 먼저 시도해봤던 방법이고, 현재는 포기한 방법이다
장점
사실 pandacss가 물론 나온지 얼마 안된 신생 라이브러리임을 감안해도,생각보다 인기가 많이 없는 것 같다(css-in-js에서 갈아탈거면 tailwind로 가던가, 아니면 그냥 css module,scss로 가는 것 같다)
인기가 없다는 건, 그만큼 레퍼런스도 없다는 소리이기 때문에 유저가 아예 사용하는지 조차 모르는 것도 좋지 않을까 하는 생각이 들었다
단점
1.5 그러면 styled-system 폴더를 빌드하지 말고 external로 설정하면?(실패)
styled-system을 자체적으로 빌드하지 않고, 원래 사용했던 상태 그대로 유지하여, 사용자의 로컬 환경에 있는 styled-system 폴더를 참조하도록 설정하면, 기존 스타일 + customize도 가능하지 않을까? 해서 도전해봤지만..
도저히 node_modules/** 에 위치한 파일들이 local의 파일을 참조하게 하는 방법을 잘 모르겠다(사실 있는지도 잘 모르겠다)
// node_modules/**/* 에 있는 파일
external 처리하지 않았을 경우
import { css } from ".././styled-system" - styled-system이 같이 빌드 됨
external에 포함했을 경우
import { css } from 'styled-system' - 컴포넌트의 import경로 그대로
이 부분에서 정말 레퍼런스가 부족하다는 걸 뼈저리게 느꼈다
tailwind의 preset과 마찬가지로, pandacss도 preset이라는 개념이 존재한다
쉽게 말하면 스타일 모음집인데, 유저가 내가 만든 preset을 install해서 config에 등록하기만 하면 내가 생성했던 스타일들을 그대로 재사용할 수 있다.
import { definePreset } from '@pandacss/dev'
export default definePreset({
name: 'my-preset',
theme: {
tokens: {
colors: {
rose: {
50: { value: '#fff1f2' },
// ...
800: { value: '#9f2233' }
}
}
}
}
})
import 내 프리셋 from '@pandacss/preset-panda'
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
presets: [pandaPreset, 내 프리셋]
})
일단 presets이 배열이기 때문에 또다른 프리셋을 추가할 수도 있고, 직접 다른 theme들을 추가하거나, 기존에 있는 스타일을 확장할 수 있기 때문에 스타일 관련 커스텀 자유도가 매우 높아진다
그리고 빌드도 매우 쉽다..
단점은 유저가 pandacss의 기본 개념을 이해하고 있어야 한다는 것이다.
Panda CSS를 사용할 때 가장 어려웠던 점은 스타일이 빌드 타임에 생성된다는 개념이었다.
이론적으로는 이해했지만, 막상 "왜 스타일이 적용되지 않지?" 하고 찾아보면, 문제의 근본 원인은 빌드 타임에 스타일이 생성되기 때문이었다(애초에 어떠한 이유로 스타일이 생성되지 않았기 때문)
한마디로 생각보다 러닝커브가 존재한다는 생각이 들었고, styled-system 폴더 라는 개념도 조금 생소하지 않을까 라는 생각이 들었다
2.5 컴포넌트 copy/paste(개발 중)
이렇게 내가 만든 preset을 등록한 다음, 내가 만들어 놓은 컴포넌트 코드를 그대로(import문 포함) 본인 코드에 붙여넣기만 하면 굳이 패키지로 다운받지 않아도 사용할 수가 있다
이 분야 대표격인 라이브러리로 shadcn이 있는데,
홈페이지에 가면 본인들은 component library가 아니라고 한다
컴포넌트 로직은 radix UI를 사용하고, 스타일은 tailwind를 사용해서 -> 본인들은 이걸 copy/paste 해서 사용할 수 있는 cli만 제공하는 것이다(본인들이 개발한 건 cli 뿐)
장점
이제는 스타일 뿐만 아니라 컴포넌트 로직까지 유저가 customize할 수 있게 된다
번거로운 패키지 관리 및 업데이트에서 벗어날 수 있다
단점
버전 관리를 할 수 없다
예를 들어 내가 제공한 컴포넌트에 버그가 생겨 코드를 수정했다면,
일반적인 npm 패키지일 경우 버전 업그레이드를 하면 되지만, 현재 방식에서는 유저가 직접 문서에 접속해서 알아차리는 방법밖에는 없다
유저가 컴포넌트를 사용하기 위해서는 나와 세팅을 동일하게 해줘야 한다
나의 경우 styled-system을 tsconfig path를 통해 경로 별칭을 사용하고 있는데, 이 컴포넌트를 복사해가는 경우에도 나의 경로 별칭과 동일하게 적용해줘야 한다(shadcn도 똑같다)
또한 panda의 경우 이 styled-system의 위치나 네이밍을 변경할 수 있는데 이 부분에도 제약이 생긴다
그래서 shadcn에서는 다양한 cli로 이 문제를 해결하고자 하는 것 같다
shadcn에서 제공하는 cli로는 init(초기 세팅 도움),add(컴포넌트 copy),diff(experimental 기능)이 있다
react 19버전부터는 <style> 이라는 태그가 생긴다고 한다
The built-in browser
<style>component lets you add inline CSS stylesheets to your document.

저 두번째 분이 chakra UI 개발자인데, 이번에 3버전에서 emotion을 제거하지 않은 이유로 style tag 를 꼽았다.
대부분의 css-in-js 라이브러리들이 꽤 좋은 성능상 이점이 생겨서, 이 부분은 걱정할 내용이 아니라고 한다
만약에 성능상 문제때문에 panda 같은 atomic으로 갈아탈 생각이라면, 조금 기다려봐도 되지 않을까 싶다