CLAUDE CODE ADAPTER · VERSION 1.4 · APRIL 2026

AI-Driven Frontend Application
Development Methodology

A-ADM Core 방법론의 Claude Code + React/TypeScript 구현 어댑터.
A-JADM이 생성한 openapi.yaml을 시작점으로 프론트엔드 SDLC를 자동화합니다.

6
SDLC 단계
5
Claude Code 스킬
5
계약 파일
3
슬래시 커맨드
A-ADM 시리즈
← A-JADM Java Backend · A-GADM Go Backend · ● A-FADM Frontend · React/TypeScript
← A-JADM (백엔드 방법론)

A-FADM이란

A-FADM은 A-JADM의 프론트엔드 확장입니다.
백엔드가 openapi.yaml을 생성한 시점부터 프론트엔드 파이프라인이 시작됩니다.
반복적인 프롬프트 재작성 대신 스킬·계약 파일·슬래시 커맨드로 일관된 React/TypeScript 코드를 생성합니다.

A-ADM CORE 참조

이 문서는 A-ADM CoreClaude Code + React/TypeScript 구현 어댑터입니다.
방법론 본질(설계 원칙 · 추적성 규칙 · 계약 파일 스키마)은 Core 문서를 참조하세요.

A-ADM Core 보기 → 이 어댑터 고유 내용: openapi.yaml 연동 · React/TS 고정 스택 · 프로토타이핑 ROI 분석
계약
파일 기반 스킬 연결
추론
제거 — 명세가 결정
선택
프로토타입 조건부 실행
추적
명세 1:1 테스트

A-JADM과의 연결 구조

A-FADM은 A-JADM의 /gen-openapi 커맨드가 openapi.yaml을 생성한 시점부터 시작합니다.
백엔드 팀이 API 명세를 확정하기 전에도 openapi.yaml 초안을 기반으로 프론트엔드 파이프라인을 병렬로 진행할 수 있습니다.
[ A-JADM 백엔드 파이프라인 ]
implement-bc 완료
    ↓
/gen-openapi → openapi.yaml   ← 두 방법론의 연결 지점
    ↓
[ A-FADM 프론트엔드 파이프라인 시작 ]

세 가지 핵심 축

스킬 (Skill)
재사용 가능한 프롬프트 모듈
SKILL.md 오케스트레이터 구조.
layout-prototype → fe-prototype → fe-component-spec → fe-to-skeleton 네 스킬이 순서대로 실행되며 각 산출물이 다음 스킬의 입력이 된다.
계약 파일 (Contract)
스킬 간 인터페이스
openapi.yaml · prototype-layout.html · fe-screen-spec.md · fe-ui-patterns.md · fe-component-spec.md · DESIGN.md.
스킬이 서로를 직접 호출하지 않고 파일로 소통.
fe-component-spec.md가 없으면 fe-to-skeleton이 즉시 중단.
fe-screen-spec.md는 fe-component-spec Step 0에서 자동 역추출 — 개발자 친화적 콘텐츠 명세.
DESIGN.md는 외부 제공 — layout-prototype·fe-prototype(Silent) · /implement-fe(Soft gate) 참조.
fe-ui-patterns.md는 CRUD 인터랙션 패턴을 정의 — 모든 도메인 화면에 일관 적용.
슬래시 커맨드
자동화 실행 단위
CLAUDE.md에 정의된 /implement-fe · /fe-gen-test.
계약 파일을 읽어 추론 없이 3단계 레이어 순서로 실행.

3대 설계 원칙

원칙의 전체 정의는 A-ADM Core → 설계 원칙을 참조하세요.
A-FADM은 Core 원칙 중 프론트엔드에 해당하는 세 가지를 적용합니다.

① API-Contract First
openapi.yaml이 시작점

백엔드 확정 전에도 초안 openapi.yaml로 병렬 개발 가능.

② Type Safety End-to-End
openapi-typescript 자동 생성

API 타입 수동 작성 금지. any 타입 사용 금지.

③ Prototype as Spec
프로토타입이 명세 역할

Claude Code 환경에서 ROI 변화.
목적은 컴포넌트 명세 도출.

6단계 파이프라인

각 단계는 명확한 입력·산출물·게이트를 가집니다.
layout-prototype은 프로젝트당 1회, fe-prototype은 도메인별 조건부 실행합니다.

