diff --git a/.agents/skills/code/component/SKILL.md b/.agents/skills/code/component/SKILL.md new file mode 100644 index 00000000..ef93799d --- /dev/null +++ b/.agents/skills/code/component/SKILL.md @@ -0,0 +1,26 @@ +# code/component + +## 트리거 + +- "컴포넌트 만들어줘" +- "{이름} 컴포넌트 생성해줘" + +## 참조 + +- `docs/conventions/component.md` → 네이밍/코드 스타일 (rafce, fragment, 타입 위치 등) +- `docs/conventions/architecture.md` → 폴더 구조 + +## Phase 1 — 계획 확인 + +1. 컴포넌트 성격을 확인한다: + - 여러 페이지에서 재사용 → `apps/{app}/src/shared/components/` + - 특정 페이지 전용 → `apps/{app}/src/pages/{page}/components/` + - 디자인 시스템(범용 UI) → `packages/design-system/src/components/` +2. 컴포넌트명(PascalCase)과 폴더명(camelCase), props 타입 필요 여부를 확인한다. +3. 배치 경로·파일명·props 타입 초안을 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +## Phase 2 — 실행 + +1. `{경로}/{folderCamelCase}/{ComponentPascalCase}.tsx`를 생성한다. +2. `docs/conventions/component.md`의 컴포넌트 규칙을 따른다: `rafce` 형태, 의미 없는 `div` 대신 fragment, children 불필요 시 selfClosing, props 타입은 컴포넌트 상단에 정의. +3. 생성된 파일 경로를 요약해 보고한다. diff --git a/.agents/skills/code/page/SKILL.md b/.agents/skills/code/page/SKILL.md new file mode 100644 index 00000000..dd396f9b --- /dev/null +++ b/.agents/skills/code/page/SKILL.md @@ -0,0 +1,22 @@ +# code/page + +## 트리거 + +- "새 페이지 만들어줘" +- "{이름} 페이지 스캐폴딩해줘" + +## 참조 + +- `docs/conventions/architecture.md` → 폴더 구조 + +## Phase 1 — 계획 확인 + +1. 페이지명(camelCase)과 위치(`apps/{app}/src/pages/{name}`)를 확인한다. +2. 필요한 하위 폴더(`components`, `hooks`, `utils`, `types`, `apis`, `constants` 중 실제로 쓸 것만)를 확인한다. +3. 생성할 폴더/파일 목록을 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +## Phase 2 — 실행 + +1. 승인된 하위 폴더만 `apps/{app}/src/pages/{name}/` 아래 생성한다 (빈 폴더는 자리표시 파일 없이 실제 파일과 함께 생성). +2. 라우팅 연결이 필요하면 `routes` 설정에 추가할지 사용자에게 확인한다. +3. 생성된 구조를 요약해 보고한다. diff --git a/.agents/skills/figma/to-code/SKILL.md b/.agents/skills/figma/to-code/SKILL.md new file mode 100644 index 00000000..54e7e05d --- /dev/null +++ b/.agents/skills/figma/to-code/SKILL.md @@ -0,0 +1,29 @@ +# figma/to-code + +## 트리거 + +- "이 피그마 디자인 구현해줘" +- "피그마 링크 보고 컴포넌트 만들어줘" + +## 사전 설정 + +- `docs/setup/figma-mcp.md` → Figma MCP 연동 설정. 세션에 Figma MCP 도구가 없으면 먼저 이 문서를 안내한다. + +## 참조 + +- `docs/conventions/component.md` → 네이밍/코드 스타일 +- `docs/conventions/architecture.md` → 폴더 구조 +- `docs/design/tokens.md` → 색상/spacing/타이포그래피 토큰 +- `.agents/skills/code/component/SKILL.md` → 배치 위치(shared/pages/design-system) 판단 및 파일 생성 절차 + +## Phase 1 — 디자인 컨텍스트 확보 및 계획 + +1. 공유된 Figma URL로 디자인 컨텍스트(구조, 스크린샷, 변수/토큰)를 가져온다. +2. 추출한 구조를 컴포넌트 단위로 분해하고, `code/component` 스킬의 Phase 1 배치 기준을 그대로 적용해 각 컴포넌트의 배치 위치(shared/pages/design-system)를 정한다. +3. 컴포넌트 목록 + 배치 경로 + 스타일 매핑 개요(어떤 값이 `docs/design/tokens.md`에 있고, 없는 값은 무엇인지)를 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +## Phase 2 — 구현 + +1. `code/component` 스킬의 Phase 2를 그대로 따라 파일을 생성한다 (rafce, fragment, props 타입 위치 등 `component.md` 규칙 적용). +2. 색상/spacing/타이포그래피는 `docs/design/tokens.md`에 등록된 토큰으로만 매핑한다. 표에 없는 값이 필요하면 hex/px를 하드코딩하지 않고, 토큰을 새로 추가할지 먼저 사용자에게 확인한다. +3. 구현 결과를 디자인 스크린샷과 비교해 자체 점검하고 요약 보고한다. diff --git a/.agents/skills/figma/to-figma/SKILL.md b/.agents/skills/figma/to-figma/SKILL.md new file mode 100644 index 00000000..80f99c21 --- /dev/null +++ b/.agents/skills/figma/to-figma/SKILL.md @@ -0,0 +1,21 @@ +# figma/to-figma + +## 트리거 + +- "이 컴포넌트 피그마로 만들어줘" +- "이 페이지 디자인 동기화해줘" + +## 사전 설정 + +- `docs/setup/figma-mcp.md` → Figma MCP 연동 설정. 세션에 Figma MCP 도구가 없으면 먼저 이 문서를 안내한다. + +## Phase 1 — 대상 확인 + +1. 반영할 코드 범위(컴포넌트/페이지)와 대상 Figma 파일·위치를 확인한다. +2. Figma MCP 도구를 호출하기 전에 해당 MCP가 제공하는 사전 스킬(`/figma-use` 등)이 있으면 먼저 로드한다. +3. 반영 계획(대상 코드, 대상 Figma 파일, 생성/수정 범위)을 출력하고 사용자 승인을 기다린다. **외부 Figma 파일을 직접 수정하는 작업이므로 승인 없이 Phase 2로 넘어가지 않는다.** + +## Phase 2 — 실행 + +1. 승인된 범위로 Figma MCP 도구를 호출해 반영한다. +2. 결과 Figma 파일 링크를 보고한다. diff --git a/.agents/skills/git/branch/SKILL.md b/.agents/skills/git/branch/SKILL.md new file mode 100644 index 00000000..e029ee38 --- /dev/null +++ b/.agents/skills/git/branch/SKILL.md @@ -0,0 +1,25 @@ +# git/branch + +## 트리거 + +- "이슈 #123 브랜치 만들어줘" +- "브랜치 새로 파줘" +- "{기능} 작업 브랜치 만들어줘" + +## 참조 + +- `docs/conventions/branch.md` → 브랜치 네이밍 형식 +- `docs/conventions/merge.md` → develop 최신화 규칙 + +## Phase 1 — 계획 확인 + +1. 이슈번호와 작업 타입(`docs/conventions/commit.md`의 타입 목록 중 하나)을 확인한다. 사용자가 알려주지 않았다면 GitHub 이슈 제목/라벨을 조회하거나 직접 물어본다. +2. `docs/conventions/branch.md` 형식에 맞춘 브랜치명을 제안한다: `{타입}/#{이슈번호}/{기능명}` +3. 현재 브랜치가 `develop`이 아니거나 `develop`이 최신이 아닐 수 있으면 함께 안내한다. +4. 브랜치명과 실행 계획을 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +## Phase 2 — 실행 + +1. `develop`으로 이동해 `git pull origin develop`으로 최신화한다. +2. 승인된 이름으로 `git checkout -b {브랜치명}`을 실행한다. +3. 생성된 브랜치명과 시작 커밋을 요약해 보고한다. diff --git a/.agents/skills/git/commit/SKILL.md b/.agents/skills/git/commit/SKILL.md new file mode 100644 index 00000000..deb1a830 --- /dev/null +++ b/.agents/skills/git/commit/SKILL.md @@ -0,0 +1,54 @@ +# git/commit + +## 트리거 + +- "커밋해줘" +- "커밋 만들어줘" +- "지금까지 한 거 커밋해줘" +- "변경사항 나눠서 커밋해줘" + +## 참조 + +- `docs/conventions/commit.md` → 타입 목록과 메시지 형식 +- `docs/conventions/merge.md` → main/develop 직접 커밋 금지 규칙 + +## 핵심 원칙 + +1. **secret guard 먼저**: `.env`류 파일, password, api key, secret, token 패턴이 스테이징/변경분에 있으면 즉시 멈추고 알린다. +2. **atomic 단위 분리**: 논리적으로 무관한 변경은 별도 커밋으로 나눈다. +3. **2단계 진행**: Phase 1(계획표+승인) → Phase 2(실행). 승인 없이 커밋하지 않는다. +4. **push는 명시적 요청 시에만** 수행한다. + +## Phase 1 — 계획 확인 + +1. `git status`, `git diff`(staged+unstaged), 최근 `git log`로 변경 내용을 파악한다. +2. 현재 브랜치가 `main`/`develop`이면 즉시 중단하고 사용자에게 알린다. +3. **secret guard**: 변경된 파일에서 `.env`류 파일, `password`, `api_key`, `secret`, `token` 패턴을 검색한다. 발견되면 즉시 멈추고 사용자에게 알린다 — 확인 없이 다음 단계로 넘어가지 않는다. +4. 변경 파일들을 도메인/기능/계층 단위로 분류한다. 서로 무관한 변경(예: 의존성 변경 vs 핵심 구현 vs 설정)은 별도 커밋으로 나눈다. +5. 각 그룹마다 `docs/conventions/commit.md` 형식(`{타입}: {메시지}`)의 커밋 메시지 초안을 작성한다. +6. 아래 형식으로 계획표를 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +``` +## 커밋 계획 + +### 커밋 1: feat: 소셜 로그인 컴포넌트 추가 +- apps/client/src/pages/login/components/SocialLogin.tsx + +### 커밋 2: chore: turbo filter 스크립트 추가 +- package.json + +계속 진행할까요? +``` + +## Phase 2 — 실행 + +1. 승인된 각 그룹만 순서대로 `git add {파일명}`으로 스테이징한다 (`git add -A`/`git add .` 금지, 파일명을 지정한다). +2. 그룹별로 승인된 메시지로 커밋한다. +3. `git log --oneline -n {커밋 수}`로 결과를 확인하고 요약 보고한다. + +## 금지 + +- `--no-verify` 사용 금지 (사용자가 요청해도 이유를 먼저 묻는다). +- 스테이징되지 않은 파일을 임의로 전부 `add`하지 않는다. +- `.env`, 인증서, 토큰 파일을 커밋에 포함하지 않는다. +- 승인 없이 커밋을 실행하지 않는다. diff --git a/.agents/skills/git/issue/SKILL.md b/.agents/skills/git/issue/SKILL.md new file mode 100644 index 00000000..d0394391 --- /dev/null +++ b/.agents/skills/git/issue/SKILL.md @@ -0,0 +1,80 @@ +# git/issue + +## 트리거 + +- "이슈 만들어줘" +- "이슈 올려줘" +- "이슈 써줘" +- 새 기능 개발 또는 버그 수정을 시작하기 전 + +인자 없이 실행하면 현재 대화 컨텍스트에서 작업 내용을 추론한다. + +## 참조 + +- `.github/ISSUE_TEMPLATE/{feature,fix,refactor}.yml` → 이슈 제목/라벨/본문 템플릿 (Pinback은 이 3종류만 존재) +- `.agents/skills/git/branch/SKILL.md` → 브랜치 생성은 이 스킬에 위임한다 (중복 구현 금지) + +## Phase 1 — 계획 확인 + +1. 타입을 확인한다: `Feat`(새 기능) / `Fix`(버그) / `Refactor`(리팩터링) 중 하나. 대화 컨텍스트로 추론하고, 애매하면 사용자에게 확인한다. + - Pinback 이슈 템플릿은 이 3종류만 존재한다. `setting`/`chore` 등 나머지 타입은 이슈 없이 바로 `git/branch`로 진행할 수 있다. +2. 제목: 템플릿에 고정된 프리픽스(`[Feat] `/`[Fix] `/`[Refactor] `) + 한국어 요약. +3. 본문: 해당 템플릿의 `Task Description`(필수) / `ETC`(선택) 필드에 맞춰 작성한다. +4. 아래 형식으로 계획표를 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +``` +## 이슈 생성 계획 + +타입: Feat +제목: [Feat] 소셜 로그인 기능 구현 +라벨: 📌 feat +Assignee: @me + +### 본문 미리보기 +--- +### Task Description + +... + +### ETC + +... +--- + +계속 진행할까요? +``` + +## Phase 2 — 이슈 생성 + +```bash +gh issue create \ + --title "[Feat] 소셜 로그인 기능 구현" \ + --body "$(cat <<'EOF' +### Task Description + +... + +### ETC + +... +EOF +)" \ + --label "📌 feat" \ + --assignee "@me" +``` + +생성된 이슈 URL에서 이슈 번호를 추출한다. + +## Phase 3 — 브랜치 생성 + +이슈 번호를 확보했으면 `.agents/skills/git/branch/SKILL.md`의 Phase 1로 이어서 진행한다. 브랜치 네이밍·develop 최신화는 해당 스킬 규칙을 그대로 따른다. + +## 주의사항 + +- assignee는 항상 `@me`. +- `gh` CLI 미인증 시 `gh auth login`을 안내하고 중단한다. +- 같은 이름의 이슈/브랜치가 이미 있으면 사용자에게 알리고 다른 이름을 제안한다. + +## 금지 + +- 사용자 승인 없이 이슈를 생성하지 않는다. diff --git a/.agents/skills/git/pr/SKILL.md b/.agents/skills/git/pr/SKILL.md new file mode 100644 index 00000000..9bf9ca76 --- /dev/null +++ b/.agents/skills/git/pr/SKILL.md @@ -0,0 +1,50 @@ +# git/pr + +## 트리거 + +- "PR 만들어줘" +- "PR 열어줘" +- "이 브랜치로 PR 생성해줘" +- 브랜치 작업이 완료되고 `develop`으로 머지 준비가 된 시점 + +## 참조 + +- `.github/pull_request_template.md` → PR 본문 템플릿 +- `docs/conventions/merge.md` → 병합 방식(squash), approve 조건 +- `docs/conventions/commit.md` → 제목에 쓰는 타입 목록 + +## 핵심 원칙 + +1. **전체 diff 기준**: `develop` 대비 전체 변경을 분석한다. 최신 커밋 하나만 보지 않는다. +2. **제목은 `{Type}(scope): 한국어 요약` 형식** — `docs/conventions/commit.md` 타입 목록을 따른다 (예: `Feat(client): 소셜 로그인 기능 구현`). +3. **근거 기반으로 쓴다**: 실제로 실행·확인한 명령/화면만 적는다. 확인하지 않은 증거를 만들지 않는다. +4. **구현 의도를 설명한다**: 무엇을 바꿨는지는 diff가 대신한다. 왜 이 구조를 택했는지, 어떤 문제를 해결했는지를 적는다. +5. **실제 검증과 계획된 검증을 분리한다**: 실행하지 않은 명령은 통과했다고 쓰지 않는다. +6. **base 브랜치 확인**: 기본값은 `develop`. 다르면 먼저 사용자에게 물어본다. + +## Phase 1 — 계획 확인 + +1. base 브랜치를 확인한다 (기본 `develop`, 다르면 먼저 사용자에게 확인). +2. `git log {base}..HEAD --oneline --reverse`, `git diff {base}...HEAD --stat`, `--name-only`으로 전체 변경사항을 파악한다. +3. 브랜치명에서 이슈번호를 추출하고 관련 이슈 내용을 확인한다. +4. `pnpm check-types`, `pnpm lint`를 실행해 통과 여부를 확인한다. 실패하면 PR 작성 전에 먼저 사용자에게 알리고 진행 여부를 묻는다. +5. `.github/pull_request_template.md` 형식에 맞춰 초안을 작성한다: + - **Related Issues**: 브랜치의 이슈번호로 `close #N` + - **Tasks**: 변경 파일 나열로 끝내지 않는다. 변경 단위(도메인/기능)별로 무엇을·왜 바꿨는지 서술한다. + - **PR Point (To Reviewer)**: 판단이 필요한 구조 선택, 남은 리스크, 의도적으로 제외한 범위, `pnpm check-types`/`pnpm lint` 실행 결과를 적는다. + - **Screenshot**: UI 변경이 있으면 실제로 확인한 화면만 첨부하도록 안내한다 (표로 정리 제안). UI 변경이 없거나 확인하지 않았으면 섹션을 생략한다. +6. 초안을 출력하고 사용자 승인을 기다린다. 승인 없이 Phase 2로 넘어가지 않는다. + +## Phase 2 — 실행 + +1. 필요 시 원격에 브랜치를 push한다. +2. 승인된 제목/본문으로 `gh pr create --base {base}`를 실행한다. +3. 리뷰어는 `review-assign.yml` 워크플로우가 자동 지정하므로 별도로 지정하지 않는다. reviewer/milestone은 사용자가 명시한 경우에만 추가한다. +4. PR URL을 보고한다. + +## 금지 + +- PR을 병합하지 않는다. 병합은 2명 이상 approve 후 사용자가 직접 처리한다. +- force-push로 base 브랜치를 덮어쓰지 않는다. +- 실행하지 않은 명령을 통과했다고 기록하지 않는다. +- 없는 증거(screenshot, 실행 결과 등)를 있는 것처럼 쓰지 않는다. diff --git a/.agents/skills/meta/manage/SKILL.md b/.agents/skills/meta/manage/SKILL.md new file mode 100644 index 00000000..d72e7d6b --- /dev/null +++ b/.agents/skills/meta/manage/SKILL.md @@ -0,0 +1,30 @@ +# meta/manage + +## 트리거 + +- "이거 스킬로 만들어줘" +- "스킬 수정해줘" +- "이 스킬 이제 안 써, 폐기해줘" + +## 참조 + +- `AGENTS.md` → 트리거 → 스킬 매핑 표 + +## 스킬화 기준 + +아래 중 2개 이상 해당해야 새 스킬로 만든다: +- 3번 이상 같은 방식으로 반복 요청됨 +- 순서/절차 실수가 잦음 +- 참조해야 할 문서·파일이 명확함 +- Phase가 자연스럽게 2개 이상으로 나뉨 + +## Phase 1 — 변경 내용 확인 + +추가/수정/폐기 대상과 이유를 확인하고, 어떤 파일이 바뀌는지 계획을 출력해 승인을 받는다. + +## Phase 2 — 실행 + +- **추가**: `.agents/skills/{category}/{name}/SKILL.md`를 생성한다. 컨벤션 원문이 필요하면 `docs/conventions/`에 별도 파일로 만들고, SKILL.md에는 복제하지 않고 경로만 참조한다. +- **수정**: 해당 SKILL.md만 수정한다. +- **폐기**: 파일을 삭제하지 않고 최상단에 `> ⚠️ DEPRECATED — {대체 스킬명} 사용`을 추가한다. +- 위 어떤 경우든 마지막에 `AGENTS.md`의 트리거 표를 동기화한다 (추가/수정 시 행 추가·갱신, 폐기 시 행 제거). diff --git a/.agents/skills/meta/orchestrate/SKILL.md b/.agents/skills/meta/orchestrate/SKILL.md new file mode 100644 index 00000000..e5b72ede --- /dev/null +++ b/.agents/skills/meta/orchestrate/SKILL.md @@ -0,0 +1,25 @@ +# meta/orchestrate + +## 트리거 + +- "커밋하고 PR까지 만들어줘" +- "브랜치 파서 작업하고 PR 열어줘" +- 하나의 요청이 두 개 이상의 스킬 트리거에 걸릴 때 + +## 참조 + +- `AGENTS.md` → 트리거 → 스킬 매핑 표 + +## Phase 1 — 스킬 체인 도출 + +요청을 분석해 실행할 스킬들의 순서를 정한다 (예: `git/branch` → `git/commit` → `git/pr`). + +## Phase 2 — 계획 출력 및 승인 + +도출된 스킬 체인과 각 스킬에서 수행할 작업을 요약해 출력하고, 사용자 승인을 기다린다. + +## Phase 3 — 순차 실행 + +1. 각 스킬의 SKILL.md를 순서대로 Read하고 그 Phase를 그대로 따른다. +2. 각 스킬은 자신의 Phase 1(계획+승인)을 그대로 유지한다 — orchestrate 단계의 승인이 개별 스킬의 승인 게이트를 대체하지 않는다. +3. 한 스킬에서 실패하거나 예상과 다른 상태(블로커)를 만나면 즉시 중단하고 사용자에게 보고한다. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..bcd944af --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,71 @@ +# pinback-client Agent Guide + +Claude Code / Codex 공통 진입점입니다. +규칙 원문은 `docs/`에 있습니다 — 이 파일에 직접 넣지 마세요. + +--- + +## 절대 규칙 + +작업 요청을 받으면 아래 순서를 반드시 지킨다: + +1. 아래 트리거 표에서 요청에 해당하는 스킬을 찾는다. +2. **해당 SKILL.md 파일을 Read 도구로 먼저 읽는다. 읽기 전에 어떤 작업도 시작하지 않는다.** +3. 스킬 파일의 Phase 순서를 그대로 따른다. +4. 트리거가 두 스킬 이상에 걸리면 `meta/orchestrate`로 위임한다. + +--- + +## 저장소 + +- Product: pinback-client — pnpm/turborepo 모노레포 (apps: client, extension, landing / packages: analytics, contracts, design-system 등) +- 도구: Claude Code, Codex +- 스택: TypeScript, React 19, Vite, Storybook, Vitest, Tailwind + +--- + +## 트리거 → 스킬 매핑 + +### git + +| 트리거 | Read 할 파일 | +| ------ | ------------ | +| "이슈 만들어줘", "이슈 올려줘", 새 작업 시작 전 | `.agents/skills/git/issue/SKILL.md` | +| "이슈 #123 브랜치 만들어줘", "브랜치 새로 파줘" | `.agents/skills/git/branch/SKILL.md` | +| "커밋해줘", "지금까지 한 거 커밋해줘", "변경사항 나눠서 커밋해줘" | `.agents/skills/git/commit/SKILL.md` | +| "PR 만들어줘", "PR 열어줘" | `.agents/skills/git/pr/SKILL.md` | + +### code + +| 트리거 | Read 할 파일 | +| ------ | ------------ | +| "컴포넌트 만들어줘", "{이름} 컴포넌트 생성해줘" | `.agents/skills/code/component/SKILL.md` | +| "새 페이지 만들어줘", "{이름} 페이지 스캐폴딩해줘" | `.agents/skills/code/page/SKILL.md` | + +### figma + +| 트리거 | Read 할 파일 | +| ------ | ------------ | +| "이 피그마 디자인 구현해줘", "피그마 링크 보고 컴포넌트 만들어줘" | `.agents/skills/figma/to-code/SKILL.md` | +| "이 컴포넌트/페이지 피그마로 만들어줘", "이 페이지 디자인 동기화해줘" | `.agents/skills/figma/to-figma/SKILL.md` | + +### meta + +| 트리거 | Read 할 파일 | +| ------ | ------------ | +| 두 개 이상 스킬이 걸리는 복합 요청 | `.agents/skills/meta/orchestrate/SKILL.md` | +| "이거 스킬로 만들어줘", "스킬 폐기해줘" | `.agents/skills/meta/manage/SKILL.md` | + +--- + +## 문서 위치 + +| 내용 | 경로 | +| ---- | ---- | +| 브랜치 네이밍 | `docs/conventions/branch.md` | +| 커밋 메시지 | `docs/conventions/commit.md` | +| 병합·작업 기본 규칙 | `docs/conventions/merge.md` | +| 코딩/네이밍 컨벤션 | `docs/conventions/component.md` | +| 폴더 구조·기술 스택 | `docs/conventions/architecture.md` | +| 피그마 MCP 설정 | `docs/setup/figma-mcp.md` | +| 디자인 토큰 | `docs/design/tokens.md` | diff --git a/docs/conventions/architecture.md b/docs/conventions/architecture.md new file mode 100644 index 00000000..1247cfa6 --- /dev/null +++ b/docs/conventions/architecture.md @@ -0,0 +1,57 @@ +# 폴더 구조 & 기술 스택 + +## 폴더 구조 + +`shared/` 아래 폴더는 전부 common(공통)의 의미로 사용한다. +`pages/` 아래 세부 폴더(components, hooks 등)는 각 페이지에 종속된다. + +``` +Pinback Service +├─ apps +│ ├─ client +│ │ └─ src +│ │ ├─ shared // 공통으로 재사용하는 코드 위치 +│ │ │ ├─ components +│ │ │ ├─ hooks +│ │ │ ├─ utils +│ │ │ ├─ types +│ │ │ └─ ETC +│ │ └─ pages +│ │ ├─ dashBoard +│ │ │ ├─ components +│ │ │ ├─ hooks +│ │ │ ├─ utils +│ │ │ ├─ types +│ │ │ └─ ETC +│ │ └─ detail +│ ├─ extension +│ └─ landing +├─ config // 모노레포 공통 config +│ ├─ eslint +│ └─ typescript +└─ packages // 모노레포 공통 packages (ex. design-system) + └─ design-system +``` + +컴포넌트 폴더명은 camelCase, 폴더 내 컴포넌트 파일명은 PascalCase다 (예: `components/balloon/Balloon.tsx`). + +## 기술 스택 + +| 역할 | 스택 | +| --- | --- | +| UI Library | React | +| Language | TypeScript | +| Styling | Tailwind CSS | +| Data Fetching | Axios | +| Server State Management | TanStack Query | +| UI Test | Storybook | +| Repository Management | Monorepo | +| Build System | Turborepo | +| Formatting | ESLint, Prettier | +| Package Manager | pnpm | +| Version Control | Git, GitHub | +| Deployment (초기 ver1) | Vercel | + +## 관련 규칙 + +네이밍·코드 스타일은 [component.md](./component.md) 참고. diff --git a/docs/conventions/branch.md b/docs/conventions/branch.md new file mode 100644 index 00000000..9924bc0f --- /dev/null +++ b/docs/conventions/branch.md @@ -0,0 +1,26 @@ +# 브랜치 네이밍 컨벤션 + +## 형식 + +`{타입}/#{이슈번호}/{페이지 or 기능 이름}` + +여러 단어가 연결된다면 `-`로 연결한다. + +예시: +- `setting/#1/router-setting` +- `feat/#5/login` +- `fix/#6/register-form-bug-fix` + +타입 목록은 [commit.md](./commit.md) 참고. + +## 브랜치 생성 방법 + +```bash +# 브랜치 생성 + 이동 +# 🚨 develop에서 만들었는지 무조건 확인하기 +$ git checkout -b feat/#{이슈번호}/{기능명} +``` + +## 관련 규칙 + +병합·작업 기본 규칙은 [merge.md](./merge.md) 참고. diff --git a/docs/conventions/commit.md b/docs/conventions/commit.md new file mode 100644 index 00000000..98d3a669 --- /dev/null +++ b/docs/conventions/commit.md @@ -0,0 +1,32 @@ +# 커밋 메시지 컨벤션 + +## 형식 + +`{타입}: {커밋 메시지}` + +예시: +- `feat: login form 구현` +- `refactor: image upload 로직 커스텀훅으로 분리` + +## 타입 목록 + +| 머릿말 | 설명 | +| --- | --- | +| `setting` | 패키지 설치, 개발 설정 | +| `feat` | 새로운 기능 추가 / 퍼블리싱 | +| `fix` | 버그 수정 | +| `api` | api 연결 로직 작성 | +| `refactor` | 프로덕션 코드 리팩토링, QA 반영 | +| `chore` | 빌드 테스트 업데이트, 패키지 매니저 설정 (프로덕션 코드 변경 X) | +| `deploy` | 배포 작업 | +| `comment` | 필요한 주석 추가 및 변경 | +| `test` | 테스트 추가, 테스트 리팩토링 (프로덕션 코드 변경 X) | +| `rename` | 파일 혹은 폴더명을 수정하거나 옮기는 작업만인 경우 | +| `remove` | 파일을 삭제하는 작업만 수행한 경우 | +| `docs` | 문서 수정 | +| `!HOTFIX` | 코드 포맷 변경, 세미콜론 누락, 코드 수정이 없는 경우 | +| `!BREAKING CHANGE` | 커다란 API 변경의 경우 | + +## 관련 규칙 + +브랜치 네이밍은 [branch.md](./branch.md), 병합 규칙은 [merge.md](./merge.md) 참고. diff --git a/docs/conventions/component.md b/docs/conventions/component.md new file mode 100644 index 00000000..47336af6 --- /dev/null +++ b/docs/conventions/component.md @@ -0,0 +1,101 @@ +# 코딩 컨벤션 + +## 기본(Default) 네이밍 + +1. 컴포넌트 / class → `PascalCase` +2. 폴더명 → `camelCase` +3. 파일명 *(컴포넌트 제외)* → `camelCase` +4. 변수, 함수 → `camelCase` +5. 파라미터 → `camelCase` +6. 상수 → `BIG_SNAKE_CASE` + +## 변수 + +- `var` 금지. +- `const` → `let` 순서로 위부터 선언. +- 변수를 조합하여 문자열 생성 시 `+` 금지 → 리터럴(백틱 ``` `` ```) 사용. +- 변수명은 의미를 확실히 나타낼 수 있도록 작성한다. + - 예: 배열에 `Arr`보다는 `fruits`, `userLists` 등. +- 줄임말을 쓰지 않는다. 이름이 길어지더라도 어떤 변수인지 정확하게 표현한다. + - 예: `Btn` X → `Button`으로 사용. +- `map` 사용 시 변동되는 리스트라면 key값을 고유하게 설정한다. **`index` 사용 금지.** + - 서버에서 내려주는 id값 또는 uuid 사용. +- **전역 변수**는 되도록 사용하지 않는다. +- 상수는 영문 대문자 스네이크 케이스로 작성한다: `API_KEY` + +## 함수 + +- 화살표 함수 사용. `function` 키워드 금지. +- 중복 함수는 `utils` 폴더에 모아서 재사용한다. +- 변수/함수명은 20자 미만으로 작성한다. + - 최대한 네이밍에 의미를 담아서 작성하고, 필요 시 주석으로 설명을 추가한다. +- 이벤트 핸들링 함수에는 `handle`을 붙인다. 그 외에는 금지. + - 이벤트 핸들링 함수 예: `onClick`, `onMouseEnter`, `onMouseOut`, `onKeyPress` + - 이벤트 핸들링 함수가 많을 때는 동작까지 포함한다: `handleResetClick`, `handleSubmitClick` +- boolean 관련 함수는 **`is` + 동작**으로 작성한다. 예외적으로 `has` 사용 가능. +- 필요하다면 early return 패턴을 적극적으로 활용한다. + + ```jsx + // early return 패턴 + function processUser(user) { + if (!user || !user.isActive) return; // 조건이 맞지 않으면 일찍 반환 + // 나머지 처리 코드... + } + ``` + +## 컴포넌트 + +- `rafce`(React Arrow Function Component with Export) 형태로 고정한다. +- 의미 없는 `div` 또는 컴포넌트 최상단은 `fragment`를 사용한다. + + ```jsx + const InfoText = () => { + return ( + <> +

