REPO DEEP DIVE · 2026-07-29 · CHAKRA-UI/CHAKRA-UI · Emotion 런타임을 걷어내고 Panda CSS 엔진 위에 다시 지은 v3

chakra-ui/chakra-ui 딥다이브
"스타일 props 그대로, 엔진은 통째로 교체" React 컴포넌트 시스템

Chakra UI<Button colorPalette="teal">처럼 스타일 props를 컴포넌트에 바로 얹어 쓰는 React UI 라이브러리다. 버튼·모달·콤보박스 같은 50개 넘는 접근성 준수 컴포넌트를 하나의 패키지 @chakra-ui/react로 제공한다.

2024년 말 나온 v3는 겉모습(스타일 props API)은 유지하면서 속(스타일 엔진)을 완전히 갈아엎은 드문 사례다. 런타임 CSS-in-JS 라이브러리였던 Emotion을 걷어내고 Panda CSS에서 가져온 토큰·레시피 엔진을 직접 이식했고, 상태 로직은 Ark UI(Zag.js 상태 머신 기반)에 통째로 위임했다. 이 문서는 그 교체가 실제 소스 코드 어디서, 어떻게 일어났는지를 따라간다.

(저장소 chakra-ui/chakra-ui · 제작 Segun Adebayo · 라이선스 MIT · 핵심 패키지 @chakra-ui/react v3.36.1 · React 19 지원(peer ≥18) · pnpm 워크스페이스 모노레포(패키지 4개 + 앱 3개) · 컴포넌트 디렉터리 116개 · 최신 커밋 065f71c, 2026-07-25)
목차
  1. 한 줄 정체
  2. 왜 지금 뜨는가
  3. 무엇을 해결하나
  4. 전체 구조
  5. 핵심 설계·동작 원리
  6. 기술 스택·의존성
  7. 설치·요구사항
  8. 실제 사용 흐름
  9. 함정·오해 방지
  10. 대안 비교
  11. 정리 — 누가 쓰면 좋은가

1한 줄 정체

"스타일 props로 쓰는 React 컴포넌트 라이브러리" — 단, v3는 엔진을 통째로 갈아엎었다

Chakra UI를 한 문장으로 정의하면: "토큰(색·간격·폰트) 기반 디자인 시스템을, CSS 파일 없이 JSX props로 바로 조립하게 해주는 React 컴포넌트 라이브러리"다. <Box p="4" bg="gray.100">처럼 여백·색을 props로 쓰면, 내부 엔진이 이를 실제 CSS로 변환해 페이지에 주입한다.

중요한 건 v2와 v3가 겉으로는 비슷해 보이지만 속은 완전히 다른 프로젝트라는 점이다. v2까지는 Emotion(런타임 CSS-in-JS 라이브러리)의 styled()·ThemeProvider·css prop을 그대로 쓰는 얇은 래퍼였다. v3는 소스 코드 packages/react/src/styled-system/ 폴더 전체가 Panda CSS(정적 CSS-in-JS 프리셋 도구)의 런타임 엔진을 포크해 온 것이고, 컴포넌트의 상태 로직(열림/닫힘, 포커스, 키보드 내비게이션)은 Ark UI라는 별도 헤드리스 라이브러리에 위임한다. 즉 Chakra팀이 스타일 엔진과 상태 머신을 직접 만들지 않고, 검증된 두 오픈소스(Panda·Ark)를 자기 컴포넌트 API 뒤에 이식한 것이다.

한 줄 비유

"같은 리모컨(props API), 안의 TV(엔진)는 완전히 새 부품으로"

사용자 입장에서 리모컨(<Button size="lg" colorPalette="teal"> 같은 문법)은 v2든 v3든 크게 다르지 않다. 하지만 그 리모컨 신호를 받아 실제로 화면을 켜는 TV 내부 회로(스타일 계산 엔진)는 v3에서 완전히 새 부품(Panda 엔진)으로 바뀌었고, 채널을 바꾸는 버튼 로직(열림/닫힘 상태 관리)도 외부 전문 업체(Ark UI)가 만든 모듈로 교체됐다.

겉모습의 연속성 덕분에 "리모컨 사용법 문서"(컴포넌트 API 문서)는 크게 재작성할 필요가 없었지만, 내부를 커스터마이징하거나 디버깅하려는 사람에게는 완전히 다른 책을 다시 읽어야 하는 수준의 변화였다.