DESIGN.md (외부 제공) layout-prototype fe-prototype (선택) → 검토 확정 → fe-component-spec fe-to-skeleton /implement-fe /fe-gen-test
0-L
레이아웃 프로토타이핑 — 프로젝트당 1회
layout-prototype · 앱 Shell 구조 확정 · prototype-layout.html
1
앱 Shell 구조 정의
GNB · 사이드바 · 콘텐츠 영역 · 브레드크럼 · 토스트 위치를 배치한다.
반응형 breakpoint(mobile/tablet/desktop) 기준을 포함한다.
2
라우팅 구조 시각화
메뉴 항목에 data-route 속성으로 경로를 명시한다.
전체 화면 목록과 네비게이션 흐름이 한눈에 보여야 한다.
3
콘텐츠 슬롯 마킹
data-slot="content" 속성으로 도메인 화면이 삽입될 영역을 표시한다.
fe-prototype은 이 슬롯 안에 도메인 화면을 배치한다.
산출물 구조
prototype-layout.html
├── Shell (GNB · Sidebar · Footer)
├── data-route="/..." 라우팅 목록
├── data-slot="content" 콘텐츠 영역
├── data-slot="toast" 토스트 위치
└── 반응형 breakpoint 데모
DESIGN.md 참조 방식 — Silent: DESIGN.md가 있으면 color tokens · typography를 Shell에 적용. 없으면 Tailwind 기본값으로 조용히 진행.
입력: usecases/*.md(전체 화면 목록) + DESIGN.md(선택)
산출: prototype-layout.html
소비자: fe-prototype · /implement-fe(Shell 컴포넌트 참조)
0-D
도메인 화면 프로토타이핑 — 필수 · 반복 가능
fe-prototype · prototype HTML 생성 · HTML 직접 수정으로 빠른 피드백 루프
1
Shell 템플릿 로드 + 화면 생성
prototype-layout.html의 data-slot="content" 영역에 도메인 화면 삽입.
usecases/*.md + openapi.yaml 기반. 핵심 흐름 1~2개 한정.
2
반복 수정 (HTML 직접 수정)
개발자가 변경을 요청하면 Claude Code가 HTML을 직접 수정하여 즉시 확인.
fe-screen-spec 개입 없이 빠른 피드백 루프. 만족할 때까지 반복.
3
프로토타입 확정 → fe-component-spec 실행
fe-component-spec {domain} 커맨드 실행 = 프로토타입 확정 선언.
Step 0에서 확정된 HTML을 역추출하여 fe-screen-spec.md를 자동 생성.
필수 실행: 모든 도메인에 대해 fe-prototype을 실행한다.
prototype HTML이 fe-component-spec Step 0의 필수 입력이기 때문이다.
간소화 모드: 단순 CRUD는 목록+모달(생성/수정)+삭제 확인만 포함.
1회 생성으로 충분. 복잡한 화면만 반복 검토.
fe-screen-spec 생성 시점: fe-prototype이 아닌 fe-component-spec Step 0에서 역추출.
프로토타입 반복 중에는 fe-screen-spec이 개입하지 않는다.
1
컴포넌트 명세
fe-component-spec · Step 0 역추출 + Step 1~4 구현 명세
0
prototype HTML → fe-screen-spec 역추출 v1.4
확정된 prototype-{domain}.html을 파싱하여 fe-screen-spec.md 자동 생성.
개발자에게 역추출 결과를 보여주고 확인. 이 커맨드 실행 = 프로토타입 확정 선언.
1
fe-screen-spec + openapi 입력 수집
fe-screen-spec에서 레이아웃·위젯·조건부 표시, openapi에서 엔드포인트·스키마 추출.
widget → shadcn 컴포넌트 매핑. conditional-display → Props 조건 변환.
2
화면 동작 명세화
초기 상태 · 인터랙션(트리거→처리→부작용) · 에러/로딩/빈 상태 처리를 모두 명문화.
추론 없는 구현의 기반.
3
품질 게이트 통과
10개 항목 체크 후 진행.
하나라도 누락이면 해당 항목 보완 후 진행.
품질 게이트 10항목
□ fe-screen-spec의 모든 screen이 반영됐는가
□ 모든 widget이 shadcn 컴포넌트로 매핑됐는가
□ conditional-display가 Props 조건으로 변환됐는가
□ navigation이 이벤트 핸들러로 변환됐는가
□ 모든 API 응답 타입이 TypeScript로 정의됐는가
□ 에러 코드별 UI 처리가 명시됐는가
□ 로딩·에러·빈 상태 세 가지가 정의됐는가
□ 컴포넌트 분리 기준과 Props가 정의됐는가
□ 인터랙션이 트리거→처리→부작용 형태인가
□ queryKey가 ['{domain}', params] 형태인가
산출물: fe-screen-spec.md + fe-component-spec.md
2
스켈레톤 생성
fe-to-skeleton · 추론 없는 1:1 매핑 · 컴파일 가능한 껍데기
1
타입 파일 생성 (먼저)
spec의 타입 정의 섹션 → types/{domain}.types.ts.
다른 파일이 참조하므로 반드시 먼저 생성.
2
API stub · 훅 stub 생성
api/{domain}.api.ts (TODO placeholder) · hooks/use{Domain}.ts (enabled: false).
/implement-fe step2에서 채운다.
3
컴포넌트 파일 생성
spec의 컴포넌트 분리 테이블 기반으로 1:1 생성.
mock 데이터 사용, 상태 처리 분기는 TODO 주석.
spec에 없는 컴포넌트는 추가하지 않는다.
생성 순서 (강제)
1. types/{domain}.types.ts
2. api/{domain}.api.ts
3. hooks/use{Domain}*.ts
4. __mocks__/{domain}.mock.ts
5. components/*.tsx
spec에 없는 컴포넌트 추가 금지.
추론 없는 1:1 매핑.
3
구현
/implement-fe · 3단계 레이어 순서 강제
Step 1 — 구조
컴포넌트 파일 생성
타입 정의 확정
mock 데이터 사용
API 연동 없음
DESIGN.md → shadcn 선택 · Tailwind 토큰
Step 2 — API 연동
useQuery/useMutation 구현
queryKey 패턴 적용
axios 함수 구현
openapi 타입 연결
Step 3 — 상태 처리
로딩 Skeleton
에러 toast + 재시도
빈 상태 Empty UI
409 충돌 등 도메인 에러
DESIGN.md → 에러/빈 상태 색상
4
테스트
/fe-gen-test · Vitest + Testing Library · 명세 1:1 추적
hooks
useQuery 파라미터 검증
queryKey 패턴 확인
API mock 계약 테스트
components
렌더링 스냅샷
인터랙션 이벤트
로딩/에러/빈 상태 분기
contract
API mock 응답 계약
타입 일치 검증
에러 핸들링 경로
추적 원칙: fe-component-spec.md의 UI 동작 1개 = Vitest 테스트 케이스 1개.
명세가 없는 동작은 테스트하지 않는다.

5개 스킬 상세

각 스킬은 독립적인 SKILL.md로 구성됩니다.
스킬끼리는 계약 파일로만 소통합니다.

layout-prototype

앱 레이아웃 프로토타이핑 스킬

전체 앱의 Shell 구조를 단일 HTML로 생성한다.
GNB · 사이드바 · 콘텐츠 영역 · 브레드크럼 · 토스트 위치를 배치하고, 메뉴 항목에 data-route로 라우팅 구조를 표현한다.
콘텐츠 영역에 data-slot="content"를 마킹하여 fe-prototype이 삽입할 위치를 지정한다.
프로젝트당 1회 실행.

입력: usecases/*.md(전체 화면 목록) + DESIGN.md(선택) / 산출: prototype-layout.html
DESIGN.md 참조 방식 — Silent: DESIGN.md가 있으면 color tokens · typography · spacing을 Shell에 반영. 없으면 Tailwind 기본값으로 조용히 진행.
금지: React/TS 구조, 도메인 화면 구현 (Shell만 담당), 실제 API 호출
fe-prototype과의 관계: layout-prototype이 Shell을, fe-prototype이 콘텐츠를 담당한다.
입력이 다르고(앱 레벨 vs 도메인 레벨), 실행 빈도가 다르므로(1회 vs N회) 별도 스킬로 분리.
fe-prototype

도메인 화면 프로토타이핑 스킬 — 필수 실행

prototype-layout.html의 Shell 안에 도메인 화면을 배치하는 단일 HTML 파일 목업 생성.
필수 실행 — 모든 도메인에 대해 실행 (단순 CRUD는 간소화 모드).
HTML 직접 수정으로 빠른 피드백 루프. fe-screen-spec 개입 없음.
확정 시점: fe-component-spec {domain} 실행.

입력: prototype-layout.html + usecases/*.md + openapi.yaml(선택) + DESIGN.md(선택)
산출: prototype-{domain}.html (반복 수정 가능 · 확정 후 폐기)
DESIGN.md 참조 방식 — Silent: DESIGN.md가 있으면 color tokens를 반영. 없으면 Tailwind 기본값으로 조용히 진행.
금지: React/TS 구조, 실제 API 호출, 픽셀 퍼펙트 디자인
fe-component-spec

컴포넌트 명세 스킬 Step 0 내장

Step 0: 확정된 prototype HTML에서 fe-screen-spec.md를 역추출 + 개발자 확인.
Step 1~4: fe-screen-spec + openapi.yaml로 fe-component-spec.md 생성.
prototype-{domain}.html이 Hard gate — 미존재 시 중단.

입력: prototype-{domain}.html(Hard gate) + openapi.yaml
산출: fe-screen-spec.md (보존) + fe-component-spec.md (보존)
fe-to-skeleton

스켈레톤 생성 스킬

fe-component-spec.md를 유일한 입력으로 받아 컴파일 가능한 TypeScript 스켈레톤 생성.
spec에 없는 컴포넌트는 절대 추가하지 않는다.
/implement-fe step2가 이 구조 위에 API 연동을 추가한다.

입력: fe-component-spec.md / 산출: types · api · hooks · components
CLAUDE.md

프로젝트 고정 규칙

4개 값만 변경하면 배포 가능한 프로젝트 설정 파일.
스택·금지 규칙·파일 구조·슬래시 커맨드 정의를 포함.
모든 스킬과 커맨드가 이 파일을 준수한다.

설정: name · backend-api-base · openapi-spec · feature-root
계약 파일 스키마와 파이프라인 원칙은 A-ADM Core → 계약 파일을 참조하세요.
A-FADM은 A-JADM의 openapi.yaml을 추가 입력으로 사용합니다.

계약 파일 체계

스킬 간 인터페이스를 파일로 명문화합니다.
fe-component-spec.md가 없으면 fe-to-skeleton이 즉시 중단합니다.

prototype-layout.html
layout-prototype 스킬 산출
Shell 구조 → GNB · 사이드바 · 콘텐츠 · Footer
data-route → 전체 라우팅 경로 목록
data-slot → 콘텐츠·토스트 삽입 위치
반응형 → mobile/tablet/desktop breakpoint
공통 UI → 브레드크럼 · 유저 메뉴 · 알림 영역
생명주기
프로젝트당 1회 생성
Shell 변경 시에만 갱신
구현 단계에서 Shell 컴포넌트의 참조 기준
소비자: fe-prototype · /implement-fe(Shell 참조)
fe-screen-spec.md
fe-component-spec Step 0 자동 역추출 · 도메인별 1개
v1.4 신규
화면 요구사항 (What 수준)
layout → single-column / two-column / wizard / tabs
sections · fields → 화면 영역 · 필드 · 위젯 유형
conditional-display → 조건부 표시 규칙
navigation → 화면 전환 흐름 · post-action
change-log (변경 이력)
date → 변경 일자
change → 주요 결정사항 (프로토타입 반복 중 변경 이력)
개발자 참고용 — 선택 기록 · fe-component-spec 구현 메모에 반영
생명주기
fe-component-spec Step 0에서 역추출
개발자가 확인 (수정 가능)
Step 1~4에서 입력으로 사용
구현 완료 후 보존 (개발자 레퍼런스)
소비자: fe-component-spec Step 1~4 입력 · /implement-fe 콘텐츠 참조(Soft gate)
독자: 사람. 비즈니스 언어로 작성. shadcn/Props/queryKey 등 구현 용어 없음.
openapi.yaml
A-JADM /gen-openapi 산출
paths → API 엔드포인트 목록
schemas → 요청/응답 TypeScript 타입 기반
operationId → axios 함수명 기반
error responses → UI 에러 처리 기준
소비자: fe-component-spec · fe-to-skeleton
fe-component-spec.md
fe-component-spec 스킬 산출
API Contract → 타입·에러 코드 정의
화면 동작 → 인터랙션 1:1 테스트 추적
상태 처리 → 로딩/에러/빈 상태 UI
컴포넌트 분리 → Props · 파일 경로
타입 정의 → openapi import 또는 직접 정의
소비자: fe-to-skeleton · /implement-fe · /fe-gen-test
fe-ui-patterns.md
프로젝트 초기 1회 작성 · 프로젝트 루트 배치
CRUD 인터랙션 패턴
crud-edit-mode → modal / page / inline
목록 패턴 → 페이지네이션 · 필터 · 정렬
모달/페이지 흐름 → 생성·수정·삭제 전환 흐름
폼 검증 → 타이밍 · 에러 표시 위치
공통 UI 처리
토스트 → 위치 · 메시지 패턴 · 지속 시간
로딩 → skeleton / spinner 선택
빈 상태 → 메시지 · 추가 버튼 표시
낙관적 업데이트 → 적용 기준 정의
참조 방식
fe-prototype — Soft gate
CRUD 프로토타입 인터랙션 패턴 적용

fe-component-spec — Soft gate
인터랙션 명세 시 패턴 참조

/implement-fe · /fe-gen-test — Soft gate
구현·테스트 시 패턴 준수
없으면 경고 후 기본 패턴(modal형 CRUD)으로 진행
도메인별 예외: overrides 섹션으로 명시
DESIGN.md
외부 제공 · 프로젝트 루트 배치
포함 내용 (토큰 레벨)
colors → Primary/Secondary/Semantic hex값
typography → 폰트 패밀리 · 타입 스케일
spacing → 간격 스케일 · border-radius
components → shadcn 선택 기준 · 금지 패턴
참조 방식
layout-prototype — Silent
있으면 참조, 없으면 Tailwind 기본값으로 조용히 진행

fe-prototype — Silent
있으면 참조, 없으면 Tailwind 기본값으로 조용히 진행

/implement-fe — Soft gate
없으면 경고 후 기본값으로 진행 (중단하지 않음)

fe-to-skeleton · /fe-gen-test — 비참조
구조/테스트 레이어 — 시각 토큰 무관
SSOT 원칙
DESIGN.md는 시각 토큰의 단일 진실 원천.

fe-component-spec.md는 동작/구조 명세에 집중하며 시각 토큰을 복사하지 않는다.

DESIGN.md 변경 시 fe-component-spec.md 갱신 불필요.
소비자: layout-prototype(Silent) · fe-prototype(Silent) · /implement-fe Step1·Step3

파일 간 흐름

DESIGN.md (외부 제공 · 프로젝트 루트)
       │ Silent 참조                    │ Soft gate 참조
       ↓                               ↓
usecases/*.md (전체 화면 목록)              Step1: shadcn 선택 · Tailwind 토큰
       ↓                               Step3: 에러/빈 상태 색상
prototype-layout.html     ← layout-prototype 산출 (프로젝트당 1회 · Shell 구조)
       ↓ [Shell 템플릿 제공]
fe-ui-patterns.md (프로젝트 초기 1회 작성 · CRUD 인터랙션 패턴)
       ↓ [Soft gate — 없으면 기본 패턴]
usecases/*.md + openapi.yaml
       ↓
fe-prototype {domain}     → prototype-{domain}.html (필수 · 반복 수정 · 확정 후 폐기)
       ↓ 개발자: "이 정도면 됐다"
fe-component-spec {domain}
  ├→ Step 0: prototype HTML → fe-screen-spec.md (역추출 · 확인 · 보존)
  └→ Step 1~4: fe-screen-spec + openapi → fe-component-spec.md (구현 명세)
       ↓
컴포넌트 스켈레톤         ← fe-to-skeleton   (추론 없는 1:1 매핑 · DESIGN.md 비참조)
       ↓
Step1 구조 → Step2 API 연동 → Step3 상태 처리  ← /implement-fe (fe-component-spec + fe-screen-spec 콘텐츠 + DESIGN.md)
       ↓
테스트 스위트             ← /fe-gen-test      (명세 1:1 추적 · DESIGN.md 비참조)

프로토타이핑 — 레이아웃과 도메인 화면

A-FADM의 프로토타이핑은 2단계로 구성됩니다.
layout-prototype이 앱 Shell을 확정한 뒤, fe-prototype이 Shell 안에 도메인 화면을 배치합니다.

Phase 0-L · layout-prototype

Shell 구조 확정

목적 → 전체 앱의 뼈대(GNB · 사이드바 · 콘텐츠 영역) 확정
실행 빈도 → 프로젝트당 1회
입력 → usecases/*.md(전체 화면 목록) + DESIGN.md(선택)
산출 → prototype-layout.html (계약 파일로 보존)
폐기 여부 → 보존 — fe-prototype · /implement-fe가 참조
Phase 0-D · fe-prototype 필수

도메인 화면 검증

목적 → 특정 도메인 화면의 컴포넌트 구조 · 인터랙션 검증
실행 빈도 → 모든 도메인 필수 (반복 수정 가능)
입력 → prototype-layout.html + usecases/*.md + openapi.yaml(선택)
산출 → prototype-{domain}.html (HTML 직접 수정으로 반복)
확정 시점fe-component-spec {domain} 실행 시
폐기 여부 → HTML 폐기 / fe-screen-spec(Step 0 역추출) 보존
분리 이유: Shell 정의와 도메인 화면 정의는 입력이 다르고(앱 레벨 vs 도메인 레벨), 실행 빈도가 다르며(1회 vs N회), 생명주기가 다릅니다(보존 vs 폐기). A-ADM의 "Lean over Comprehensive" 원칙에 따라 별도 스킬로 분리합니다.

Claude Code 환경에서 ROI 변화

구현 비용이 낮아질수록 "재작업 비용 절감" 명분이 약해진다
일반 개발:
  프로토타입(1일) + 구현(5일) = 6일
  바로 구현(5일) + 재작업(3일) = 8일
  → 프로토타입 ROI 명확

Claude Code:
  프로토타입(0.5일) + 구현(1일) = 1.5일
  바로 구현(1일) + 재작업(0.5일) = 1.5일
  → ROI 불명확 — 목적이 달라져야 함

달라진 목적

명세 품질 확보
fe-component-spec.md를 잘 쓰려면 화면 구조가 머릿속에 있어야 한다.
프로토타입이 그 직관을 만든다.
이해관계자 소통
문서보다 화면이 빠르게 피드백을 끌어낸다.
10페이지 명세보다 클릭 가능한 화면이 대화를 만든다.
화면 요구사항 자동 문서화 v1.4
fe-component-spec {domain} 실행 시 Step 0에서 확정된 HTML을 역추출하여 fe-screen-spec.md를 자동 생성.
개발자가 비즈니스 언어로 읽을 수 있는 화면 요구사항 레퍼런스.
프로토타입 반복 중에는 개입하지 않고, 확정 후 1회 생성.

본질적 한계 — 알고 사용할 것

착각 효과

프로토타입이 그럴듯할수록 이해관계자는 "거의 다 됐네"라고 생각한다.
실제 구현은 0%인데 일정 압박이 생긴다.
프로토타입 배너를 항상 표시해 차단.

표면적 피드백

색상·버튼 위치 같은 시각적 피드백은 쉽게 나오지만, 깊은 요구사항 발견은 어렵다.
프로토타입은 얕은 피드백을 빠르게 수집하는 도구다.

수렴 실패

"한 번만 더" 사이클이 반복된다.
검토 횟수를 명시적으로 한정하지 않으면 프로토타이핑 자체가 끝나지 않는다.
최대 2회 검토 후 확정 원칙.

핵심 규칙:
프로토타입 목적을 코드 작성 전에 명시적으로 결정한다.
"이해관계자 승인용 → 버린다" 또는 "컴포넌트 구조 확인용 → 명세에 반영 후 버린다".
목적이 정해지면 어느 수준까지 만들지, 언제 멈출지가 자연스럽게 결정된다.

layout-prototype 핵심 구현 패턴

Shell 구조 + 콘텐츠 슬롯 — fe-prototype이 이 슬롯에 화면을 삽입

<!-- prototype-layout.html -->
<div class="app-shell">
  <nav data-component="GNB">
    <a data-route="/" class="logo">Hotel App</a>
    <a data-route="/search">검색</a>
    <a data-route="/bookings">예약 내역</a>
    <div data-component="UserMenu">...</div>
  </nav>

  <div class="layout-body">
    <aside data-component="Sidebar">
      <a data-route="/availability">객실 조회</a>
      <a data-route="/booking/new">예약하기</a>
      <a data-route="/admin/rooms">객실 관리</a>
    </aside>

    <main data-slot="content">
      <!-- 도메인 화면이 여기에 삽입됨 -->
      <div class="placeholder">
        콘텐츠 영역 (fe-prototype이 채움)
      </div>
    </main>
  </div>

  <div data-slot="toast"
       style="position:fixed;top:16px;right:16px;">
    <!-- 토스트 알림 위치 -->
  </div>
</div>

반응형 breakpoint 데모 — 레이아웃 검증용

<!-- 반응형 규칙 (Tailwind CDN) -->
<style>
  .layout-body {
    display: grid;
    grid-template-columns: 240px 1fr;
  }
  /* tablet */
  @media (max-width: 1024px) {
    .layout-body {
      grid-template-columns: 64px 1fr;
    }
    aside span.label { display: none; }
  }
  /* mobile */
  @media (max-width: 640px) {
    .layout-body {
      grid-template-columns: 1fr;
    }
    aside { display: none; }
  }
