Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
69360cd
refactor(design-tokens): Figma 의존 제거 및 light/dark 카테고리 분할 구조로 전환
berrypjh May 6, 2026
d9803a2
refactor(ui-core): 토큰 타입과 테스트의 Global 참조를 Light로 변경
berrypjh May 6, 2026
0d014da
refactor(react-ui): ThemeProvider 기본 모드를 global → light로 변경
berrypjh May 6, 2026
c1c3f79
refactor(react-native-ui): ThemeProvider 기본 모드를 global → light로 변경
berrypjh May 6, 2026
1731a1c
feat(demo-web): 디자인 토큰 카탈로그 페이지와 라이트/다크 테마 토글 추가
berrypjh May 6, 2026
c8ad23d
build(root): Tailwind CSS v4 마이그레이션
berrypjh May 6, 2026
a7f4be7
refactor(design-tokens): SD 파이프라인 정리 및 AI 친화 산출물 추가
berrypjh May 7, 2026
3c7d731
refactor(ui-core): dead code 정리 및 AI 친화 문서·산출물 추가
berrypjh May 7, 2026
9f899f7
build(ui-core): tsc 산출물을 out-tsc로 격리해 src 오염 차단
berrypjh May 8, 2026
1b891b6
refactor(react-native-ui): 캡슐화 정리 + 소비자용 AGENTS·tokens 카탈로그 노출
berrypjh May 8, 2026
398c1f8
refactor(react-ui): 캡슐화·AI 친화 layer·빌드 파이프라인 정비
berrypjh May 8, 2026
dcbfb95
feat(demo-mobile): react-native-ui 토큰·테마 데모로 App 화면 전환
berrypjh May 8, 2026
5bdc595
refactor(demo-web): Tailwind 토큰 클래스로 마이그레이션 + design-tokens 직접 의존 제거
berrypjh May 8, 2026
9077434
chore(root): 에디터/포매터 워크스페이스 설정 정비
berrypjh May 8, 2026
322287f
refactor(design-tokens): 토큰 JSON을 DTCG 형식으로 마이그레이션
berrypjh May 9, 2026
f80c25c
refactor(react-native-ui): ThemeProvider 기본 토큰 매핑 명시화 + 소비자 문서 정확화
berrypjh May 9, 2026
860a85c
refactor(react-ui): MenuItem 미사용 export 정리 + 소비자 문서 정확화
berrypjh May 9, 2026
878ed07
refactor(ui-core): leaf-primitive 토큰 구조에 맞춰 path 타입·테스트 정리
berrypjh May 9, 2026
31d5c55
build(root): 릴리즈/CI 설정과 npm scripts 재정비
berrypjh May 9, 2026
d3f0683
chore(demo-mobile): nx project.json 추가
berrypjh May 9, 2026
17f842a
chore(demo-web): project.json의 빈 targets 블록과 안내 주석 제거
berrypjh May 9, 2026
f010360
chore(demo-web-e2e): package.json의 nx implicitDependencies 제거
berrypjh May 9, 2026
90fd1a9
feat(react-ui): 정식 배포용 스타일 진입점 확정
berrypjh May 9, 2026
08d8e6c
chore(scripts): measure-tokens·treeshake 측정 스크립트 추가
berrypjh May 9, 2026
f7f8078
docs(root): ai-commit skill에 BREAKING CHANGE 적용 범위와 글자 수 제한 명시
berrypjh May 9, 2026
0270277
chore(root): size-limit react-native-ui 한도를 실측 baseline +20%로 조정
berrypjh May 9, 2026
3f15580
chore(demo-mobile): typecheck 타깃 명시 추가
berrypjh May 9, 2026
497fea2
chore(demo-web): typecheck 타깃 명시 추가
berrypjh May 9, 2026
d7970db
chore(demo-web-e2e): typecheck 타깃 명시 추가
berrypjh May 9, 2026
04d1520
feat(design-tokens): primary를 emerald로 교체하고 WCAG AA 매핑으로 정비
berrypjh May 9, 2026
fb2b874
fix(react-ui): SCSS 로드 순서 정정 + composite outDir + button 색 variant 매핑 정비
berrypjh May 9, 2026
bcf82c8
style(ui-core): README 포매팅 정비
berrypjh May 9, 2026
cd0e253
ci(root): Storybook a11y 자동 검사(axe + WCAG 2 AA) job 추가
berrypjh May 9, 2026
96a8f26
fix(design-tokens): light text.secondary를 se700으로 올려 ne100 캔버스에서 AA 충족
berrypjh May 9, 2026
3ba248a
test(react-ui): Storybook test-runner a11y baseline + 14개 stories 임시 …
berrypjh May 9, 2026
9e787fe
build(root): typecheck/build-storybook 의존성 보정
berrypjh May 9, 2026
033815b
chore(demo-mobile): typecheck dependsOn에 ^typecheck 추가
berrypjh May 9, 2026
0ff3e49
chore(demo-web): typecheck dependsOn에 ^typecheck 추가
berrypjh May 9, 2026
506ba85
build(react-ui): typecheck가 out-tsc로 declaration을 emit하도록 변경
berrypjh May 9, 2026
b8141c7
build(ui-core): typecheck가 out-tsc로 declaration을 emit하도록 변경
berrypjh May 9, 2026
4b274c6
ci(root): size job을 명시 step으로 교체
berrypjh May 9, 2026
3f5b2d4
build(design-tokens): typecheck를 build:ts 의존 noop으로 명시
berrypjh May 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions .claude/skills/ai-commit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: ai-commit
description: staged 변경을 scope별로 분석하고 Conventional Commits 형식의 한국어 커밋 메시지를 제안한 뒤, 승인 후 scope별로 커밋한다.
when_to_use: Use when the user wants to create commit messages for staged git changes, especially when multiple apps/libs scopes are staged together.
argument-hint: [optional-scope]
argument-hint: [major]
disable-model-invocation: true
---