용어
CSS-in-JS
CSS 스타일을 별도 .css 파일이 아니라 JavaScript 코드(객체·함수) 안에 정의하고, 실행 시점에 실제 CSS로 변환해 페이지에 넣는 방식. Emotion·styled-components가 대표적이다. "런타임" CSS-in-JS는 브라우저에서 매번 계산하고, "빌드타임"(정적) 방식은 미리 계산해 CSS 파일로 뽑아둔다.
용어
Panda CSS
Chakra UI 팀이 만든 또 다른 오픈소스 도구로, 토큰·레시피 기반으로 CSS를 생성하는 "빌드타임에 가까운" 스타일 시스템. Chakra v3는 이 Panda의 런타임 코드(config.ts·css.ts·cva.ts 등)를 자기 저장소 안으로 그대로 가져와 썼다.
용어
Ark UI / Zag.js
Ark UI는 "스타일이 하나도 없는" 순수 로직 컴포넌트 모음(헤드리스 UI)이고, 그 내부는 상태 머신 라이브러리 Zag.js로 짜여 있다. 아코디언이 열렸는지, 어떤 항목에 포커스가 있는지 같은 "행동"만 책임지고 겉모습은 전혀 정하지 않는다. Chakra는 여기에 스타일만 입힌다.

2왜 지금 뜨는가

"AI가 짜는 코드"에 최적화된 API + 공식 MCP 서버 + 성능 재작성

Chakra UI는 2019년부터 있던 오래된 프로젝트지만, v3(2024년 말 출시) 이후 다시 화제가 된 데는 세 가지 최근 흐름이 겹쳐 있다.

① AI 코딩 도구가 다루기 좋은 "예측 가능한 props 문법"

size="lg", colorPalette="teal", variant="outline"처럼 정해진 값 집합만 받는 props는 LLM(대형 언어 모델)이 코드를 생성할 때 틀리기 어려운 구조다. 실제로 저장소 안에는 apps/mcp라는 공식 MCP(Model Context Protocol) 서버가 들어 있고, packages/cli/src/commands/component.ts 같은 CLI 명령이 AI 에이전트가 컴포넌트를 조회·생성하도록 돕는다. "AI가 UI를 짜는 시대"에 맞춰 도구 자체를 정비한 셈이다.

② v2→v3 대규모 마이그레이션 수요

기존 v2 사용자 다수가 아직 이전하지 못한 채 남아 있어, 공식 codemod(npx @chakra-ui/codemod upgrade)와 마이그레이션 가이드 검색량이 꾸준하다. MCP 서버 안에도 v2-to-v3-migration.ts라는 전용 도구가 있을 정도로, "이전 작업 자체"가 하나의 큰 사용 사례가 됐다.

③ 체감 가능한 성능·번들 크기 개선

공식 블로그(apps/www/content/blog/01-chakra-v2-vs-v3-a-detailed-comparison.mdx)는 v3가 재조정(reconciliation) 성능 4배, 리렌더 성능 1.6배 개선됐다고 밝힌다. 설치 의존성도 v2의 4개 패키지(@chakra-ui/react+@emotion/react+@emotion/styled+framer-motion)에서 v3는 2개(@chakra-ui/react+@emotion/react)로 줄었다. "무거운 UI 라이브러리"라는 인식을 벗으려는 시도다.

시장 포지션
MUI·shadcn/ui·Mantine 사이 어딘가

구글 트렌드·npm 다운로드 기준으로 MUI(Material UI)만큼 크지는 않지만, "스타일 props + 접근성 내장" 조합을 원하는 팀에서 꾸준히 1군 후보로 언급된다. shadcn/ui가 "코드 복사" 방식으로 뜨자, Chakra도 chakra snippet add CLI로 유사한 "컴포지션 복사" 경험을 뒤늦게 제공하기 시작했다(자세한 비교는 10번 섹션).

3무엇을 해결하나

"디자인 토큰 + 접근성 + 상태 로직"을 매번 새로 짜지 않게 해준다

프론트엔드 개발자가 새 프로젝트를 시작할 때 늘 반복하는 세 가지 숙제가 있다. Chakra UI는 이 셋을 한 번에 해결하려는 라이브러리다.

문제 ① — 디자인 토큰을 CSS 변수로 일관되게 뿌리기