Welcome!

+

This our new page, we're glad you're are here!

+ + ); + }; + ``` + +- children이 불필요할 땐 selfClosing을 사용한다: `` +- children을 적극적으로 활용한다. + +## 타입 + +- object → `interface` +- 단일 변수 → type alias +- 컴포넌트 인자에 대한 타입은 컴포넌트 상단에 정의한다. +- 그 외의 타입들은 `types` 폴더에 정의한다. +- swagger 서버가 지원되면 openapi-typescript로 타입 생성을 자동화하는 것도 고려한다. + +## 메소드 + +- 배열 복사 시 스프레드 연산자(`...`)를 사용한다: `const copies = [...originals]` +- `for`보다는 `forEach`/`map`을 사용한다. +- 구조 분해 할당을 적극 이용한다. + + ```tsx + interface UserDataProps { + userName: string; + userBirth: string; + } + + function checkIsUser({ userName, userBirth }: UserDataProps) { + // ... + } + ``` + +- 불필요한 반복문(`filter`, `array.includes()` 등)을 지양한다. + - 조건부로 데이터를 확인·추출하는 로직에는 `Map`이나 `Object`처럼 key값으로 원소를 찾는 자료형을 고려하거나, 배열을 순회하지 않고 index로 바로 접근할 수 있는 방법이 없는지 고려한다. + +## 기타 + +- `button` 태그에는 `type`을 명시적으로 작성한다. +- 비교 연산자는 `===`와 `!==`만 사용한다. +- axios 호출 시 `then`/`catch` 대신 `async`/`await`를 지향한다. + +## 관련 규칙 + +컴포넌트/파일 배치 위치는 [architecture.md](./architecture.md) 참고. diff --git a/docs/conventions/merge.md b/docs/conventions/merge.md new file mode 100644 index 00000000..f14dffd2 --- /dev/null +++ b/docs/conventions/merge.md @@ -0,0 +1,7 @@ +# 브랜치 병합(merge) & 기본 규칙 + +1. 메인 브랜치(`main`, `develop`)에서 직접 커밋하지 않는다. +2. 작업 브랜치(`feat` 등)에서만 커밋하고, 병합은 PR(Pull Request)을 통해서만 한다. + - 병합 방식은 `squash merge`를 사용한다. +3. 작업 전에는 항상 `git pull origin develop`으로 최신화한다. +4. 팀원 리뷰 후 1명 이상의 approve를 받아야 병합할 수 있다. diff --git a/docs/design/tokens.md b/docs/design/tokens.md new file mode 100644 index 00000000..35ee7a1e --- /dev/null +++ b/docs/design/tokens.md @@ -0,0 +1,25 @@ +# 디자인 토큰 + +피그마 디자인에서 추출한 값은 아래 표에 등록된 토큰으로만 매핑한다. 필요한 값이 표에 없으면 hex/px를 하드코딩하지 않고, 먼저 이 표에 토큰을 추가할지 확인한다. + +## Color + +| 토큰 | 값 | 용도 | +| --- | --- | --- | +| _(등록된 토큰 없음)_ | | | + +## Spacing + +| 토큰 | 값 | 용도 | +| --- | --- | --- | +| _(등록된 토큰 없음)_ | | | + +## Typography + +| 토큰 | 값 | 용도 | +| --- | --- | --- | +| _(등록된 토큰 없음)_ | | | + +## 관련 규칙 + +컴포넌트 구현 규칙은 [component.md](../conventions/component.md) 참고. diff --git a/docs/setup/figma-mcp.md b/docs/setup/figma-mcp.md new file mode 100644 index 00000000..c6502f8a --- /dev/null +++ b/docs/setup/figma-mcp.md @@ -0,0 +1,50 @@ +# 피그마 MCP 연동 + +## 개요 + +Figma MCP를 통해 피그마 디자인을 직접 참조하면서 컴포넌트를 구현한다. + +## 설정 + +### 1. Figma Personal Access Token 발급 + +1. Figma → 우측 상단 프로필 → Settings → Security +2. Personal access tokens → `Create new token` +3. 이름 입력 후 토큰 복사 + +### 2. 환경 변수 설정 + +`.env.local`에 추가한다 (커밋 금지, `.gitignore`에 이미 포함됨): + +```text +FIGMA_API_KEY=your_personal_access_token +``` + +### 3. MCP 서버 등록 + +`~/.claude/settings.json`에 추가: + +```json +{ + "mcpServers": { + "figma": { + "command": "npx", + "args": ["-y", "figma-developer-mcp"], + "env": { + "FIGMA_API_KEY": "${FIGMA_API_KEY}" + } + } + } +} +``` + +Codex 등 다른 툴을 쓰는 경우 해당 툴의 MCP 설정 파일에 동일한 서버 정의를 등록한다. + +### 4. 연결 확인 + +세션에서 피그마 파일 URL을 공유하면 MCP가 자동으로 디자인 데이터를 로드한다. + +## 주의사항 + +- Personal Access Token은 절대 커밋하지 않는다. +- 피그마 값이 `docs/design/tokens.md` 토큰 표에 없으면 hex를 하드코딩하지 않고, 토큰 추가 여부를 먼저 확인한다.