</style>

<!-- 레이아웃 시뮬레이터 -->
<div style="position:fixed;bottom:16px;left:16px;
  background:#1F2937;color:white;
  padding:12px;border-radius:8px;z-index:9999;">
  <div>레이아웃 시뮬레이터</div>
  <button onclick="setViewport('mobile')">
    Mobile
  </button>
  <button onclick="setViewport('tablet')">
    Tablet
  </button>
  <button onclick="setViewport('desktop')">
    Desktop
  </button>
</div>

fe-prototype 핵심 구현 패턴

컴포넌트 경계 표시 — fe-component-spec.md의 입력이 된다

<div data-component="RoomCard"
     data-props="room, nights, onBook">
  <!-- RoomCard 내용 -->
</div>

<div data-component="SearchSummaryBar"
     data-props="criteria">
  <!-- SearchSummaryBar 내용 -->
</div>

상태 시뮬레이터 패널 — 이해관계자 검토 시 엣지 케이스 확인

<div style="position:fixed;bottom:16px;right:16px;
  background:#1F2937;color:white;
  padding:12px;border-radius:8px;z-index:9999;">
  <div>상태 시뮬레이터</div>
  <button onclick="setUIState('loading')">로딩</button>
  <button onclick="setUIState('error')">에러</button>
  <button onclick="setUIState('empty')">빈 목록</button>
  <button onclick="setUIState('normal')">정상</button>