Expand All @@ -25,30 +25,41 @@ disable-model-invocation: true

## 입력 인자

- `$ARGUMENTS`가 비어 있으면: 모든 staged scope를 처리한다.
- `$ARGUMENTS`에 scope가 있으면: 해당 scope만 처리한다.
- 예: `/ai-commit main-web`
- 예: `/ai-commit react-ui`
scope 선택은 사용자가 `git add`로 직접 제어한다. skill은 scope 인자를 받지 않는다.

- 인자 없음: 모든 staged scope를 일반(patch/minor) commit 흐름으로 처리한다.
- `major`: 이번 호출의 **published library scope** commit에만 BREAKING CHANGE footer 처리 흐름을 적용한다.
- published library scope = `libs/*`의 두 번째 path 세그먼트 (현재: `design-tokens`, `ui-core`, `react-ui`, `react-native-ui`)
- `root`, `apps/*`(예: `demo-web`, `demo-mobile`, `demo-web-e2e`), `scripts` 등 그 외 scope는 `major` 인자가 있어도 일반 흐름으로 처리한다.
- staged scope 중 library scope가 하나도 없으면 `major` 인자가 무시된다는 사실을 한 번 알리고 일반 흐름으로 진행한다.
- 같은 메시지에 `BREAKING CHANGE: <본문>` 형식의 footer 본문이 함께 있으면 그 본문을 그대로 사용한다.
- 본문이 없으면 사용자에게 마이그레이션 가이드를 묻고, 응답을 받기 전까지 commit하지 않는다.
- 합성된 commit 메시지(title + body + footer) 전체를 사용자에게 다시 보여주고 별도 승인(`y`)을 받는다.
- 0.x 단계라면 다음 release에서 1.0.0으로의 major bump가 발생할 수 있음을 한 번 안내한다.
- 그 외 인자는 무시하고 일반 흐름으로 처리한다.

## 반드시 지킬 절차

