A-ADM Core 방법론의 Claude Code + React/TypeScript 구현 어댑터.
A-JADM이 생성한 openapi.yaml을 시작점으로 프론트엔드 SDLC를 자동화합니다.
A-FADM은 A-JADM의 프론트엔드 확장입니다.
백엔드가 openapi.yaml을 생성한 시점부터 프론트엔드 파이프라인이 시작됩니다.
반복적인 프롬프트 재작성 대신 스킬·계약 파일·슬래시 커맨드로 일관된 React/TypeScript 코드를 생성합니다.
이 문서는 A-ADM Core의 Claude Code + React/TypeScript 구현 어댑터입니다.
방법론 본질(설계 원칙 · 추적성 규칙 · 계약 파일 스키마)은 Core 문서를 참조하세요.
openapi.yaml을 생성한 시점부터 시작합니다. [ A-JADM 백엔드 파이프라인 ]
implement-bc 완료
↓
/gen-openapi → openapi.yaml ← 두 방법론의 연결 지점
↓
[ A-FADM 프론트엔드 파이프라인 시작 ]
원칙의 전체 정의는 A-ADM Core → 설계 원칙을 참조하세요.
A-FADM은 Core 원칙 중 프론트엔드에 해당하는 세 가지를 적용합니다.
백엔드 확정 전에도 초안 openapi.yaml로 병렬 개발 가능.
API 타입 수동 작성 금지. any 타입 사용 금지.
Claude Code 환경에서 ROI 변화.
목적은 컴포넌트 명세 도출.
각 단계는 명확한 입력·산출물·게이트를 가집니다.
fe-prototype은 조건에 따라 선택적으로 실행합니다.
각 스킬은 독립적인 SKILL.md로 구성됩니다.
스킬끼리는 계약 파일로만 소통합니다.
단일 HTML 파일 목업 생성.
핵심 흐름 1~2개 한정.
data-component 속성으로 컴포넌트 경계 표시.
상태 시뮬레이터(로딩/에러/빈 상태) 패널 내장. 검토 후 폐기.
API Contract · 화면 동작 · 상태 처리 · 컴포넌트 분리 · 타입 정의를 fe-component-spec.md에 명문화.
fe-prototype 산출물이 있으면 data-component에서 컴포넌트 분리 초안 자동 추출.
fe-component-spec.md를 유일한 입력으로 받아 컴파일 가능한 TypeScript 스켈레톤 생성.
spec에 없는 컴포넌트는 절대 추가하지 않는다.
/implement-fe step2가 이 구조 위에 API 연동을 추가한다.
4개 값만 변경하면 배포 가능한 프로젝트 설정 파일.
스택·금지 규칙·파일 구조·슬래시 커맨드 정의를 포함.
모든 스킬과 커맨드가 이 파일을 준수한다.
스킬 간 인터페이스를 파일로 명문화합니다.
fe-component-spec.md가 없으면 fe-to-skeleton이 즉시 중단합니다.
UC명세서 + openapi.yaml
↓
prototype-{domain}.html ← fe-prototype 산출 (선택, 검토 후 폐기)
↓ [검토 확정 — data-component 경계 추출]
fe-component-spec.md ← fe-component-spec 산출 (계약 파일)
↓
컴포넌트 스켈레톤 ← fe-to-skeleton (추론 없는 1:1 매핑)
↓
Step1 구조 → Step2 API 연동 → Step3 상태 처리 ← /implement-fe
↓
테스트 스위트 ← /fe-gen-test (명세 1:1 추적)
Claude Code 환경에서 프로토타이핑의 목적은 "재작업 비용 절감"이 아닙니다.
fe-component-spec.md 품질 확보와 이해관계자 소통이 목적입니다.
일반 개발: 프로토타입(1일) + 구현(5일) = 6일 바로 구현(5일) + 재작업(3일) = 8일 → 프로토타입 ROI 명확 Claude Code: 프로토타입(0.5일) + 구현(1일) = 1.5일 바로 구현(1일) + 재작업(0.5일) = 1.5일 → ROI 불명확 — 목적이 달라져야 함
프로토타입이 그럴듯할수록 이해관계자는 "거의 다 됐네"라고 생각한다.
실제 구현은 0%인데 일정 압박이 생긴다.
프로토타입 배너를 항상 표시해 차단.
색상·버튼 위치 같은 시각적 피드백은 쉽게 나오지만, 깊은 요구사항 발견은 어렵다.
프로토타입은 얕은 피드백을 빠르게 수집하는 도구다.
"한 번만 더" 사이클이 반복된다.
검토 횟수를 명시적으로 한정하지 않으면 프로토타이핑 자체가 끝나지 않는다.
최대 2회 검토 후 확정 원칙.
컴포넌트 경계 표시 — 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>
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 사용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/
├── 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 자동 생성
슬래시 커맨드는 A-ADM Core 워크플로를 React/TypeScript 환경에서 실행하는 진입점입니다. A-JADM의 openapi.yaml에서 시작합니다.
CLAUDE.md에 정의된 3개 커맨드가 셋업·구현·테스트를 자동화합니다.
모든 커맨드는 CLAUDE.md와 fe-component-spec.md를 읽어 추론 없이 실행합니다.
CLAUDE.md를 읽어 Vite 프로젝트 생성 · 패키지 설치 · 폴더 구조 · 공통 설정 파일 생성.
최초 1회 실행.
--gen-types로 openapi 타입까지 한 번에 생성.
/setup-fe # 기본 셋업 /setup-fe --gen-types # 셋업 + openapi 타입 생성 /setup-fe --dry-run # 실행 계획만 출력
fe-component-spec.md를 읽어 step1→step2→step3 순서로 구현.
파일 없으면 즉시 중단하고 fe-component-spec 스킬 실행을 안내.
/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-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 타입 생성 # 0단계 — 프로토타이핑 (화면 구조 불확실 + 이해관계자 승인 필요) fe-prototype → prototype-availability.html (검토 후 폐기) fe-prototype → prototype-booking.html (검토 후 폐기) # 1단계 — 컴포넌트 명세 (openapi.yaml + 프로토타입 검토 결과 반영) fe-component-spec availability → fe-component-spec.md (search · availability · detail) fe-component-spec booking → fe-component-spec.md (booking form · confirm) # 2단계 — 스켈레톤 생성 fe-to-skeleton availability → types · api · hooks · components (stub) fe-to-skeleton booking → types · api · hooks · components (stub) # 3단계 — 구현 (도메인 단위) /implement-fe search step1 → SearchPage + DateRangePicker + GuestRoomCounter /implement-fe search step2 → Zustand store (searchCriteria) /implement-fe availability step1 → AvailabilityPage + RoomCard + PackageCard /implement-fe availability step2 → useAvailability (TanStack Query) /implement-fe availability step3 → 로딩 Skeleton · 에러 · 빈 상태 /implement-fe booking step1 → BookingFormPage + BookingSummaryCard /implement-fe booking step2 → useCreateBooking (useMutation) · 409 충돌 처리 /implement-fe booking step3 → BookingConfirmPage # 4단계 — 테스트 /fe-gen-test availability → useAvailability · RoomCard · PackageCard 테스트 /fe-gen-test availability --contract → API mock 계약 테스트 /fe-gen-test booking → useCreateBooking · BookingFormPage 테스트
코드 생성 후 실제로 실행하기 위한 환경 구성 절차입니다.
/setup-fe 커맨드가 대부분을 자동화하며, 수동 개입이 필요한 단계를 명시합니다.
--gen-types 옵션 추가.cp .env.example .env 후 VITE_API_BASE_URL을 실제 백엔드 주소로 변경. # 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 수정
백엔드 openapi.yaml을 TypeScript 타입으로 변환합니다.
이 타입이 모든 컴포넌트의 타입 추론 기반이 됩니다.
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']
npm run dev 실행. 포트 3000. /api/* 요청은 vite.config.ts 프록시를 통해 백엔드로 전달 — 브라우저에서 CORS 발생 없음./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,
}
}
npm run gen:types로 타입 최신화 필수. npm run build로 TypeScript 컴파일 + Vite 번들링. dist/..env.development · .env.production으로 환경별 API 주소 분리. VITE_API_BASE_URL이 실제 서버를 가리킨다.dist/는 순수 정적 파일. # 빌드 전 타입 최신화
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 run dev | 개발 서버 (port 3000, 프록시 포함) | 개발 중 항상 |
npm run build | TypeScript 컴파일 + Vite 번들링 → dist/ | 배포 전 |
npm run preview | 빌드 결과물 로컬 확인 (port 4173) | 배포 전 검증 |
npm run test | Vitest 테스트 실행 | 구현 완료 후, CI |
npm run test:ui | Vitest UI 모드 (브라우저 결과 확인) | 개발 중 |
npm run gen:types | openapi.yaml → src/types/api.d.ts | API 변경 시마다 |
npm run gen:types:watch | openapi.yaml 변경 감지 모드 | API 활발히 변경 중 |