</div>
FIXED STACK React 18 TypeScript 5 TanStack Query v5 shadcn/ui + Tailwind openapi-typescript Vitest any 타입 금지

고정 스택 규칙

CLAUDE.md에 선언된 스택과 금지 규칙은 모든 스킬과 커맨드가 따릅니다.
A-JADM의 Lombok 금지 규칙과 동일한 역할입니다.

고정 스택

역할라이브러리
UI 프레임워크React 18 + TypeScript 5
서버 상태TanStack Query v5
클라이언트 상태Zustand
UI 컴포넌트shadcn/ui + Tailwind CSS
API 타입openapi-typescript
HTTP 클라이언트axios
테스트Vitest + Testing Library
라우팅React Router v6

절대 금지 규칙

금지  any 타입 사용
금지  useEffect로 서버 데이터 fetch → TanStack Query 사용
금지  CSS 인라인 style 속성 → Tailwind 클래스 사용
금지  prop drilling 3단 초과 → Zustand store 사용
금지  default export 혼용 → named export 통일
금지  컴포넌트 내 직접 axios 호출 → hooks/ 래퍼로 분리

핵심 코딩 패턴

TanStack Query — queryKey 패턴

// ✅ 올바른 패턴
const { data } = useQuery({
  queryKey: ['orders', { page, status }],
  queryFn: () => orderApi.getList({ page, status }),
})