1. 먼저 `list_staged_scopes` tool을 호출한다.
2. staged scope가 없으면 그 사실을 알려주고 바로 종료한다.
3. `$ARGUMENTS`가 있으면 그 값과 정확히 일치하는 scope만 대상으로 삼는다.
- 해당 scope가 없으면 존재하는 scope 목록을 보여주고 종료한다.
4. 각 대상 scope마다 `get_scope_details` tool을 호출한다.
5. 각 scope에 대해 커밋 메시지를 제안한다.
3. 각 staged scope마다 `get_scope_details` tool을 호출한다.
4. 각 scope에 대해 커밋 메시지를 제안한다.
- title 형식: `type(scope): 설명`
- type은 영어 (`feat`, `fix`, `refactor`, `docs`, `style`, `test`, `chore`, `build`, `ci`)
- scope는 MCP가 반환한 값 그대로 사용한다
- type은 영어 lower-case (`feat`, `fix`, `refactor`, `docs`, `design`, `style`, `test`, `chore`, `build`, `ci`, `revert`)
- scope는 MCP가 반환한 값 그대로 사용한다 (lower-case 유지)
- 설명은 한국어로 작성한다
- body는 최대 3줄
- rename / delete / copy / 공통화 / 구조 정리가 핵심이면 body에서 반드시 언급한다
6. 반드시 사용자 승인 후에만 `commit_scope` tool을 호출한다.
- 글자 수 제한 (commitlint hard limit — 위반 시 commit 차단)
- title: 100자 이내 (`header-max-length`)
- footer 각 줄: 100자 이내 (`footer-max-line-length`) — BREAKING CHANGE 본문이 길면 줄바꿈으로 wrap
- body: 제한 없음(프로젝트 override) 이지만 가독성을 위해 100자 이내 권장
- `major` 인자가 있고 scope가 published library(`libs/*`)일 때만 위 BREAKING CHANGE footer 처리 절차를 함께 따른다
5. 반드시 사용자 승인 후에만 `commit_scope` tool을 호출한다.
- 승인 전에는 절대 커밋하지 않는다.
7. 여러 scope가 있으면 한 번에 전부 commit하지 말고, scope별로 순서대로 승인받고 진행한다.
8. 사용자가 수정 요청을 하면 수정된 제목/본문으로 다시 제안한 뒤 승인받는다.
9. tool 실행이 실패하면 stderr/에러를 요약해서 보여주고, 다음 scope로 넘어갈지 중단할지 사용자 의사를 확인한다.
6. 여러 scope가 있으면 한 번에 전부 commit하지 말고, scope별로 순서대로 승인받고 진행한다.
7. 사용자가 수정 요청을 하면 수정된 제목/본문으로 다시 제안한 뒤 승인받는다.
8. tool 실행이 실패하면 stderr/에러를 요약해서 보여주고, 다음 scope로 넘어갈지 중단할지 사용자 의사를 확인한다.

## 응답 방식

Expand Down Expand Up @@ -83,3 +94,5 @@ disable-model-invocation: true
- body가 불필요하면 비워도 되지만, rename/refactor 성격이 강하면 body를 넣는다.
- 사용자가 "본문 없이"를 원하면 title만 사용한다.
- 사용자가 여러 scope를 한 번에 묶어달라고 명시하지 않은 이상, scope별 개별 커밋을 유지한다.
- BREAKING CHANGE footer는 사용자가 `major` 인자로 명시적으로 요청하고 scope가 published library(`libs/*`)일 때만 추가한다. LLM이 자체 판단으로 footer를 제안하거나 추가하지 않는다.
- title은 `feat(scope): ...` 같은 형식만 허용한다. `feat!:` 등 헤더 `!` 표기는 commitlint(`no-header-bang`)가 차단하므로 사용하지 않는다.
35 changes: 35 additions & 0 deletions .claude/skills/ai-commit/examples/commit-message-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,27 @@
- `fix`: 버그 수정
- `refactor`: 동작 변화 없이 구조 개선
- `docs`: 문서 수정
- `design`: 시각적 디자인/스타일 토큰 변경 (프로젝트 허용 type)
- `style`: 포맷/스타일만 수정
- `test`: 테스트 추가/수정
- `chore`: 설정, 스크립트, 유지보수성 변경
- `build`: 빌드 관련 변경
- `ci`: CI/CD 관련 변경
- `revert`: 이전 commit revert (프로젝트 허용 type)

