Checkbox
Stable여러 항목 중 하나 이상을 선택하거나 동의/설정 여부를 전환할 때 사용하는 컴포넌트입니다.
Overview
Checkbox는 목록에서 하나 이상의 항목을 선택하거나, 약관 동의·기능 활성화와 같이 독립적인 상태를 켜고 끌 때 사용합니다. 단독으로 사용하거나 여러 개를 그룹으로 묶어 배치할 수 있습니다.
상태: Unchecked (미선택)
<Checkbox
size="md"
label="마케팅 정보 수신 동의 (선택)"
description="다양한 혜택 및 이벤트 소식을 이메일과 SMS로 받아보실 수 있습니다."
onChange={(e) => setChecked(e.target.checked)}
/>Checkbox는 WAI-ARIA 표준을 준수하며 네이티브 <input type="checkbox">를 내장하고 있습니다. 스페이스바(Space) 및 탭(Tab) 키보드 탐색과 스크린 리더 음성 안내가 완벽하게 지원됩니다.
Anatomy
| 번호 | 구성 요소 | 역할 |
|---|---|---|
| 1 | 컨트롤 박스 (Control Box) | 체크 여부를 시각적으로 표시하는 사각 박스 컨테이너 (호버, 포커스, 에러 테두리 반영) |
| 2 | 인디케이터 (Indicator) | 선택 시 Check 아이콘, 일부 선택 시 Minus(Indeterminate) 아이콘 노출 |
| 3 | 레이블 (Label) | 사용자가 선택하려는 대상의 명확한 이름 또는 동의 문구 (클릭 시 토글) |
| 4 | 보조 설명 (Description) | 옵션에 대한 상세 부가 설명 (스크린 리더 aria-describedby 자동 연결) |
Sizes
화면의 정보 밀도와 사용 맥락에 맞춰 3가지 크기를 제공합니다. 기본값은 md(20px)입니다.
| Size | 규격 (박스 / 아이콘) | 미리보기 (Preview) | 권장 적용 맥락 |
|---|---|---|---|
sm (16px) | 16px / 12px | 테이블 행 내부, 데이터 밀도가 높은 컴팩트 목록 | |
md (20px) | 20px / 14px (기본) | 일반 웹 폼, 설정 다이얼로그, 기본 표준 선택지 | |
lg (24px) | 24px / 16px | 모바일 터치 중심 화면, 전체 동의 및 주요 강조 약관 |
States
사용자의 상호작용 및 데이터 유효성 검증 상태를 명확히 전달합니다.
| 상태 (State) | 미리보기 (Preview) | 동작 및 가이드 |
|---|---|---|
| Unchecked | 사용자가 아직 선택하지 않은 기본 대기 상태 | |
| Checked | 사용자가 동의하거나 기능을 활성화한 상태 | |
| Indeterminate | 부모-자식 그룹에서 하위 항목 중 일부만 선택된 상태 | |
| Error | 필수 동의가 누락되었거나 유효성 검증에 실패한 상태 | |
| Disabled | 조건 미충족 또는 권한 부족으로 비활성화된 상태 |
Variants
체크박스는 단일 옵션 제어 외에도 부모-자식 관계의 전체 선택 그룹(Select All Group) 패턴으로 널리 활용됩니다. 아래 실제 동작하는 예제를 직접 테스트해 보세요.
Guidelines
권장해요
긍정형 문장으로 명확하게 레이블을 작성합니다 (예: '알림 수신').
여러 항목 중 복수 선택이 가능할 때 Checkbox를 사용합니다.
설정 변경이 폼 제출(Submit) 시 한꺼번에 저장되는 흐름에 적용합니다.
하위 항목이 일부만 선택된 부모 체크박스에는 indeterminate 상태를 적용합니다.
피해주세요
부정형 질문으로 혼란을 주지 않습니다 (예: '알림 수신 거부 안 함').
상호 배타적인 단일 선택에는 Checkbox 대신 Radio 버튼을 사용합니다.
토글 즉시 시스템에 즉각 반영되는 설정에는 Checkbox 대신 Switch를 사용합니다.
레이블 없이 단독으로 배치할 때는 aria-label을 누락하지 않습니다.
API
| Prop | Type | Default | Description |
|---|---|---|---|
| size | 'sm' | 'md' | 'lg' | 'md' | 체크박스 컨트롤 박스 크기 및 텍스트 스케일 |
| checked | boolean | undefined | 제어 컴포넌트용 선택 상태 여부 |
| defaultChecked | boolean | undefined | 비제어 컴포넌트용 초기 선택 상태 여부 |
| indeterminate | boolean | false | 부모-자식 그룹의 일부 선택 상태 표현 (aria-checked="mixed") |
| error | boolean | false | 유효성 검사 에러 상태 (aria-invalid="true" 및 빨간 테두리) |
| disabled | boolean | false | 비활성화 상태 여부 |
| label | ReactNode | undefined | 체크박스 우측 레이블 텍스트 (클릭 시 체크박스 토글) |
| description | ReactNode | undefined | 레이블 하단 보조 설명 텍스트 (aria-describedby 자동 연계) |
| wrapperClassName | string | '' | 외곽 레이블 래퍼 커스텀 클래스 |
| onChange | (e: ChangeEvent<HTMLInputElement>) => void | undefined | 선택 상태 변경 시 호출되는 이벤트 핸들러 |
Code Example
import { useState } from 'react';
import { Checkbox } from '@/components/ui';
export function Example() {
const [agreed, setAgreed] = useState(false);
return (
<Checkbox
size="md"
checked={agreed}
label="개인정보 처리방침에 동의합니다 (필수)"
description="수집된 정보는 서비스 제공 목적으로만 활용됩니다."
onChange={(e) => setAgreed(e.target.checked)}
/>
);
}