접근성, 속도, 사용자 경험이 뛰어난 UI 구축을 위한 간결한 규칙입니다. MUST/SHOULD/NEVER를 사용하여 결정을 안내합니다.
상호작용
키보드
- MUST: WAI-ARIA APG에 따른 전체 키보드 지원
- MUST: 표시 가능하고 가려지지 않는 포커스 링 (
:focus-visible;:focus-within과 그룹화); sticky/fixed 요소가 포커스를 덮지 않음 - MUST: APG 패턴에 따라 포커스 관리 (트랩, 이동, 반환)
- NEVER: 포커스 대체 표시 없이
outline: none사용
타겟 및 입력
- MUST: 히트 타겟 ≥24px (모바일 ≥44px); 시각적 크기가 <24px이면 히트 영역 확장
- MUST: 모바일
<input>글꼴 크기 ≥16px (iOS 확대 방지) - NEVER: 브라우저 확대 비활성화 (
user-scalable=no,maximum-scale=1) - MUST:
touch-action: manipulation설정 (더블 탭 확대 방지) - SHOULD: 디자인에 맞게
-webkit-tap-highlight-color설정
폼
- MUST: 수화(hydration)에 안전한 입력 (포커스/값 손실 없음)
- NEVER:
<input>/<textarea>에서 붙여넣기 차단 - MUST: 로딩 버튼은 스피너를 표시하고 원래 레이블을 유지
- MUST: Enter 키는 포커스된 입력 제출;
<textarea>에서는 ⌘/Ctrl+Enter가 제출 - MUST: 요청이 시작될 때까지 제출 활성화; 그런 다음 스피너와 함께 비활성화
- MUST: 자유 텍스트 허용, 이후에 검증 — 타이핑 차단 금지
- MUST: 불완전한 폼 제출을 허용하여 검증 오류 표시
- MUST: 오류는 필드 옆에 인라인으로 표시; 제출 시 첫 번째 오류로 포커스 이동
- MUST:
autocomplete+ 의미 있는name; 올바른type및inputmode - SHOULD: 이메일/코드/사용자 이름에 대해 맞춤법 검사 비활성화
- SHOULD: 플레이스홀더는
…로 끝나고 예시 패턴 표시 - MUST: 탐색 전 저장되지 않은 변경 사항 경고
- MUST: 비밀번호 관리자 및 2FA와 호환 가능; 코드 붙여넣기 허용
- MUST: 텍스트 확장 후행 공백 처리를 위해 값 트림
- MUST: 체크박스/라디오에 데드 존 없음; 레이블+컨트롤이 하나의 히트 타겟 공유
상태 및 탐색
- MUST: URL이 상태를 반영 (딥링크 필터/탭/페이지네이션/확장 패널)
- MUST: 뒤로/앞으로 가기가 스크롤 위치 복원
- MUST: 링크는 탐색에
<a>/<Link>사용 (Cmd/Ctrl/중간 클릭 지원) - NEVER: 탐색에
<div onClick>사용
피드백
- SHOULD: 낙관적 UI; 응답 시 조정; 실패 시 롤백 또는 실행 취소 제공
- MUST: 파괴적 작업 확인 또는 실행 취소 창 제공
- MUST: 토스트/인라인 검증에 polite
aria-live사용 - SHOULD: 줄임표 (
…)는 후속 작업을 여는 옵션 ("이름 바꾸기…") 및 로딩 상태 ("로딩 중…")에 사용
터치 및 드래그
- MUST: 넉넉한 타겟, 명확한 어포던스; 까다로운 상호작용 피하기
- MUST: 첫 번째 툴팁 지연; 이후 동일 요소는 즉시 표시
- MUST: 모달/서랍에서
overscroll-behavior: contain설정 - SHOULD: 페이지 러버밴드 바운스 억제 시
@media (pointer: fine)내부<html>에overscroll-behavior: none설정; 당겨서 새로고침을 위해 거친 포인터(coarse-pointer) 페이지 기본값 유지 - MUST: 드래그 중 텍스트 선택 비활성화 및 드래그된 요소에
inert설정 - MUST: 드래그/스와이프/집기/경로 제스처는 필수적이지 않은 한 탭/클릭 및 키보드 대안 제공
- MUST: 클릭 가능해 보이면 반드시 클릭 가능해야 함
자동 포커스
- SHOULD: 단일 기본 입력이 있는 데스크톱에서 자동 포커스; 모바일에서는 드물게
애니메이션
- MUST:
prefers-reduced-motion준수 (축소된 변형 제공 또는 비활성화) - SHOULD: CSS > Web Animations API > JS 라이브러리 선호
- MUST: 컴포지터 친화적 속성 (
transform,opacity)만 애니메이션 처리 - NEVER: 레이아웃 속성 (
top,left,width,height) 애니메이션 처리 - NEVER:
transition: all— 속성을 명시적으로 나열 - SHOULD: 인과관계를 명확히 하거나 의도적인 즐거움을 더할 때만 애니메이션 처리
- SHOULD: 변경 사항 (크기/거리/트리거)에 맞는 이징 선택
- MUST: 애니메이션은 중단 가능하고 입력 기반이어야 함; 음소거되고 필수가 아닌 루프에만 자동 재생
- MUST: 다른 콘텐츠와 함께 5초 이상 지속되는 자동 재생 모션은 일시 중지, 중지 또는 숨기기 컨트롤 제공
- MUST: 올바른
transform-origin(모션이 "물리적으로" 시작되어야 하는 위치에서 시작) - MUST:
transform-box: fill-box와 함께<g>래퍼에 SVG 변환 적용
레이아웃
- SHOULD: 광학적 정렬; 인식이 기하학보다 우선할 때 ±1px 조정
- MUST: 그리드/베이스라인/가장자리에 의도적인 정렬 — 우발적 배치 금지
- SHOULD: 아이콘/텍스트 잠금 균형 맞추기 (두께/크기/간격/색상)
- MUST: 모바일, 노트북, 울트라와이드 확인 (50% 줌으로 울트라와이드 시뮬레이션)
- MUST: 안전 영역 준수 (
env(safe-area-inset-*)) - MUST: 원치 않는 스크롤바 방지; 오버플로우 수정
- SHOULD: 레이아웃에 JS 측정보다 Flex/Grid 선호
콘텐츠 및 접근성
- SHOULD: 인라인 도움말 우선; 툴팁은 최후의 수단
- MUST: 스켈레톤은 최종 콘텐츠를 반영하여 레이아웃 이동 방지
- MUST:
<title>이 현재 컨텍스트와 일치 - MUST: 막다른 길 없음; 항상 다음 단계/복구 제공
- MUST: 빈/성긴/밀집/오류 상태 디자인
- SHOULD: 둥근 따옴표 (“ ”) 사용; 과부/외톨이 방지 (
text-wrap: balance) - MUST: 숫자 비교에
font-variant-numeric: tabular-nums사용 - MUST: 중복 상태 신호 (색상만으로는 안 됨); 아이콘에는 텍스트 레이블이 있어야 함
- MUST: 시각적 요소에 레이블이 없어도 접근 가능한 이름 존재
- MUST:
…문자 사용 (...아님) - MUST: 제목에
scroll-margin-top; "콘텐츠로 건너뛰기" 링크; 계층적<h1>–<h6> - MUST: 사용자 생성 콘텐츠에 탄력적 (짧음/평균/매우 김)
- MUST: 로케일 인식 날짜/시간/숫자 (
Intl.DateTimeFormat,Intl.NumberFormat) - SHOULD: 브랜드 이름, 코드 토큰 및 식별자에
translate="no"설정 (잘못된 자동 번역 방지) - MUST: 정확한
aria-label; 장식적 요소는aria-hidden - MUST: 아이콘 전용 버튼은 설명적인
aria-label을 가져야 함 - MUST: ARIA보다 기본 시맨틱 (
button,a,label,table) 선호 - MUST: 미디어에는 해당하는 자막/대본/설명이 있어야 함; 컨트롤은 키보드로 조작 가능; 장식적 미디어는 보조 기술로부터 숨김
- MUST: 줄 바꿈 없는 공백:
10 MB,⌘ K, 브랜드 이름
콘텐츠 처리
- MUST: 텍스트 컨테이너가 긴 콘텐츠 처리 (
truncate,line-clamp-*,break-words) - MUST: Flex 자식 요소는 truncation을 위해
min-w-0필요 - MUST: 빈 상태 처리 — 빈 문자열/배열에 대한 깨진 UI 금지
성능
- SHOULD: iOS 저전력 모드 및 macOS Safari에서 테스트
- MUST: 안정적으로 측정 (런타임에 영향을 주는 확장 프로그램 비활성화)
- MUST: 리렌더링 추적 및 최소화 (React DevTools/React Scan)
- MUST: CPU/네트워크 스로틀링으로 프로파일링
- MUST: 레이아웃 읽기/쓰기 배치; 리플로우/리페인트 방지
- MUST: 변경 (
POST/PATCH/DELETE) 대상 <500ms - SHOULD: 제어되지 않는 입력 선호; 제어된 입력은 키 입력당 저렴해야 함
- MUST: 대규모 목록 (>50개 항목) 가상화
- MUST: 접힘선 위 이미지 사전 로드; 나머지는 지연 로드
- MUST: CLS 방지 (명시적 이미지 치수)
- SHOULD: CDN 도메인에 대해
<link rel="preconnect"> - SHOULD: 중요 글꼴:
font-display: swap과 함께<link rel="preload" as="font"> - SHOULD: 애니메이션 GIF보다
<video autoplay muted loop playsinline>; 정지/모션 감소 대안 제공 - SHOULD: 짧고 필수적이지 않은 루프에는 Safari H.264 MP4
<picture>소스,prefers-reduced-motion미디어 조건 및 정지 폴백 포함
다크 모드 및 테마
- MUST: 다크 테마의 경우
<html>에color-scheme: dark설정 - SHOULD:
<meta name="theme-color">가 페이지 배경과 일치 - MUST: 네이티브
<select>: 명시적background-color및color(Windows 수정)
수화(Hydration)
- MUST:
value가 있는 입력에는onChange필요 (또는defaultValue사용) - SHOULD: 수화 불일치에 대비하여 날짜/시간 렌더링 보호
디자인
- SHOULD: 계층적 그림자 (앰비언트 + 직접)
- SHOULD: 반투명 테두리 + 그림자를 통한 선명한 가장자리
- SHOULD: 중첩된 모서리 반경: 자식 ≤ 부모; 동심원
- SHOULD: 색조 일관성: 테두리/그림자/텍스트를 배경 색조 쪽으로 틴트
- MUST: 접근 가능한 차트 (색맹 친화적 팔레트)
- MUST: 명도 대비 충족 — WCAG 2보다 APCA 선호
- MUST:
:hover/:active/:focus에서 명도 대비 증가 - SHOULD: 브라우저 UI를 배경과 일치
- SHOULD: 어두운 색상 그라데이션 띠 현상 방지 (필요시 배경 이미지 사용)