## 길이 제한 (commitlint hard limit)

위반하면 commit이 차단된다. 메시지를 제안할 때 미리 맞춰서 작성한다.

| 위치 | 제한 | 출처 |
| ---------------- | --------------------------------------- | --------------------------------------------------- |
| title (header) | 100자 이내 | `header-max-length` (config-conventional 기본) |
| footer 각 줄 | 100자 이내 | `footer-max-line-length` (config-conventional 기본) |
| body 각 줄 | 제한 없음 (가독성 위해 100자 이내 권장) | 프로젝트 override (`body-max-line-length: 0`) |
| header `!:` 표기 | 금지 — `feat!:` 사용 X | 프로젝트 custom rule `no-header-bang` |
| type/scope case | lower-case 필수 | config-conventional 기본 |

특히 BREAKING CHANGE footer 본문은 한 줄에 길게 쓰면 commitlint가 차단한다. 한국어 한 글자도 1자로 카운트되므로 마이그레이션 가이드 본문은 적절히 줄바꿈해야 한다.

## 제목 작성 규칙

Expand Down Expand Up @@ -88,3 +104,22 @@ body
- 미래 계획 언급
- "최적화", "개선", "정리"만 있고 대상이 없는 제목
- scope 임의 변경

## BREAKING CHANGE 표기 (`/ai-commit major` 사용 시에만)

- 평소에는 절대 추가하지 않는다. 사용자가 `major` 인자로 명시적으로 요청하고, **scope가 published library(`libs/*`)일 때만** 처리한다.
- `root`, `apps/*`, `scripts` 등 비-library scope는 `major` 인자가 있어도 일반 흐름으로 commit한다.
- title은 일반 conventional commit 그대로 사용한다. `feat!:`, `fix!:` 등 헤더 `!` 표기는 commitlint가 차단하므로 사용하지 않는다.
- body 마지막 단락에 빈 줄 한 행을 둔 뒤 `BREAKING CHANGE: <마이그레이션 가이드>` footer를 작성한다.
- footer 본문은 사용자가 제공한 텍스트를 그대로 사용한다. LLM이 추측해서 작성하지 않는다.

좋은 예:

```
feat(react-ui): ThemeProvider API 정리

기존 mode prop을 제거하고 theme prop으로 통합한다.

BREAKING CHANGE: ThemeProvider의 mode prop이 theme prop으로 이름 변경됨.
기존 사용처는 theme={mode}로 마이그레이션 필요.
```
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# ─── tools/scripts/measure-tokens (선택) ───────────────────────────────────
# Anthropic count_tokens API 사용 시 필요. OpenAI/tiktoken만 쓰면 비워둬도 됨.
# 발급: https://console.anthropic.com/settings/keys
ANTHROPIC_API_KEY=

# 모델 오버라이드 (선택)
# MEASURE_ANTHROPIC_MODEL=claude-sonnet-4-6
# MEASURE_OPENAI_MODEL=gpt-4o
12 changes: 6 additions & 6 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ on:
branches: [main]
types: [opened, synchronize, reopened]
paths:
- 'libs/react-ui/**'
- "libs/react-ui/**"
push:
branches: [main]
paths:
- 'libs/react-ui/**'
- "libs/react-ui/**"

concurrency:
group: chromatic-${{ github.workflow }}-${{ github.ref }}
Expand All @@ -30,16 +30,16 @@ jobs:
uses: pnpm/action-setup@v6
with:
version: ${{ vars.PNPM_VERSION }}
run_install: false

- name: Setup Node.js
- name: Setup Node.js (pnpm cache)
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: 'pnpm'
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile
run: pnpm install --frozen-lockfile --prefer-offline

- name: Build Libraries
run: pnpm run build:libs:web
Expand Down
123 changes: 117 additions & 6 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: 'pnpm'
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
Expand Down Expand Up @@ -97,7 +97,7 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: 'pnpm'
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
Expand All @@ -106,10 +106,44 @@ jobs:
- name: Lint (affected)
run: pnpm nx affected -t lint --parallel=3 --base=$NX_BASE --head=$NX_HEAD