// ✅ mutation 후 invalidate
const mutation = useMutation({
  mutationFn: orderApi.cancel,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['orders'] })
  },
})

에러·로딩·빈 상태 처리 패턴

// ✅ 올바른 순서
if (isPending) return <OrderListSkeleton />
if (isError) return (
  <ErrorState onRetry={() => refetch()} />
)
if (!data?.content.length) return <EmptyState />

// openapi 타입 사용 패턴
import type { components } from '@/types/api'
type Order = components['schemas']['OrderResponse']
type Summary = Pick<Order, 'orderId' | 'status'>

컴포넌트 파일 구조

src/
├── app/
│   ├── layout/                        # Shell 컴포넌트 (prototype-layout.html 기반)
│   │   ├── AppShell.tsx               # GNB + Sidebar + Content 레이아웃
│   │   ├── GNB.tsx                    # 글로벌 네비게이션 바
│   │   ├── Sidebar.tsx                # 사이드바 네비게이션
│   │   └── Breadcrumb.tsx             # 브레드크럼
│   └── routes.tsx                     # React Router 설정
├── features/
│   └── {domain}/                      # 예: order, availability, booking
│       ├── components/
│       │   ├── {Domain}ListPage.tsx   # 페이지 컴포넌트 (라우팅 진입점)
│       │   ├── {Domain}Card.tsx       # 카드/행 렌더링
│       │   └── {Domain}Form.tsx       # 폼 컴포넌트
│       ├── hooks/
│       │   ├── use{Domain}List.ts     # useQuery 래퍼
│       │   └── use{Domain}Mutation.ts # useMutation 래퍼
│       ├── api/
│       │   └── {domain}.api.ts        # axios 호출 함수
│       ├── types/
│       │   └── {domain}.types.ts      # 로컬 타입 (openapi 타입 re-export)
│       └── fe-component-spec.md       # 계약 파일 (스킬 산출물)
├── shared/
│   ├── components/                    # 공통 UI (Button, Modal 등)
│   ├── stores/                        # Zustand stores
│   └── lib/
│       ├── axios.ts                   # axios 인스턴스
│       └── queryClient.ts             # TanStack Query 클라이언트
└── types/
    └── api.d.ts                       # openapi-typescript 자동 생성
