Chakra UI 완벽 가이드 | 컴포넌트·테마·Emotion 스택·프로덕션
이 글의 핵심
Chakra UI는 React용 컴포넌트 세트이자 테마 시스템입니다. 스타일이 Emotion과 styled-system 위에서 어떻게 해석되는지, SSR·번들·접근성·운영 시 자주 막히는 지점까지 한 번에 정리합니다.
이 글의 핵심
Chakra UI로 아름다운 UI를 구축하는 완벽 가이드입니다. Components, Theming, Dark Mode, 접근성, TypeScript까지 실전 예제로 정리했습니다.
실무 경험 공유: Chakra UI를 도입하면서, UI 개발 속도가 3배 향상되고 접근성이 자동으로 보장된 경험을 공유합니다.
들어가며: “UI 개발이 느려요”
실무에서 마주치는 문제들
컴포넌트를 처음부터 만들어야 해요
시간이 오래 걸립니다. Chakra UI는 50+ 컴포넌트를 제공합니다. 접근성을 고려하지 못해요
수동 구현이 어렵습니다. Chakra UI는 자동으로 보장합니다. 다크 모드가 필요해요
직접 구현이 복잡합니다. Chakra UI는 내장되어 있습니다.
1. Chakra UI란?
핵심 특징
Chakra UI는 React 컴포넌트 라이브러리입니다. 주요 장점
- 50+ 컴포넌트: 즉시 사용 가능
- 접근성: WAI-ARIA 준수
- 테마: 완전한 커스터마이징
- 다크 모드: 내장
- TypeScript: 완벽한 지원
2. 설치 및 설정
설치
npm install @chakra-ui/react @emotion/react @emotion/styled framer-motion
Provider 설정
import { ChakraProvider } from '@chakra-ui/react';
export default function App({ Component, pageProps }) {
return (
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
);
}
3. 기본 컴포넌트
import { Button, Box, Text, Heading, Stack } from '@chakra-ui/react';
export default function Home() {
return (
<Box p={8}>
<Heading mb={4}>Welcome to Chakra UI</Heading>
<Text mb={4}>Build accessible React apps with speed</Text>
<Stack direction="row" spacing={4}>
<Button colorScheme="blue">Primary</Button>
<Button colorScheme="green">Secondary</Button>
<Button variant="outline">Outline</Button>
</Stack>
</Box>
);
}
4. Layout
import { Box, Flex, Grid, GridItem, Container, Stack } from '@chakra-ui/react';
export default function Layout() {
return (
<Container maxW="container.xl">
<Flex justify="space-between" align="center" mb={8}>
<Box>Logo</Box>
<Stack direction="row" spacing={4}>
<Box>Home</Box>
<Box>About</Box>
</Stack>
</Flex>
<Grid templateColumns="repeat(3, 1fr)" gap={6}>
<GridItem>Card 1</GridItem>
<GridItem>Card 2</GridItem>
<GridItem>Card 3</GridItem>
</Grid>
</Container>
);
}
5. Form
import {
FormControl,
FormLabel,
FormErrorMessage,
Input,
Button,
VStack,
} from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
interface FormData {
email: string;
password: string;
}
export default function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm<FormData>();
const onSubmit = (data: FormData) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<VStack spacing={4}>
<FormControl isInvalid={!!errors.email}>
<FormLabel>Email</FormLabel>
<Input {...register('email', { required: 'Email is required' })} />
<FormErrorMessage>{errors.email?.message}</FormErrorMessage>
</FormControl>
<FormControl isInvalid={!!errors.password}>
<FormLabel>Password</FormLabel>
<Input
type="password"
{...register('password', { required: 'Password is required' })}
/>
<FormErrorMessage>{errors.password?.message}</FormErrorMessage>
</FormControl>
<Button type="submit" colorScheme="blue" width="full">
Submit
</Button>
</VStack>
</form>
);
}
6. Theming
import { extendTheme, ChakraProvider } from '@chakra-ui/react';
const theme = extendTheme({
colors: {
brand: {
50: '#e3f2fd',
100: '#bbdefb',
500: '#2196f3',
900: '#0d47a1',
},
},
fonts: {
heading: 'Georgia, serif',
body: 'Arial, sans-serif',
},
components: {
Button: {
baseStyle: {
fontWeight: 'bold',
},
variants: {
solid: {
bg: 'brand.500',
color: 'white',
},
},
},
},
});
export default function App() {
return (
<ChakraProvider theme={theme}>
{/* 컴포넌트 */}
</ChakraProvider>
);
}
7. Dark Mode
import { Box, Button, useColorMode, useColorModeValue } from '@chakra-ui/react';
export default function DarkModeToggle() {
const { colorMode, toggleColorMode } = useColorMode();
const bg = useColorModeValue('white', 'gray.800');
const color = useColorModeValue('black', 'white');
return (
<Box bg={bg} color={color} p={8}>
<Button onClick={toggleColorMode}>
Toggle {colorMode === 'light' ? 'Dark' : 'Light'}
</Button>
</Box>
);
}
8. Responsive
import { Box, Text } from '@chakra-ui/react';
export default function Responsive() {
return (
<Box
width={{ base: '100%', md: '50%', lg: '25%' }}
p={{ base: 4, md: 6, lg: 8 }}
>
<Text fontSize={{ base: 'md', md: 'lg', lg: 'xl' }}>
Responsive Text
</Text>
</Box>
);
}
9. 내부 스택: Emotion·styled-system·테마 토큰
Chakra UI v2 계열은 스타일을 CSS-in-JS(Emotion) 로 생성합니다. Box에 넘기는 p, mt, colorScheme 같은 속성은 styled-system 규칙에 따라 테마 토큰(스페이스 스케일, 컬러 팔레트)으로 해석되고, 최종적으로 고유 클래스명이 붙은 스타일이 주입됩니다. 따라서 “인라인 스타일 객체를 매번 새로 만든다”기보다 테마 기반의 일관된 디자인 토큰을 쓰는 쪽에 가깝습니다.
프로덕션 함의: 런타임 CSS-in-JS는 첫 페인트 이후 스타일 삽입·SSR 시 스타일 순서 이슈를 팀 설정과 맞춰야 합니다. Chakra v3는 아키텍처가 크게 바뀌었으므로, 신규 프로젝트에서는 공식 마이그레이션 가이드와 디자인 시스템 버전을 먼저 고정하는 것이 안전합니다.
10. Next.js·SSR·하이드레이션
App Router·Pages Router 모두 서버에서 HTML을 먼저 보내는 경우, 테마·Color Mode는 초기 색상 플래시(FOUC) 와 연결됩니다. 일반적인 대응은 초기 테마 힌트를 쿠키/헤더에 싣기, ColorModeScript 를 _document에 배치(버전별 문서 확인)하는 식입니다. Emotion 캐시를 서버/클라이언트에 공유하는 설정이 누락되면 클래스가 어긋날 수 있으므로, 공식 Next.js 예제와 패키지 메이저 버전을 함께 맞춥니다.
11. 번들 크기·트리 쉐이킹
@chakra-ui/react에서 필요한 컴포넌트만 import하는 것이 기본입니다. 전역으로 모든 컴포넌트를 등록하는 패턴은 번들 팽창으로 이어집니다. 아이콘 패키지(@chakra-ui/icons)는 사용 아이콘만 가져오고, 차트·에디터처럼 무거운 확장은 지연 로딩을 검토합니다.
12. 접근성·키보드·포커스
Chakra는 많은 컴포넌트에 ARIA 역할·키보드 동작을 기본 탑재합니다. 다만 커스텀 as 폴리모피즘으로 시맨틱이 바뀌면(예: Button as="div") 키보드 포커스가 깨질 수 있습니다. 포커스 링을 끄는 스타일은 WCAG 대비와 함께 검토해야 합니다.
13. 트러블슈팅
| 증상 | 점검 |
|---|---|
| 다크 모드가 한 박자 늦게 적용 | SSR·쿠키·ColorModeScript·시스템 테마 동기화 |
| 스타일이 전혀 안 먹음 | ChakraProvider 누락·상위에서 emotion 캐시 중복 |
| 리스트/모달에서 스크롤 잠김 | Portal 컨테이너·blockScrollOnMount·중첩 모달 |
| 테스트에서 테마 토큰 오류 | Jest·Vitest에 별도 Chakra wrapper 또는 최소 테마 주입 |
| v2 코드를 v3로 옮겼는데 API가 다름 | 마이그레이션 가이드·컴포넌트 이름 변경표 |
정리 및 체크리스트
핵심 요약
- Chakra UI: React 컴포넌트 라이브러리
- 50+ 컴포넌트: 즉시 사용 가능
- 접근성: WAI-ARIA 준수
- 테마: 완전한 커스터마이징
- 다크 모드: 내장
- TypeScript: 완벽한 지원
구현 체크리스트
- Chakra UI 설치
- Provider 설정
- 기본 컴포넌트 사용
- Layout 구성
- Form 구현
- Theming 커스터마이징
- Dark Mode 구현
- Responsive 디자인
같이 보면 좋은 글
이 글에서 다루는 키워드
Chakra UI, React, UI Library, Theming, Accessibility, TypeScript, Frontend
자주 묻는 질문 (FAQ)
Q. MUI와 비교하면 어떤가요?
A. Chakra UI가 더 간단하고 커스터마이징이 쉽습니다. MUI는 더 많은 컴포넌트를 제공합니다.
Q. 번들 크기는 어떤가요?
A. Tree-shakable이라 사용한 것만 포함됩니다.
Q. Next.js에서 사용할 수 있나요?
A. 네, 완벽하게 호환됩니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, 많은 기업에서 안정적으로 사용하고 있습니다.