DESIGN_RULES.md
actibooky 프론트엔드 공통 작업 규칙입니다. 브랜드가 바뀌어도 변하지 않는 원칙만 담습니다. 새 프로젝트 루트에 그대로 두면 사람과 AI 에이전트가 같은 규칙을 따릅니다.
DESIGN_RULES.md 란 & 적용 방법
- 무엇 · 원칙·컬러·타이포·깊이·컴포넌트·폼·접근성 등 브랜드 무관 공통 규칙. "감각"이 아니라 규칙으로 일관성을 맞춥니다.
- 서비스 비주얼 토큰 · 정확한 팔레트·스페이싱 스케일·라디우스 값 등은 각 서비스의
DESIGN.md(getdesign 형식) +globals.css가 정의합니다. 이 문서와 짝을 이룹니다. - 어디에 · 프로젝트 루트에
DESIGN_RULES.md로 저장합니다. (아래 버튼으로 복사 또는 다운로드) - 어떻게 연결(import) · 에이전트 지침 파일에서 참조합니다:
Claude Code
CLAUDE.md 에 한 줄:
@DESIGN_RULES.md
Codex / Gemini
AGENTS.md / GEMINI.md 에서 참조 또는 본문 인용.
See ./DESIGN_RULES.md
Cursor / 기타
규칙 파일에서 DESIGN_RULES.md 를 읽도록 지정.
.cursor/rules → DESIGN_RULES.md
DESIGN_RULES.md
DESIGN_RULES.md
actibooky 프론트엔드 공통 작업 규칙. 스택: Next.js (App Router) + React 19 + Tailwind v4 + shadcn/ui(Base UI). 미감은 Vercel Geist식 절제를 따른다.
이 문서는 브랜드가 바뀌어도 변하지 않는 규칙(원칙) 만 담는다. 서비스별 비주얼 토큰(정확한 팔레트·스페이싱 스케일·라디우스 값 등)은 각 서비스의
DESIGN.md(getdesign 형식)와globals.css가 정의한다. 프로젝트 루트에 이 파일을 두고 사람과 AI 에이전트가 함께 따른다.
1. 원칙 (절제 / subtraction)
- 디자이너 없이도 일관성 - "감각"이 아니라 토큰·제약(규칙) 으로 강제한다.
- 절제 - 거의 흰 캔버스 위 거의 검정 잉크가 제목·본문·CTA·보더를 전부 끌고 간다. 그 외에는 거의 아무것도 경쟁하지 않는다.
- 색은 한 곳에만 - 유일한 라이브 액센트는 브랜드 액센트(
--brand). 큰 면을 액센트로 채우지 않는다(링크·포커스·핵심 CTA에만). - 깊이는 그림자가 아니라 1px hairline 우선 - 면 분리는 border 로, 그림자는 최후의 수단.
- 단일 코어 + 서비스 스킨 · 라이트/다크 · 접근성 기본값 AA.
2. 컬러 규칙
- 모든 색은 OKLCH, raw hex/rgb 하드코딩 금지 - 반드시 토큰을 경유한다.
- 잉크-그레이 사다리를 단계적으로:
foreground(잉크) →muted-foreground(본문/보조) → 더 옅은 단계. 본문을 순수 검정(#000)으로 쓰지 않는다. - 표면:
background(캔버스) 위card(elevated), 경계는border(hairline 1px). - 액센트는 하나:
--brand= 링크 · 포커스링 · 핵심 CTA · chart-1. 큰 면 fill 금지. globals.css= 코어(:root+.dark+@theme inline). 서비스 스킨은[data-brand="<service>"]에서 색 토큰 일부만 override. (실제 색 값은 서비스DESIGN.md/globals.css소관.)
3. 타이포그래피 규칙
- 디스플레이일수록 트래킹을 타이트하게(
tracking-tight), 본문은 중립. - 무게는 절제: 제목 700/600, 버튼·라벨 500, 본문 400. (light/black·italic 남용 금지.)
- 금액·표·카운터 등 정렬/갱신 숫자는 tabular-nums.
- 본문은 16px 이상, 한글 가독성 우선.
- 폰트는 토큰으로: 기본 Pretendard, 서비스별 SUIT/SUITE(
font-suit/font-suite). 기술 라벨/코드는 mono. (정확한 타입 스케일 값은 서비스DESIGN.md소관.)
4. 깊이 (elevation) 규칙
- L0 평면: 1px hairline(
border), 그림자 없음 - 기본 카드·인풋·구분선. - L1 위스퍼: border + 아주 옅은 마이크로 섀도(살짝 떠 보이는 카드).
- L2 플로팅: 메뉴·모달·툴팁 등만 레이어드 소프트 섀도.
- 무거운 드롭섀도·글로우 금지. 장식 시스템은 하나만(둘째 장식 추가 금지).
5. 컴포넌트
- shadcn/ui 우선 -
components/ui의 컴포넌트를 최대한 활용한다. components/ui폴더의 기존 컴포넌트는 수정하지 않는다(업스트림/레지스트리 동기화). 변형이 필요하면 래퍼를 만든다.- Base UI 에는
asChild가 없다 → 합성은renderprop:render={<Button ... />}, 필요 시nativeButton={false}. - 새 UI 패턴은 컴포넌트로 추출한다(한 파일 = 한 책임). 페이지에서 raw
<button>등을 직접 만들지 말고 DS 컴포넌트를 쓴다.
6. 폼
- 거의 모든 폼 = zod 스키마 + react-hook-form + shadcn Form 컴포넌트.
- 검증은 제출(또는 다이얼로그 오픈) 전에 수행한다.
7. 상태 · 피드백
- 서버 액션 결과 → 카드가 아니라 sonner toast.
- 비동기 처리 →
toast.promise로 loading/success/error 를 일관되게. - 제출 버튼은 pending 상태(useTransition 등)로 중복 클릭을 막는다.
8. 확인 · 경고
- native
confirm()/alert()금지 → shadcn/Base UI AlertDialog. - 필수값 검증 통과 후 controlled
open으로 열고,ActiononClick에서 실제 동작.
9. 아이콘 · 이미지 · 링크
- 아이콘은 lucide-react.
- 내부 이동은 next/link, 이미지는 next/image. (정적 에셋 다운로드는 일반
<a download>.)
10. 접근성
- 대비 AA 이상. 색만으로 정보를 전달하지 않는다(텍스트·아이콘 병행).
- 키보드 포커스를 가시화한다(
focus-visible). 동적 글자크기·브라우저 줌 허용.
11. Base UI 주의점
GroupLabel은 반드시 해당Group안에 둔다.CommandDialog는 cmdk<Command>루트 래퍼가 필요하다.
12. Do / Don't
Do
- 캔버스는 거의 흰색으로 두고 잉크가 제목·CTA·보더를 끌고 가게 한다.
- 색은 브랜드 액센트와 일러스트에만.
--brand는 링크·포커스에 예약. - 카드·인풋은 1px hairline 먼저, 그림자는 최후.
- 그레이 텍스트 사다리를 단계적으로 밟는다.
- 디스플레이 제목은 타이트한 네거티브 트래킹.
Don't
- 큰 면을 액센트 색으로 채우지 않는다.
- 본문을 순수 검정(
#000)으로 쓰지 않는다. - 그림자를 남발하지 않는다(hairline 우선).
- 둘째 장식 시스템을 추가하지 않는다.
- radius·버튼 모양을 한 맥락에서 혼용하지 않는다.