CLAUDE CODE ADAPTER 고유 내용

슬래시 커맨드는 A-ADM Core 워크플로를 React/TypeScript 환경에서 실행하는 진입점입니다. A-JADM의 openapi.yaml에서 시작합니다.

슬래시 커맨드 레퍼런스

CLAUDE.md에 정의된 3개 커맨드가 셋업·구현·테스트를 자동화합니다.
모든 커맨드는 CLAUDE.md와 fe-component-spec.md를 읽어 추론 없이 실행합니다.
/implement-fe는 추가로 DESIGN.md를 Soft gate로 참조합니다.

/setup-fe [--gen-types] [--dry-run]

프로젝트 셋업 커맨드

CLAUDE.md를 읽어 Vite 프로젝트 생성 · 패키지 설치 · 폴더 구조 · 공통 설정 파일 생성.
최초 1회 실행.
--gen-types로 openapi 타입까지 한 번에 생성.

/setup-fe                # 기본 셋업
/setup-fe --gen-types    # 셋업 + openapi 타입 생성
/setup-fe --dry-run      # 실행 계획만 출력
/implement-fe {domain} [step]

도메인 구현 커맨드

fe-component-spec.md를 읽어 step1→step2→step3 순서로 구현.
fe-component-spec.md 없으면 즉시 중단하고 fe-component-spec 스킬 실행을 안내.
DESIGN.md Soft gate: DESIGN.md 없으면 경고 후 Tailwind 기본값으로 진행. Step1(shadcn 선택·Tailwind 토큰) · Step3(에러/빈 상태 색상)에 참조.