"이 프로젝트의 파랑은 정확히 몇 번 색인가", "간격은 4px 단위인가 8px 단위인가"를 팀 전체가 매번 다시 정의하는 대신, Chakra는 packages/react/src/theme/tokens/ 아래 색·간격·폰트·그림자·둥근 모서리 등 20여 종의 토큰을 미리 정의해 CSS 변수(--chakra-colors-...)로 뿌린다. bg="colorPalette.solid"처럼 쓰면 라이트/다크 모드에 따라 알아서 값이 바뀐다.

문제 ② — 접근성(키보드·스크린리더)을 컴포넌트마다 다시 구현하지 않기

아코디언·콤보박스·다이얼로그 같은 컴포넌트는 WAI-ARIA(웹 접근성 표준) 패턴을 정확히 지켜야 스크린리더 사용자·키보드 사용자가 문제없이 쓸 수 있다. 이 로직을 웹앱마다 새로 짜는 건 비효율적이고 버그가 나기 쉽다. Chakra v3는 이 부분을 통째로 Ark UI에 맡겨, "행동은 검증된 라이브러리, 겉모습은 우리 팀 취향"으로 분업한다.

문제 ③ — 팀마다 다른 디자인을 "테마 하나"로 관리하기

버튼 색, 카드 그림자, 기본 폰트 같은 걸 컴포넌트 파일 하나하나 뒤져 고치는 대신, createSystem(defaultConfig, myConfig) 한 곳에서 토큰·레시피(컴포넌트별 스타일 규칙)를 병합해 프로젝트 전체 디자인을 한 번에 바꿀 수 있게 한다.

비유

레고에 비유하면, 토큰은 "정해진 색깔의 블록 세트"이고 레시피는 "이 블록들로 자동차 바퀴를 조립하는 설명서"다. Ark UI는 그 자동차의 "바퀴가 실제로 굴러가게 하는 축과 베어링(작동 부품)"을 담당한다. Chakra는 이 셋을 미리 준비해줘서, 개발자는 색깔·설명서·부품을 처음부터 만들 필요 없이 <Button> 한 줄로 완성된 조립품을 꺼내 쓴다.

4전체 구조

pnpm 워크스페이스 모노레포 — 패키지 4개 + 앱 3개 + 샌드박스 9개

