Emotion CSS에서 Panda CSS로의 마이그레이션 가이드
Emotion CSS를 Panda CSS로 마이그레이션하는 방법과 코드 변환 가이드
1. 코드 변환 가이드
1.1 기본 스타일 변환
Emotion CSS:
const style = css`
color: red;
background: white;
`;Panda CSS:
import { css } from '@mildang/styled-system/css';
const style = css({
color: 'red',
background: 'white',
});1.2 중첩 선택자 변환
Emotion CSS:
const style = css`
& .child {
color: red;
}
&:hover {
background: blue;
}
`;Panda CSS:
import { css } from '@mildang/styled-system/css';
const style = css({
'& .child': {
color: 'red',
},
'&:hover': {
background: 'blue',
},
});1.3 외부 참조 중첩 선택자 변환
Emotion CSS:
import { menuClasses } from '@mildang/mui';
const menuStyle = emotionCSS`
& .${menuClasses.list} {
padding-top: 4px;
padding-bottom: 4px;
}
`;Panda CSS:
import { css } from '@mildang/styled-system/css';
const style = css({
'& .MuiMenu-list': {
paddingTop: '4px',
paddingBottom: '4px',
},
});1.4 조건부 스타일 변환 (CVA 사용)
Emotion CSS:
const style = ({ isActive }) => css`
color: red;
${isActive &&
css`
background: blue;
`}
`;Panda CSS (CVA 사용):
import { cva } from '@mildang/styled-system/css';
const style = cva({
base: {
color: 'red',
},
variants: {
isActive: {
true: {
background: 'blue',
},
},
},
});
// 사용 예시
const Component = ({ isActive }) => {
return <div className={style({ isActive })}>Content</div>;
};1.5 테마 사용 변환
Emotion CSS:
const style = ({ theme }) => css`
color: ${theme.palette.primary.main};
`;Panda CSS:
import { css } from '@mildang/styled-system/css';
const style = css({
color: 'primary.main', // Panda CSS의 토큰 시스템 사용
});2. 실제 예시 변환 (CVA 사용)
2.1 복잡한 컴포넌트 스타일 변환
Emotion CSS:
const editorViewerStyle = ({
theme,
editorCanvasOpen,
}: {
theme: Theme;
editorCanvasOpen: boolean;
}) => emotionCSS`
width: inherit;
height: 100%;
background-color: white;
& .excalidraw__canvas {
border-radius: 32px;
}
.excalidraw {
.dropdown-menu-button {
display: none;
}
.help-icon {
display: none;
}
.layer-ui__wrapper__footer {
bottom: ${GAP + BOTTOM_TOOLBAR_HEIGHT}px;
}
}
${
editorCanvasOpen &&
emotionCSS`
display: none;
`
}
`;Panda CSS (CVA 사용):
import { cva } from '@mildang/styled-system/css';
const editorViewerStyle = cva({
base: {
width: 'inherit',
height: '100%',
backgroundColor: 'white',
'& .excalidraw__canvas': {
borderRadius: '32px',
},
'& .excalidraw': {
'& .dropdown-menu-button': {
display: 'none',
},
'& .help-icon': {
display: 'none',
},
'& .layer-ui__wrapper__footer': {
bottom: `${GAP + BOTTOM_TOOLBAR_HEIGHT}px`,
},
},
},
variants: {
editorCanvasOpen: {
true: {
display: 'none',
},
false: {
display: 'block',
},
},
},
});
// 사용 예시
const EditorViewer = ({ editorCanvasOpen }: { editorCanvasOpen: boolean }) => {
return <div className={editorViewerStyle({ editorCanvasOpen })}>{/* 컴포넌트 내용 */}</div>;
};3. CVA 사용 시 고려사항
-
기본 스타일과 변형 분리
base속성에 공통 스타일 정의variants속성에 조건부 스타일 정의
-
타입 안정성
- CVA는 자동으로 타입을 생성하여 타입 안정성 제공
- 변형의 모든 가능한 조합에 대한 타입 체크 가능
-
복합 변형
- 여러 조건을 조합하여 사용 가능
- 각 변형의 조합에 따른 스타일 정의 가능
import { cva } from '@mildang/styled-system/css';
const style = cva({
base: {
// 기본 스타일
},
variants: {
size: {
sm: {
/* ... */
},
md: {
/* ... */
},
lg: {
/* ... */
},
},
variant: {
primary: {
/* ... */
},
secondary: {
/* ... */
},
},
},
compoundVariants: [
{
size: 'sm',
variant: 'primary',
css: {
// 특정 조합에 대한 스타일
},
},
],
});- 기본값 설정
defaultVariants를 사용하여 기본 변형값 설정 가능
import { cva } from '@mildang/styled-system/css';
const style = cva({
// ... base와 variants 정의
defaultVariants: {
size: 'md',
variant: 'primary',
},
});4. 마이그레이션 체크리스트
- 기존 Emotion CSS 코드 분석
- 토큰 시스템 정의
- 조건부 스타일을 CVA로 변환
- 컴포넌트 단위 마이그레이션
- 테스트 및 검증
- Emotion CSS 의존성 제거
5. 컬러 토큰 변환 가이드
emotion css의 컬러는 ${theme.palette.primary.main}과 같이 적용되어있는데, 이는 panda css에서는 common.7로 변환 되어야합니다.
왼쪽 컬러와 매칭되는 오른쪽 컬러 토큰으로 변경해주세요
stroke: common.4
divider: common.4
snackbar: common.12
activeRating: yellow-light-600
common.black: common.7
common.white: common.1
grey.50: common.2
grey.100: common.3
grey.200: common.4
grey.300: common.5
grey.400: common.6
grey.500: common.7
grey.600: common.10
grey.700: common.11
grey.800: common.11
grey.900: common.7
grey.A100: common.3
grey.A200: common.4
grey.A400: common.6
grey.A700: common.11
primary.dark: common.7
primary.darkActive: common.9
primary.darkHover: common.8
primary.main: common.7
primary.stroke: common.5
primary.strokeHover: common.6
primary.lightHover: common.2
primary.lightActive: common.4
primary.light: common.1
primary.contrastText: common.1
secondary.dark: brand.10
secondary.darkActive: brand.9
secondary.darkHover: brand.8
secondary.main: brand.7
secondary.stroke: brand.5
secondary.strokeHover: brand.6
secondary.lightActive: brand.3
secondary.lightHover: brand.2
secondary.light: brand.1
secondary.contrastText: common.1
error.dark: error.10
error.darkActive: error.9
error.darkHover: error.8
error.main: error.7
error.stroke: error.5
error.strokeHover: error.6
error.lightHover: error.2
error.lightActive: error.3
error.light: error.1
error.contrastText: common.1
success.dark: success.10
success.darkActive: success.9
success.darkHover: success.8
success.main: success.7
success.stroke: success.5
success.strokeHover: success.6
success.lightHover: success.2
success.lightActive: success.3
success.light: success.1
success.contrastText: common.1
warning.dark: warning.10
warning.darkActive: warning.9
warning.darkHover: warning.8
warning.main: warning.7
warning.stroke: warning.5
warning.strokeHover: warning.6
warning.lightActive: warning.3
warning.lightHover: warning.2
warning.light: warning.1
warning.contrastText: common.1
info.dark: info.10
info.darkActive: info.9
info.darkHover: info.8
info.main: info.7
info.stroke: info.5
info.strokeHover: info.6
info.lightActive: info.3
info.lightHover: info.2
info.light: info.1
info.contrastText: common.1
text.primary: common.12
text.secondary: common.11
text.tertiary: common.10
background.primary: common.1
background.secondary: common.2
background.tertiary: common.3
background.paper: common.1
background.default: common.16. 주의사항
-
토큰 시스템 활용
- Panda CSS의 토큰 시스템을 적극 활용하여 일관된 디자인 시스템 구축
- 색상, 간격, 타이포그래피 등의 값을 토큰으로 정의
- 기존 theme 참조:
apps/design-system/src/styles/ - 신규 theme 참조:
apps/design-system/src/preset/
-
성능 최적화
- Panda CSS는 빌드 타임에 CSS를 생성하므로 런타임 성능이 향상됨
- 동적 스타일링이 필요한 경우
css.raw()사용 고려
-
점진적 마이그레이션
- 큰 프로젝트의 경우 컴포넌트 단위로 점진적 마이그레이션 진행
- Emotion과 Panda CSS를 동시에 사용할 수 있음
-
일반적인 문제 해결
- 중첩 선택자 문제: Panda CSS에서는
&선택자를 명시적으로 사용 - 동적 스타일링: 조건부 스타일은 CVA를 사용하여 구현
- 테마 값 접근: Emotion의
theme객체 대신 Panda CSS의 토큰 시스템 사용
- 중첩 선택자 문제: Panda CSS에서는
-
⚠️ 중요: 마이그레이션 범위 제한
CSS 시스템 변환에만 집중하고 다른 변경사항 제외:
다음 사항들은 CSS 마이그레이션과 무관하므로 변경하지 마세요:
// ❌ 잘못된 예시 - import 문 포맷팅 변경 (CSS 변환과 무관) - import { - Menu, - MenuItem, - Stack, - } from '@mildang/mui'; + import { Menu, MenuItem, Stack } from '@mildang/mui'; // ❌ 잘못된 예시 - JSX 포맷팅 변경 (CSS 변환과 무관) - <Tooltip - title="example" - placement="top" - arrow - > + <Tooltip title="example" placement="top" arrow> // ❌ 잘못된 예시 - 변수명 변경, 코드 구조 최적화 등 (CSS 변환과 무관)올바른 마이그레이션 범위 - CSS 시스템만 변경:
// ✅ 올바른 예시 - CSS 시스템만 변경 - css={(theme: Theme) => emotionStyle(theme)} + className={pandaStyle({ variant: 'default' })} // ✅ 올바른 예시 - 스타일 정의 변환만 - const style = emotionCSS`color: red;`; + const style = css({ color: 'red' }); -
⚠️ 중요: CSS 시스템 혼용 금지
절대 금지사항: Emotion CSS와 Panda CSS 혼용
다음과 같이 emotion CSS 스타일을 panda CSS 객체에 스프레드하는 것은 런타임 에러를 발생시킵니다:
// ❌ 잘못된 예시 - 절대 하지 마세요! import { timeInputStyle } from '@mildang/design-system-legacy/esm/styles/commonStyle'; import { css } from '@mildang/styled-system/css'; const style = css({ width: '100%', ...timeInputStyle, // ❌ emotion CSS를 panda CSS에 스프레드 });올바른 해결책:
// ✅ 올바른 예시 - emotion CSS 내용을 panda CSS로 직접 변환 import { css } from '@mildang/styled-system/css'; const style = css({ width: '100%', '& input[type="time"]::-webkit-calendar-picker-indicator': { width: '22px', height: '22px', }, });이유:
- Emotion CSS는
csstagged template 또는css()함수로 emotion 전용 객체/클래스명을 반환 - Panda CSS는 완전히 다른 빌드타임 CSS-in-JS 시스템으로 일반 CSS 객체만 허용
- 두 시스템을 혼용하면 타입 에러와 런타임 스타일 깨짐 현상 발생
마이그레이션 시 확인 포인트:
import에서 emotion CSS 스타일을 가져와서 panda CSS에 스프레드하는 부분 검색...someEmotionStyle패턴을 찾아 해당 스타일을 panda CSS로 직접 변환- emotion CSS 관련 import 제거
- Emotion CSS는
-
🎯 마이그레이션 원칙: 최소 변경
DO (해야 할 것):
- CSS 스타일 정의만 변환 (
emotionCSS→css,cva) - CSS 적용 방식만 변경 (
css={style}→className={style}) - CSS 관련 import만 업데이트
- 사용하지 않는 CSS 관련 import만 제거
DON'T (하지 말아야 할 것):
- 코드 포맷팅 변경 (import 문 정렬, JSX 속성 정렬 등)
- 변수명 변경 또는 리팩토링
- 컴포넌트 구조 변경
- 비즈니스 로직 수정
- CSS와 무관한 import 정리
- 린터 규칙 적용 (CSS 변환과 무관한 경우)
이유: CSS 마이그레이션은 스타일 시스템 전환에만 집중해야 하며, 다른 변경사항은 별도 PR에서 처리해야 합니다.
- CSS 스타일 정의만 변환 (