/implement-fe order          # 전체 3단계 순차
/implement-fe order step1    # 구조만 (컴포넌트 + 타입)
/implement-fe order step2    # API 연동 (TanStack Query)
/implement-fe order step3    # 상태 처리 (로딩/에러/빈)
/implement-fe order --dry-run  # 생성 파일 목록만 출력
/fe-gen-test {domain} [scope]

테스트 생성 커맨드

fe-component-spec.md의 UI 동작 명세 → Vitest + Testing Library 테스트 생성.
명세 1개 동작 = 테스트 케이스 1개 (1:1 추적).

/fe-gen-test order              # 전체
/fe-gen-test order hooks        # hooks/ 단위 테스트만
/fe-gen-test order components   # 컴포넌트 렌더링만
/fe-gen-test order --contract   # API mock 계약 테스트

전체 커맨드 실행 시퀀스 — 호텔 예약 시스템 예시

# 사전 — 프로젝트 환경 구성 (최초 1회)
/setup-fe --gen-types         → Vite 설치 · 패키지 · 폴더 구조 · openapi 타입 생성

# 사전 — 디자인 시스템 파일 배치 (외부 제공)
DESIGN.md → 프로젝트 루트에 배치 (layout-prototype·fe-prototype·/implement-fe가 참조)

# 0-L단계 — 레이아웃 프로토타이핑 (프로젝트당 1회)
layout-prototype              → prototype-layout.html (Shell 구조 · 라우팅 · 반응형 breakpoint)
                                 (DESIGN.md: Silent 참조 · 계약 파일로 보존)

# 0-D단계 — 도메인 화면 프로토타이핑 (v1.4: 필수 · 반복 가능)
fe-prototype availability     → prototype-availability.html
  [반복: "카드로 바꿔줘" → HTML 직접 수정 → 즉시 확인 → 만족할 때까지]

fe-prototype booking          → prototype-booking.html
  [반복: "위자드 2단계로 줄여줘" → HTML 직접 수정 → 즉시 확인]

# ①단계 — 컴포넌트 명세 (v1.4: Step 0에서 fe-screen-spec 역추출 + 확인)
fe-component-spec availability
  → Step 0: prototype HTML → fe-screen-spec.md (역추출·확인)
  → Step 1~4: fe-screen-spec + openapi → fe-component-spec.md

fe-component-spec booking
  → Step 0: prototype HTML → fe-screen-spec.md (역추출·확인)
  → Step 1~4: fe-screen-spec + openapi → fe-component-spec.md

# ②단계 — 스켈레톤 생성
fe-to-skeleton availability    → types · api · hooks · components (stub · DESIGN.md 비참조)
fe-to-skeleton booking         → types · api · hooks · components (stub · DESIGN.md 비참조)

# ③단계 — 구현 (도메인 단위 · DESIGN.md: Soft gate · prototype-layout.html: Shell 참조)
/implement-fe search step1     → SearchPage + DateRangePicker + GuestRoomCounter (DESIGN.md → shadcn 선택 · 토큰)
/implement-fe search step2     → Zustand store (searchCriteria)
/implement-fe availability step1  → AvailabilityPage + RoomCard + PackageCard (DESIGN.md → shadcn 선택 · 토큰)
/implement-fe availability step2  → useAvailability (TanStack Query)
/implement-fe availability step3  → 로딩 Skeleton · 에러 · 빈 상태 (DESIGN.md → 상태 색상)
/implement-fe booking step1    → BookingFormPage + BookingSummaryCard (DESIGN.md → shadcn 선택 · 토큰)
/implement-fe booking step2    → useCreateBooking (useMutation) · 409 충돌 처리
/implement-fe booking step3    → BookingConfirmPage (DESIGN.md → 상태 색상)