저장소는 pnpm 워크스페이스(pnpm-workspace.yamlpackages/**·apps/**·sandbox/** 등록, packageManager: "pnpm@11.10.0")로 묶인 모노레포다. Turborepo는 쓰지 않는다 — 루트 package.jsonbuild 스크립트는 pnpm --filter=./packages/* build로 pnpm 자체의 필터링 기능만 쓴다(9번 섹션에서 이 부분의 흔한 오해를 다룬다).

┌───────────────────────────────────────────────────────────────┐ │ CHAKRA-UI 모노레포 구조 │ └───────────────────────────────────────────────────────────────┘ packages/ ├── react/ # ★ 본체 — @chakra-ui/react (v3.36.1) │ └── src/ │ ├── styled-system/ # Panda에서 이식한 스타일 엔진 (핵심) │ ├── theme/ # 토큰·시맨틱 토큰·레시피(컴포넌트별 스타일) │ ├── components/ # 116개 컴포넌트 폴더 (Ark UI 래핑) │ ├── hooks/ # useBreakpointValue 등 최소 훅만 남김 │ └── utils/ ├── cli/ # `chakra` CLI — typegen · snippet · component ├── codemod/ # `chakra-codemod` — v2→v3 자동 변환(jscodeshift) └── panda-preset/ # Panda CSS 사용자를 위한 Chakra 프리셋 apps/ ├── www/ # chakra-ui.com 문서 사이트 (Next.js) ├── mcp/ # ★ 공식 MCP 서버 — AI 에이전트용 도구 제공 └── compositions/ # `chakra snippet add`가 받아가는 원본 코드 sandbox/ # Next.js·Vite·Remix·Storybook·Shadow DOM 등 9종 # 실제 프레임워크와의 통합을 실물로 테스트

이 구조가 보여주는 분업은 명확하다. packages/react가 라이브러리 본체이고, cli·codemod는 그 본체를 "쓰기 쉽게/이전하기 쉽게" 돕는 도구, panda-preset은 "Panda CSS를 이미 쓰는 팀이 Chakra 디자인만 가져다 쓰게" 하는 다리다. apps/mcp는 이 라이브러리가 최근 AI 에이전트 생태계에 맞춰 스스로를 노출하는 창구다.

5핵심 설계·동작 원리

가장 중요한 절 — "Emotion 걷어내기"가 실제로 어떻게 됐는지 코드로 확인한다

① 진실: Emotion을 "완전히" 버리지는 않았다 — 저수준만 남기고 포크했다

많은 요약 글이 "v3는 Emotion을 버렸다"고 단순화하지만, 실제 소스는 더 정교하다. packages/react/package.jsondependencies를 보면 @emotion/is-prop-valid·@emotion/serialize·@emotion/use-insertion-effect-with-fallbacks·@emotion/utils가 여전히 들어 있다. 다만 사용자가 직접 설치해야 하던 @emotion/styled는 완전히 제거됐고, @emotion/react는 여전히 peerDependencies에 남아 있다(스타일 삽입에 필요한 <style> 캐시 메커니즘 때문).

결정적 증거는 packages/react/src/styled-system/factory.tsx 파일 맨 위 주석이다:

// Forked from https://github.com/emotion-js/emotion/blob/main/packages/styled/src/base.js
// but optimized for Chakra UI. All credits to the original authors.
// This also serves a bridge to React 19's style tag hoisting features.

즉 Chakra 팀은 @emotion/styled의 내부 구현(base.js)을 통째로 복사해 저장소 안에 두고 직접 유지보수하기로 했다. serializeStyles(Emotion의 CSS 객체 직렬화 함수)·registerStyles·insertStyles(Emotion의 스타일시트 삽입 함수) 같은 저수준 유틸리티만 그대로 쓰고, 상위의 styled() API·번들·의존성 계약은 자기 것으로 바꿨다. "Emotion 런타임 제거"의 진짜 의미는 "사용자가 설치해야 하는 무거운 패키지를 없애고, 필요한 저수준 엔진만 골라 내재화했다"에 가깝다.

흔한 오해
"v3는 CSS-in-JS를 완전히 버리고 정적 CSS로 갔다"는 틀렸다

Panda CSS 자체는 원래 빌드타임에 CSS 파일을 뽑아내는 도구로 유명하다. 하지만 Chakra v3가 가져온 건 Panda의 "빌드 도구"가 아니라 런타임 스타일 계산 엔진(css.ts·cva.ts·serialize.ts 등)이다. 즉 브라우저에서 여전히 스타일 객체를 실시간으로 CSS 문자열로 바꾸고 Emotion의 삽입 메커니즘으로 <style> 태그에 밀어 넣는다 — 이름만 다른 새 런타임 CSS-in-JS 엔진으로 교체된 것이지, 정적 CSS로 전환된 게 아니다. (반대로 @chakra-ui/panda-preset 패키지를 쓰면 Panda의 빌드타임 방식으로 정적 CSS를 뽑을 수 있다 — 이건 별도 선택지다.)

② 토큰 → 시맨틱 토큰 → 레시피, 3단 스타일 파이프라인

packages/react/src/theme/ 폴더는 세 층으로 나뉜다.

이 3단 구조 덕분에 colorPalette="teal" 하나만 바꾸면, 그 컴포넌트 안의 colorPalette.solid·colorPalette.fg 같은 참조가 전부 teal 계열로 자동 치환된다 — 레시피 코드를 건드릴 필요가 없다.

용어
defineRecipe / defineSlotRecipe
컴포넌트 하나(defineRecipe, 예: 버튼)나 여러 부품으로 이뤄진 컴포넌트(defineSlotRecipe, 예: 아코디언의 root·item·trigger·content)의 스타일 변형(variants)을 선언하는 함수. packages/react/src/styled-system/config.ts에서 export const defineRecipe: RecipeIdentityFn = (v) => v로 정의돼 있는데, 사실상 "타입 체크만 해주는 항등 함수"다 — 실제 일은 이 값을 나중에 cva()(단일 레시피 → CSS 클래스 변환)·sva()(슬롯 레시피 버전)가 처리한다.

③ Ark UI 결합 패턴 — "행동은 Ark, 겉모습은 Chakra"

packages/react/src/components/accordion/accordion.tsx를 열어보면 패턴이 선명하다:

import { Accordion as ArkAccordion } from "@ark-ui/react/accordion"
import { createSlotRecipeContext } from "../../styled-system"

const { withProvider, withContext } = createSlotRecipeContext({ key: "accordion" })

export const AccordionRoot = withProvider(ArkAccordion.Root, "root", { forwardAsChild: true })
export const AccordionItem = withContext(ArkAccordion.Item, "item", { forwardAsChild: true })

ArkAccordion.Root는 Ark UI가 만든, 스타일이 전혀 없는 순수 동작 컴포넌트다(열림 상태 관리, 키보드 화살표 이동, ARIA 속성 부여). withProvidercreateSlotRecipeContext가 만든 헬퍼로, 이 Ark 컴포넌트를 감싸서(wrap) "accordion" 슬롯 레시피의 스타일 클래스를 자동으로 주입한다. 116개 컴포넌트 폴더 대부분이 이 withProvider/withContext 패턴을 반복한다 — "헤드리스 라이브러리 + 자체 스타일 레이어"라는 조합을 대규모로 실증하는 좋은 예다.

비유

Ark UI 컴포넌트는 "뼈대와 근육만 있는 마네킹"이다 — 관절이 정확히 움직이고(키보드 접근성), 어디에 뭐가 있는지 표지판도 붙어 있다(ARIA). 하지만 옷은 안 입었다. Chakra의 withProvider/withContext는 이 마네킹에 레시피라는 옷장에서 고른 옷(CSS 클래스)을 입히는 역할이다. 마네킹을 새로 조각할 필요 없이, 옷만 갈아입히면 되는 구조다.

④ 시스템 병합(createSystem) — 프리셋과 커스텀 테마를 합치는 법

packages/react/src/styled-system/system.tscreateSystem(...configs)mergeConfigs(...configs)를 호출하고, merge-config.tsmergeConfigsmergeWith(깊은 병합)로 여러 설정 객체를 하나로 합친다. 그 과정에서 토큰 구조를 정규화하는 특수 로직도 있다 — 예를 들어 { value: "...", 500: {...} }처럼 값과 하위 토큰이 뒤섞인 경우 valueDEFAULT.value로 자동 이동시킨다. 사용자는 createSystem(defaultConfig, myCustomConfig) 한 줄로 "기본 프리셋 + 내 커스터마이징"을 안전하게 합칠 수 있다.

⑤ color-mix — JS 색상 계산 라이브러리 제거

v2는 색상 투명도 조절(예: 파란색을 16% 투명하게)을 위해 theme-tools 패키지의 JS 함수(transparentize)로 RGBA 값을 미리 계산했다. v3는 bg: "blue.200/16"처럼 슬래시 문법을 쓰면 styled-system/color-mix.ts가 이를 CSS 네이티브 함수 color-mix() 호출로 변환한다(color-mix(in srgb, var(--chakra-colors-blue-200), transparent 16%)). 계산을 JS에서 브라우저 CSS 엔진으로 넘긴 것 — "런타임 JS 계산을 줄이고 브라우저 네이티브 기능에 위임"하는 v3 전반의 방향과 일치한다.

6기술 스택·의존성

React 19 · Ark UI 5 · Emotion 저수준 유틸 · TypeScript · Vitest
영역실제 사용
프레임워크React peer ≥18, devDependency로 19.2.6 사용해 테스트. 함수 컴포넌트 + forwardRef(자체 forwardRef 래퍼는 제거됨)
헤드리스 UI@ark-ui/react 5.37.2 — 모든 상태형 컴포넌트(아코디언·콤보박스·다이얼로그 등)의 행동 로직 담당
스타일 엔진자체 styled-system/(Panda CSS 런타임 포크) + Emotion 저수준 유틸(@emotion/serialize·@emotion/utils 등, 스타일 삽입용)
타입TypeScript. tsgo --noEmit(TypeScript의 Go 포팅 실험 버전)로 타입 체크 — 표준 tsc보다 빠른 대안
테스트Vitest + @testing-library/react + vitest-axe(접근성 자동 검사, vitest.setup.ts에서 expect.extend(matchers)로 연결)
빌드패키지별 tsx ../../scripts/build/main.ts 커스텀 빌드 스크립트. Turborepo 없음 — pnpm의 --filter만으로 모노레포 빌드 순서를 관리
CIGitHub Actions .github/workflows/quality.yml — Build·Tests·ESLint·TypeScript 4개 job을 push/PR마다 병렬 실행
린트ESLint(eslint.config.mjs, flat config) + Prettier(format:check/format:write)
배포Changesets(@changesets/cli)로 버전·체인지로그 관리, pnpm release로 npm 배포
용어
헤드리스(headless) UI
겉모습(CSS)이 전혀 없이, 동작·상태·접근성 로직만 제공하는 컴포넌트. "포장 안 된 부품"이라 생각하면 된다. Radix UI·Ark UI·React Aria가 대표적이며, 그 위에 원하는 스타일을 자유롭게 입힐 수 있다.

7설치·요구사항

최소 필요 패키지 2개 · Node 버전 표기가 문서마다 다르다(9번에서 상세)
기본 설치

npm/pnpm으로 두 패키지만

npm install @chakra-ui/react @emotion/react — v2 때 필요했던 @emotion/styled·framer-motion더 이상 설치하면 안 된다(사용하지 않을 뿐 아니라, 저장소가 자체 포크한 유틸과 충돌할 수 있는 구버전을 끌어올 수 있다).

Provider 설정

ChakraProvider + 스니펫의 Provider 조합

루트에서 <ChakraProvider value={defaultSystem}>로 감싸야 스타일 시스템이 동작한다. 다크모드를 쓰려면 npx @chakra-ui/cli snippet add로 받은 components/ui/provider.tsxnext-themesThemeProvider를 함께 조합해준다 — Chakra 자체는 더 이상 다크모드 상태를 관리하지 않는다.

CLI 도구 3종

chakra typegen · chakra snippet add · chakra-codemod upgrade

typegen은 커스텀 테마의 토큰·레시피에 대한 TypeScript 자동완성 타입을 생성한다(packages/cli/src/commands/typegen.ts). snippet add는 Provider·color-mode 토글 같은 미리 만든 코드 조각을 프로젝트에 파일로 복사한다(shadcn/ui 방식과 유사, 10번에서 비교). codemod upgrade는 v2 코드베이스를 자동으로 v3 문법으로 바꿔준다.

항목실제 값(출처)
루트 engines.node>=22.x (레포 루트 package.json)
마이그레이션 가이드 표기"minimum node version required is Node.20.x" (apps/www/content/docs/get-started/migration.mdx)
패키지 매니저packageManager: "pnpm@11.10.0"
번들러 요구사항없음(라이브러리 소비 시) — Vite·Next.js·Remix 등 어떤 React 번들러도 무방(sandbox/ 9종이 실증)
주의
Node 버전 표기가 문서마다 다르다

레포 루트 package.jsonengines.node≥22지만, 공식 마이그레이션 문서는 "Node 20.x"를 최소 버전으로 언급한다. 이건 라이브러리를 개발(기여)할 때 요구되는 버전과, 라이브러리를 소비(설치)할 때 필요한 버전이 다르게 표기된 것으로 보인다 — 실전에서는 헷갈리지 말고 본인 프로젝트에서 직접 설치해 확인하는 게 안전하다.

8실제 사용 흐름

설치 → Provider 감싸기 → 스니펫으로 뼈대 받기 → 컴포넌트 조립 → 커스텀 테마
단계 1

설치 + Provider로 앱 감싸기

npm install @chakra-ui/react @emotion/react
npx @chakra-ui/cli snippet add

두 번째 명령이 components/ui/provider.tsx·color-mode.tsx 등을 프로젝트에 파일로 복사한다. 그 다음 앱 최상단에서 이 Provider로 감싼다.

import { Provider } from "@/components/ui/provider"

export default function App({ children }) {
  return <Provider>{children}</Provider>
}
단계 2

스타일 props로 컴포넌트 조립

import { Button, HStack } from "@chakra-ui/react"

function Demo() {
  return (
    <HStack gap="4">
      <Button colorPalette="teal" size="lg">저장</Button>
      <Button colorPalette="red" variant="outline">삭제</Button>
    </HStack>
  )
}

colorPalette 하나만 바꾸면 버튼 레시피 안의 colorPalette.solid·colorPalette.fg 등의 참조가 자동으로 그 색 계열로 풀린다 — 5번 섹션에서 본 3단 파이프라인이 실제로 작동하는 지점이다.

단계 3

여러 부품으로 된 컴포넌트는 점(.) 표기로

import { Accordion } from "@chakra-ui/react"

<Accordion.Root collapsible>
  <Accordion.Item value="a">
    <Accordion.ItemTrigger>섹션 제목</Accordion.ItemTrigger>
    <Accordion.ItemContent>내용</Accordion.ItemContent>
  </Accordion.Item>
</Accordion.Root>

v2의 <Accordion><AccordionItem><AccordionButton>처럼 컴포넌트 이름을 따로따로 임포트하던 방식 대신, v3는 네임스페이스 임포트(Accordion.Root, Accordion.Item) 하나로 관련 부품을 묶는다. 자동완성이 훨씬 편해진다.

단계 4

커스텀 테마 — createSystem으로 토큰 덮어쓰기

import { createSystem, defaultConfig } from "@chakra-ui/react"

export const system = createSystem(defaultConfig, {
  theme: {
    tokens: {
      fonts: {
        heading: { value: "'Figtree', sans-serif" },
      },
    },
  },
})

모든 토큰 값은 { value: ... } 객체로 감싸야 한다는 게 v3의 새 규칙이다(v2는 fonts: { heading: "..." }처럼 값을 바로 썼다). 이 system<ChakraProvider value={system}>에 넘기면 프로젝트 전체 테마가 바뀐다.

9함정·오해 방지

v2→v3 마이그레이션에서 특히 자주 걸리는 지점들

함정 ① — "일괄 codemod면 다 끝난다"는 착각

npx @chakra-ui/codemod upgrade는 컴포넌트 이름 변경·prop 변경·임포트 경로 변경까지 자동화하지만, 테마 커스터마이징 로직(extendThemecreateSystem)이나 색상 모드 로직(useColorMode 제거) 같은 건 수동 리팩터링이 필요하다. 공식 가이드도 "codemod부터 시작하되, 수동 단계가 이어진다"고 명시한다. codemod 결과를 그대로 배포하지 말고, --dry 플래그로 먼저 미리보기를 하는 게 안전하다.

함정 ② — ColorModeProvider·useColorMode가 사라졌다는 걸 모르고 찾아 헤매기

v2의 ColorModeProvider·useColorMode·useColorModeValue·LightMode/DarkMode 컴포넌트는 v3에 전혀 존재하지 않는다(apps/www/content/blog/01-...mdx의 "Removed Features" 절에서 확인). 대신 next-themes 라이브러리에 위임하고, Chakra는 className="light"/"dark"를 강제로 붙이는 정도만 돕는다. v2 문서를 기억하고 useColorMode를 임포트하려 하면 즉시 에러가 난다.

함정 ③ — styleConfig/multiStyleConfig 문법을 계속 찾다가 시간 낭비

v2의 theme.components.Button.baseStyle 같은 styleConfig 개념은 완전히 없어졌다. v3는 이를 defineRecipe/defineSlotRecipe(5번 섹션)로 교체했다 — 문법 구조 자체가 다르므로 옛 테마 파일을 그대로 복붙하면 타입 에러가 난다.

함정 ④ — "Turborepo로 빌드한다"는 잘못된 가정

많은 대형 모노레포가 Turborepo나 Nx를 쓰기 때문에 Chakra UI도 그럴 거라 추측하기 쉽지만, 실제 저장소에는 turbo.json이 없다. 빌드는 pnpm --filter=./packages/* build처럼 pnpm 자체 워크스페이스 필터로 처리된다. 로컬에서 레포를 클론해 빌드해보려 할 때 "turbo build" 같은 명령을 찾다가 헤매지 않도록 주의.

함정 ⑤ — @emotion/styled를 실수로 다시 설치하기

v2 시절 프로젝트를 이전하면서 package.json에 남아 있는 @emotion/styled·framer-motion을 지우지 않으면, 실제로는 안 쓰이는 무거운 의존성이 번들에 계속 남는다. 마이그레이션 가이드가 명시적으로 npm uninstall @emotion/styled framer-motion을 첫 단계로 두는 이유다.

안전하게 가는 법
"엔진이 아니라 API가 바뀐 지점"부터 고친다

내부 엔진(Panda 포크·Ark UI)이 어떻게 도는지는 몰라도 사용에는 지장이 없다. 실전에서 마주치는 건 대부분 바뀐 API 표면이다 — Provider의 themevalue prop, extendThemecreateSystem, 컴포넌트의 <AccordionItem><Accordion.Item>. 공식 마이그레이션 문서(/docs/get-started/migration)의 "Before/After" 코드 쌍을 표로 정리해두고 하나씩 대조하는 게 가장 빠르다.

10대안 비교

MUI · Mantine · shadcn/ui — "스타일 소유권"을 어디에 두느냐의 차이
라이브러리핵심 차이
MUI(Material UI)Material Design 시스템에 강하게 종속. 커스터마이징은 sx prop이나 styled()로 하지만, 기본 룩을 완전히 지우기가 Chakra보다 손이 더 간다. 생태계·컴포넌트 수는 가장 크다.
MantineChakra와 철학이 가장 비슷하다(토큰+props 기반, 훅 다수 내장). 다만 Mantine은 자체 상태 로직을 직접 구현하는 반면, Chakra v3는 그 부분을 Ark UI라는 외부 헤드리스 레이어에 위임한다는 점이 아키텍처상 가장 큰 차이.
shadcn/ui애초에 "라이브러리"가 아니라 복사해서 내 코드로 만드는 컴포넌트 모음(Radix UI + Tailwind 기반). npm 의존성으로 설치하지 않고 소스를 프로젝트에 직접 둔다. Chakra의 chakra snippet add가 최근 이 방식을 부분적으로 흉내 내지만, Chakra의 핵심 컴포넌트(Button·Accordion 등)는 여전히 @chakra-ui/react 안에 패키지로 남아 있다 — "전체 복사" 모델이 아니다.
비유

MUI는 "풀옵션 완제품 가구", shadcn/ui는 "조립 설명서와 재료만 주는 DIY 키트", Chakra는 그 중간 — "미리 조립된 뼈대(패키지)에 부속 몇 개(snippet)는 직접 골라 붙이는" 방식이다. Mantine은 Chakra와 겉보기엔 가장 닮은 완제품이지만, 내부 뼈대를 자체 제작했다는 점이 다르다.

용어
스타일 소유권(style ownership)
디자인을 고치고 싶을 때, 그 코드가 "내 프로젝트 안"에 있어 자유롭게 고칠 수 있는지, 아니면 "설치된 라이브러리 안"에 있어 오버라이드(덮어쓰기)로만 건드릴 수 있는지의 차이. shadcn/ui는 소유권을 전부 개발자에게 주고, MUI·Chakra·Mantine은 패키지가 소유하되 확장 지점(테마·레시피)을 열어둔다.

11정리 — 누가 쓰면 좋은가

"props로 빠르게, 접근성은 남에게 맡기고" 싶은 팀에 맞다

Chakra UI v3는 "CSS 파일을 거의 안 쓰고 JSX props만으로 일관된 디자인 시스템을 굴리고 싶은 팀", 그리고 "아코디언·콤보박스 같은 복잡한 접근성 로직을 직접 짜고 싶지 않은 팀"에 잘 맞는다. 내부적으로는 Panda CSS 엔진을 포크해 스타일을, Ark UI(Zag.js)를 가져와 상태 로직을 각각 전문 도구에 위임한 조합이라, "바퀴를 다시 발명하지 않는" 설계 철학을 배우기에도 좋은 사례다.

반대로 "컴포넌트 소스 코드 자체를 내 저장소에 두고 마음대로 뜯어고치고 싶다""Material Design 가이드라인을 그대로 따라야 한다"면 MUI 쪽이 더 맞을 수 있다. v2에서 넘어오는 팀이라면 공식 codemod로 시작하되, Provider·테마·색상 모드는 반드시 수동으로 대조하며 이전해야 한다(9번 섹션).

이런 사람에게 추천

디자인 토큰 시스템을 처음 도입하려는 프론트엔드 개발자

Chakra의 토큰→시맨틱 토큰→레시피 3단 구조(5번 섹션)를 따라 읽으면, "토큰 기반 디자인 시스템"이 실제로 어떻게 코드로 구현되는지 대규모 실전 예제로 배울 수 있다.

이런 사람에게 추천

헤드리스 UI + 커스텀 스타일 조합을 설계해보고 싶은 개발자

withProvider/withContext로 Ark UI 컴포넌트를 감싸는 116개의 실제 사례(packages/react/src/components/)를 읽으면, "행동은 남의 라이브러리, 겉모습은 내 것"이라는 조합형 설계를 직접 관찰할 수 있다.