typecheck:
name: Typecheck (affected)
runs-on: ubuntu-latest
needs: [derive-shas]
permissions:
contents: read
env:
NX_BASE: ${{ needs.derive-shas.outputs.nx_base }}
NX_HEAD: ${{ needs.derive-shas.outputs.nx_head }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
filter: tree:0

- name: Install pnpm
uses: pnpm/action-setup@v6
with:
version: ${{ vars.PNPM_VERSION }}

- name: Setup Node.js (pnpm cache)
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile --prefer-offline

- name: Typecheck (affected)
run: pnpm nx affected -t typecheck --parallel=3 --base=$NX_BASE --head=$NX_HEAD

test:
name: Unit Tests (affected)
runs-on: ubuntu-latest
needs: [derive-shas, format, lint]
needs: [derive-shas, format, lint, typecheck]
permissions:
contents: read
env:
Expand All @@ -131,7 +165,7 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: 'pnpm'
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
Expand All @@ -140,10 +174,87 @@ jobs:
- name: Run Unit Tests
run: pnpm nx affected -t test --configuration=ci --parallel=3 --base=$NX_BASE --head=$NX_HEAD

size:
name: Bundle Size (size-limit)
runs-on: ubuntu-latest
needs: [format, lint]
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
filter: tree:0

- name: Install pnpm
uses: pnpm/action-setup@v6
with:
version: ${{ vars.PNPM_VERSION }}

- name: Setup Node.js (pnpm cache)
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile --prefer-offline

- name: Build libs
run: pnpm run build:libs

- name: size-limit
run: pnpm run size

a11y:
name: Accessibility (Storybook + axe)
runs-on: ubuntu-latest
needs: [format, lint]
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
filter: tree:0

- name: Install pnpm
uses: pnpm/action-setup@v6
with:
version: ${{ vars.PNPM_VERSION }}

- name: Setup Node.js (pnpm cache)
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile --prefer-offline

- name: Cache Playwright browsers
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}

- name: Install Playwright Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Build Storybook
run: pnpm run build-storybook

- name: Run a11y tests (axe + WCAG 2 AA)
run: pnpm run storybook:a11y

build:
name: Build (affected)
runs-on: ubuntu-latest
needs: [derive-shas, format, lint, test]
needs: [derive-shas, format, lint, typecheck, test]
permissions:
contents: read
env:
Expand All @@ -165,7 +276,7 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: ${{ vars.NODE_VERSION }}
cache: 'pnpm'
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
node-version: ${{ vars.NODE_VERSION }}
cache: pnpm
registry-url: https://npm.pkg.github.com
scope: '@${{ github.repository_owner }}'
scope: "@${{ github.repository_owner }}"

- name: Install Dependencies
run: pnpm install --frozen-lockfile
Expand All @@ -48,6 +48,8 @@ jobs:
run: |
git config user.name "${{ vars.RELEASE_GIT_NAME }}"
git config user.email "${{ vars.RELEASE_GIT_EMAIL }}"
# CI에서는 husky hooks(보호 브랜치 차단)를 명시적으로 무력화
git config core.hooksPath /dev/null

# Beta 배포
- name: NX Release (Beta)
Expand Down
4 changes: 0 additions & 4 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ out
.next
.storybook-static

# 문서
README.md
tools/template/*

# Lock 파일
package-lock.json
pnpm-lock.yaml
Expand Down
21 changes: 19 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,25 @@
"bracketSameLine": false,
"arrowParens": "always",
"endOfLine": "lf",
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "css",
"embeddedLanguageFormatting": "auto",
"singleAttributePerLine": false
"singleAttributePerLine": false,
"overrides": [
{
"files": ["*.md", "*.mdx"],
"options": {
"proseWrap": "preserve",
"printWidth": 100,
"tabWidth": 2,
"embeddedLanguageFormatting": "auto"
}
},
{
"files": ["*.yml", "*.yaml"],
"options": {
"tabWidth": 2,
"singleQuote": false
}
}
]
}
Loading
Loading