# ④단계 — 테스트
/fe-gen-test availability      → useAvailability · RoomCard · PackageCard 테스트
/fe-gen-test availability --contract  → API mock 계약 테스트
/fe-gen-test booking           → useCreateBooking · BookingFormPage 테스트

실행 환경

코드 생성 후 실제로 실행하기 위한 환경 구성 절차입니다.
/setup-fe 커맨드가 대부분을 자동화하며, 수동 개입이 필요한 단계를 명시합니다.

전제 조건: Node.js 20 LTS 이상, npm 10 이상.
CLAUDE.md의 4개 값(name · backend-api-base · openapi-spec · feature-root)이 채워진 상태에서 실행합니다.
1
프로젝트 초기 셋업
/setup-fe · 최초 1회 실행
1
CLAUDE.md 준비
fe-skill-pipeline의 CLAUDE.md를 프로젝트 루트에 복사.
name · backend-api-base · openapi-spec · feature-root 4개 값 수정.
2
/setup-fe 실행
Vite 프로젝트 생성 → 고정 스택 패키지 설치 → 폴더 구조 생성 → 공통 설정 파일 생성.
openapi.yaml이 준비됐다면 --gen-types 옵션 추가.
3
환경변수 설정 (수동)
cp .env.example .envVITE_API_BASE_URL을 실제 백엔드 주소로 변경.
이 파일은 Git에 커밋하지 않는다.
# CLAUDE.md 4개 값 수정 후
/setup-fe --gen-types

# 생성되는 파일들
src/shared/lib/axios.ts
src/shared/lib/queryClient.ts
src/app/routes.tsx
src/test/setup.ts
src/types/api.d.ts    # --gen-types 시
vite.config.ts
vitest.config.ts
.env.example

# 수동 단계
cp .env.example .env
# VITE_API_BASE_URL 수정
2
openapi-typescript 타입 생성
A-JADM /gen-openapi 완료 후 · API 변경 시마다

백엔드 openapi.yaml을 TypeScript 타입으로 변환합니다.
이 타입이 모든 컴포넌트의 타입 추론 기반이 됩니다.

타입 동기화 원칙: 백엔드 API가 변경되면 npm run gen:types를 먼저 실행합니다.
타입 에러가 변경 영향 범위를 자동으로 알려줍니다.
# 최초 생성
npm run gen:types

# API 변경 감지 모드
npm run gen:types:watch

# 생성된 타입 사용 패턴
import type { components } from '@/types/api'
type Room = components['schemas']['RoomAvailability']
type Booking = components['schemas']['BookingResponse']
3
개발 서버 실행 및 백엔드 연동
Vite dev server · 프록시 · CORS
1
개발 서버 시작
npm run dev 실행. 포트 3000.
/api/* 요청은 vite.config.ts 프록시를 통해 백엔드로 전달 — 브라우저에서 CORS 발생 없음.
2
백엔드 없이 개발 시
msw(Mock Service Worker)로 API를 모킹.
/fe-gen-test --contract가 생성한 핸들러를 개발 환경에서 활성화해 사용.
# 개발 서버 실행
npm run dev  →  http://localhost:3000

# 프록시 동작
브라우저 → localhost:3000/api/rooms
  → Vite 프록시
    → localhost:8080/api/rooms (백엔드)

# vite.config.ts (자동 생성)
proxy: {
  '/api': {
    target: 'http://localhost:8080',
    changeOrigin: true,
  }
}
4
빌드 및 배포
production build · 환경별 .env · 정적 파일 서빙
1
프로덕션 빌드
빌드 전 npm run gen:types로 타입 최신화 필수.
npm run build로 TypeScript 컴파일 + Vite 번들링.
결과물은 dist/.
2
환경별 .env 분리
.env.development · .env.production으로 환경별 API 주소 분리.
프로덕션에서 VITE_API_BASE_URL이 실제 서버를 가리킨다.
3
SPA 라우팅 폴백
dist/는 순수 정적 파일.
Nginx · S3 + CloudFront 어디든 서빙 가능.
SPA 라우팅을 위해 404 → index.html 폴백 설정이 필수.
# 빌드 전 타입 최신화
npm run gen:types

# 프로덕션 빌드
npm run build   →  dist/

# 빌드 결과 로컬 확인
npm run preview  →  http://localhost:4173

# 환경별 .env
.env.development  VITE_API_BASE_URL=http://localhost:8080
.env.production   VITE_API_BASE_URL=https://api.example.com

# Nginx SPA 폴백 (배포 시 필수)
location / {
  try_files $uri $uri/ /index.html;
}

npm scripts 요약

명령어역할실행 시점
npm run dev개발 서버 (port 3000, 프록시 포함)개발 중 항상
npm run buildTypeScript 컴파일 + Vite 번들링 → dist/배포 전
npm run preview빌드 결과물 로컬 확인 (port 4173)배포 전 검증
npm run testVitest 테스트 실행구현 완료 후, CI
npm run test:uiVitest UI 모드 (브라우저 결과 확인)개발 중
npm run gen:typesopenapi.yaml → src/types/api.d.tsAPI 변경 시마다
npm run gen:types:watchopenapi.yaml 변경 감지 모드API 활발히 변경 중