모든 것에 하나의 일반적인 AI 비서를 사용하지 마세요. 완전한 API를 구축하기 위해 5가지 전문 에이전트를 설정하세요: 백엔드 아키텍트는 시스템을 설계하고, 데이터베이스 최적화자는 스키마를 검토하고, 프론트엔드 개발자는 클라이언트를 구축하고, 코드 검토자는 보안을 확인하며, 현실 검증자는 배포 전에 유효성을 검사합니다.
API를 빠르게 구축해야 합니다. 유혹: 하나의 AI에게 모든 것을 요청하는 것. AI는 데이터베이스를 설계하고, 엔드포인트를 작성하고, 프론트엔드를 구축하고, 코드를 검토하고, 결과를 테스트할 것입니다.
발생할 수 있는 일: 데이터베이스에 인덱스가 부족하고, 엔드포인트에 보안 취약점이 있으며, 프론트엔드는 오류 상태를 무시하고, 테스트는 “내 눈에는 괜찮아 보여”로 끝납니다.
전문 에이전트가 이를 해결합니다. 각 에이전트는 자신의 도메인을 알고 있습니다. 각 에이전트에는 체크리스트가 있습니다. 각 에이전트는 특정 결과물을 생성합니다. 백엔드 아키텍트는 확장을 고려합니다. 데이터베이스 최적화자는 누락된 인덱스를 찾아냅니다. 코드 검토자는 취약점을 발견합니다. 현실 검증자는 증거를 요구합니다.
이 튜토리얼에서는 Agency 컬렉션에서 5개의 에이전트를 설정하고 완전한 API 빌드 워크플로우를 실행합니다. API 테스트 및 문서를 위해 Apidog와 통합하여 배포 전에 엔드포인트가 OpenAPI 사양에 대해 유효성 검사되었는지 확인합니다.
사용할 5가지 에이전트
| 에이전트 | 부서 | 책임 |
|---|---|---|
| 백엔드 아키텍트 | 엔지니어링 | API 설계, 데이터베이스 스키마, 인증 |
| 데이터베이스 최적화자 | 엔지니어링 | 인덱스 권장 사항, 쿼리 최적화 |
| 프론트엔드 개발자 | 엔지니어링 | React 컴포넌트, API 클라이언트, 상태 관리 |
| 코드 검토자 | 엔지니어링 | 보안 감사, 타입 안전성, 오류 처리 |
| 현실 검증자 | 테스트 | 증거 기반 유효성 검사, 스크린샷 증명 |
에이전트 설치:
# Clone The Agency repo
git clone https://github.com/msitarzewski/agency-agents.git
cd agency-agents
# Copy agents to Claude Code
cp engineering/engineering-backend-architect.md ~/.claude/agents/
cp engineering/engineering-database-optimizer.md ~/.claude/agents/
cp engineering/engineering-frontend-developer.md ~/.claude/agents/
cp engineering/engineering-code-reviewer.md ~/.claude/agents/
cp testing/testing-reality-checker.md ~/.claude/agents/
단계 1: 백엔드 아키텍트가 시스템 설계
새 Claude Code 세션을 시작합니다:
Activate Backend Architect mode.
Design a REST API for an e-commerce platform with:
- User authentication (JWT with refresh tokens)
- Product catalog with categories and filtering
- Shopping cart management
- Order processing with status tracking
- Payment webhook integration
Output:
1. OpenAPI 3.0 specification
2. PostgreSQL database schema with relationships
3. Project folder structure (Express.js + TypeScript)
4. Authentication flow diagram
예상 결과물:
백엔드 아키텍트의 출력은 다음과 같습니다:
OpenAPI 사양 (일부):
openapi: 3.0.0
info:
title: E-commerce API
version: 1.0.0
paths:
/auth/login:
post:
summary: User login
requestBody:
content:
application/json:
schema:
type: object
properties:
email: { type: string, format: email }
password: { type: string, minLength: 8 }
responses:
'200':
description: JWT tokens
content:
application/json:
schema:
type: object
properties:
accessToken: { type: string }
refreshToken: { type: string }
데이터베이스 스키마:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
category_id UUID REFERENCES categories(id),
inventory_count INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
total_amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(50) DEFAULT 'pending',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
폴더 구조:
src/
├── controllers/
│ ├── auth.controller.ts
│ ├── products.controller.ts
│ └── orders.controller.ts
├── middleware/
│ ├── auth.middleware.ts
│ └── validation.middleware.ts
├── routes/
│ ├── auth.routes.ts
│ ├── products.routes.ts
│ └── orders.routes.ts
├── services/
│ ├── auth.service.ts
│ ├── products.service.ts
│ └── orders.service.ts
├── models/
│ ├── User.ts
│ ├── Product.ts
│ └── Order.ts
└── index.ts
출력을 저장합니다. 다음 에이전트에게 전달할 것입니다.
단계 2: 데이터베이스 최적화자가 스키마 검토
새 세션을 엽니다:
Activate Database Optimizer mode.
Review this PostgreSQL schema for an e-commerce API:
[1단계의 스키마를 붙여넣으세요]
확인 사항:
1. 외래 키 및 자주 쿼리되는 열의 누락된 인덱스
2. 제품 검색(이름, 카테고리, 가격 범위)의 쿼리 성능
3. 데이터 무결성을 위한 적절한 제약 조건
4. 일반적인 전자상거래 기능(리뷰, 위시리스트)의 누락된 테이블
5. 감사 추적을 위한 논리적 삭제(soft delete) 패턴
특정 ALTER TABLE 문과 새 테이블 정의를 출력하세요.
예상 결과물:
인덱스 권장 사항:
-- Add indexes on foreign keys
CREATE INDEX idx_products_category_id ON products(category_id);
CREATE INDEX idx_orders_user_id ON orders(user_id);
-- Add index for product search
CREATE INDEX idx_products_name_search ON products USING gin(to_tsvector('english', name));
CREATE INDEX idx_products_price ON products(price) WHERE inventory_count > 0;
-- Add composite index for category filtering
CREATE INDEX idx_products_category_price ON products(category_id, price);
누락된 테이블:
CREATE TABLE reviews (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID REFERENCES products(id),
user_id UUID REFERENCES users(id),
rating INTEGER CHECK (rating >= 1 AND rating <= 5),
comment TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(product_id, user_id)
);
CREATE TABLE cart_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
product_id UUID REFERENCES products(id),
quantity INTEGER DEFAULT 1 CHECK (quantity > 0),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, product_id)
);
추가할 제약 조건:
-- Email format validation
ALTER TABLE users ADD CONSTRAINT chk_email_format
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
-- Soft delete column
ALTER TABLE products ADD COLUMN deleted_at TIMESTAMP WITH TIME ZONE NULL;
CREATE INDEX idx_products_deleted_at ON products(deleted_at) WHERE deleted_at IS NULL;
이 권장 사항을 스키마에 적용합니다.
단계 3: 프론트엔드 개발자가 클라이언트 구축
새 세션을 엽니다:
Activate Frontend Developer mode.
Build a React dashboard for this e-commerce API:
[1단계의 OpenAPI 사양을 붙여넣으세요]
요구 사항:
- 엄격 모드의 TypeScript
- 서버 상태 관리를 위한 React Query
- 필터(카테고리, 가격 범위, 검색)가 있는 제품 목록
- 실시간 업데이트가 가능한 장바구니
- 상태 추적이 가능한 주문 내역
- 적절한 오류 처리 및 로딩 상태
- 반응형 디자인 (모바일, 태블릿, 데스크톱)
출력:
1. 프로젝트 설정 (Vite + React + TypeScript)
2. React Query 훅을 사용하는 API 클라이언트
3. 핵심 컴포넌트 (ProductList, ProductCard, Cart, OrderHistory)
4. 오류 경계(Error boundary) 및 로딩 스켈레톤(loading skeletons)
예상 결과물:
API 클라이언트:
// src/lib/api-client.ts
import { QueryClient, useQuery, useMutation } from '@tanstack/react-query';
const API_BASE = 'http://localhost:3000/api';
async function fetcher<T>(endpoint: string, options?: RequestInit): Promise<T> {
const response = await fetch(`${API_BASE}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Request failed');
}
return response.json();
}
export function useProducts(filters?: ProductFilters) {
const params = new URLSearchParams(filters as Record<string, string>);
return useQuery({
queryKey: ['products', filters],
queryFn: () => fetcher<Product[]>(`/products?${params}`),
});
}
export function useAddToCart() {
return useMutation({
mutationFn: (item: CartItem) =>
fetcher<CartItem>('/cart', {
method: 'POST',
body: JSON.stringify(item),
}),
});
}
제품 목록 컴포넌트:
// src/components/ProductList.tsx
import { useProducts } from '@/lib/api-client';
import { ProductCard } from './ProductCard';
import { FilterSidebar } from './FilterSidebar';
import { Skeleton } from './ui/skeleton';
export function ProductList() {
const [filters, setFilters] = useState<ProductFilters>({});
const { data: products, isLoading, error } = useProducts(filters);
if (error) {
return <Alert variant="destructive">{error.message}</Alert>;
}
return (
<div className="flex gap-4">
<FilterSidebar filters={filters} onFilterChange={setFilters} />
<div className="flex-1 grid grid-cols-1 md:grid-cols-3 gap-4">
{isLoading ? (
Array.from({ length: 6 }).map((_, i) => (
<Skeleton key={i} className="h-64" />
))
) : products?.length === 0 ? (
<EmptyState message="No products found" />
) : (
products?.map(product => (
<ProductCard key={product.id} product={product} />
))
)}
</div>
</div>
);
}
오류 경계 (Error Boundary):
// src/components/ErrorBoundary.tsx
export class ErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ hasError: boolean; error: Error | null }
> {
constructor(props: { children: React.ReactNode }) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
render() {
if (this.state.hasError) {
return (
<div className="p-4 bg-red-50 border border-red-200 rounded">
<h2 className="text-lg font-semibold text-red-800">Something went wrong</h2>
<p className="text-red-600">{this.state.error?.message}</p>
<Button onClick={() => window.location.reload()} className="mt-2">
Reload
</Button>
</div>
);
}
return this.props.children;
}
}
단계 4: 코드 검토자가 모든 것을 확인
새 세션을 엽니다:
Activate Code Reviewer mode.
다음 사항에 대해 이 코드베이스를 검토하세요:
1. 보안 취약점:
- SQL 인젝션 위험
- XSS 취약점
- CSRF 보호
- 인증 우회 가능성
2. TypeScript 엄격 모드 준수:
- 암시적 `any` 없음
- 적절한 타입 정의
- `null`/`undefined` 처리
3. 오류 처리 공백:
- 잡히지 않은 프라미스 거부
- 누락된 `try/catch` 블록
- 조용한 실패
[1-3단계의 코드를 붙여넣으세요]
심각도 등급(Critical, High, Medium, Low)과 특정 수정 사항이 포함된 보고서를 출력하세요.
예상 결과물:
보안 보고서:
## 심각한 문제
### 1. 제품 검색의 SQL 인젝션
**위치:** `src/controllers/products.controller.ts:24`
**문제:** 사용자 입력이 SQL 쿼리에 직접 연결됨
```typescript
// VULNERABLE
const query = `SELECT * FROM products WHERE name LIKE '%${search}%'`;
```수정: 매개변수화된 쿼리 사용
const query = 'SELECT * FROM products WHERE name LIKE $1';
await db.query(query, [`%${search}%`]);
```높은 심각도 문제
높은 심각도 문제2. CSRF 보호 누락
2. CSRF 보호 누락위치: src/index.ts문제: 상태 변경 작업에 대한 CSRF 미들웨어 없음 수정: csurf 미들웨어 추가
import csrf from 'csurf';
app.use(csrf({ cookie: true }));
```중간 심각도 문제
중간 심각도 문제3. API 응답의 암시적 Any
3. API 응답의 암시적 Any위치: src/lib/api-client.ts:8문제: fetcher 함수의 제네릭 any 타입 수정: 적절한 타입 제약 조건 추가
async function fetcher<T extends Record<string, unknown>>(
endpoint: string,
options?: RequestInit
): Promise<T> { ... }
```
**타입 안전성 보고서:**
```markdown
## TypeScript 위반 사항
1. `products.controller.ts:45` - 반환 타입 주석 누락
2. `auth.middleware.ts:12` - `catch` 블록의 암시적 `any`
3. `orders.service.ts:78` - 객체가 `undefined`일 수 있음
`tsc --noEmit`을 실행하여 전체 목록을 확인하세요. 배포 전에 수정하세요.
진행하기 전에 수정 사항을 적용하세요.
단계 5: 현실 검증자가 배포 전 유효성 검사
단계 5: 현실 검증자가 배포 전 유효성 검사새 세션을 엽니다:
Activate Reality Checker mode.
이 전자상거래 API는 프로덕션 유효성 검사를 받을 준비가 되었습니다.
필수 현실 검증 프로세스를 실행하세요:
1. 파일 존재 여부 확인
2. 주장된 기능과 실제 코드 교차 참조
3. Playwright 테스트의 스크린샷 증거 요구
4. 성능 지표를 위해 `test-results.json` 검토
Project URL: http://localhost:3000
Test results: ./public/qa-screenshots/test-results.json
출력: 특정 차단 문제와 함께 PASS 또는 NEEDS WORK.
예상 결과물:
현실 검증 명령어:
# 1. Verify files exist
ls -la src/controllers/ src/services/ src/routes/
ls -la src/components/ src/lib/
# 2. Cross-reference claimed features
grep -r "jwt\|jsonwebtoken" . --include="*.ts" || echo "NO JWT FOUND"
grep -r "bcrypt\|argon2" . --include="*.ts" || echo "NO PASSWORD HASHING FOUND"
grep -r "rateLimit\|express-rate-limit" . --include="*.ts" || echo "NO RATE LIMITING FOUND"
# 3. Run Playwright screenshot capture
npx playwright test --config=qa-playwright.config.ts --grep "@screenshot"
# 4. Review test results
cat public/qa-screenshots/test-results.json
유효성 검사 보고서:
## 현실 검증 결과
### 파일 검증: PASS
- 모든 컨트롤러 파일 존재
- 모든 컴포넌트 파일 존재
### 기능 검증: NEEDS WORK
- JWT 인증: 발견
- 비밀번호 해싱: 발견
- Rate limiting: 발견되지 않음 (차단)
### 스크린샷 증거: NEEDS WORK
- 데스크톱 레이아웃: PASS
- 태블릿 레이아웃: PASS
- 모바일 레이아웃: FAIL (375px에서 제품 그리드 깨짐)
### 성능 지표: NEEDS WORK
- 평균 로드 시간: 2.3초 (목표: <1초)
- 콘솔 오류: 3개 (목표: 0개)
- 실패한 네트워크 요청: 1개 (목표: 0개)
## 최종 상태: NEEDS WORK
### 차단 문제:
1. Rate limiting이 구현되지 않음
2. 제품 목록의 모바일 레이아웃 깨짐
3. 수정해야 할 콘솔 오류 3개
4. 로드 시간이 1초 목표를 초과함
### 비차단 문제:
- 주문 내역에 로딩 스켈레톤 추가
- 오류 메시지 개선
차단 문제를 수정하고 현실 검증자를 다시 실행하세요.
워크플로우 요약
워크플로우 요약┌─────────────────────────────────────────────────────────────────┐
│ 백엔드 아키텍트 │
│ → OpenAPI 사양, 데이터베이스 스키마, 폴더 구조 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 데이터베이스 최적화자 │
│ → 인덱스 권장 사항, 누락된 테이블, 제약 조건 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 프론트엔드 개발자 │
│ → React 컴포넌트, API 클라이언트, 오류 처리 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 코드 검토자 │
│ → 보안 감사, 타입 안전성, 오류 처리 공백 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 현실 검증자 │
│ → 증거 기반 유효성 검사, 스크린샷 증명, PASS/FAIL │
└─────────────────────────────────────────────────────────────────┘
병렬 에이전트 실행 (고급)
병렬 에이전트 실행 (고급)총 시간을 줄이기 위해 에이전트를 병렬로 실행하세요:
# Terminal 1: Backend Architect
claude "Activate Backend Architect. Design e-commerce API..."
# Terminal 2: Database Optimizer (wait for schema output)
claude "Activate Database Optimizer. Review this schema..."
# Terminal 3: Frontend Developer (wait for API spec)
claude "Activate Frontend Developer. Build React dashboard..."
# Terminal 4: Code Reviewer (wait for code)
claude "Activate Code Reviewer. Review this codebase..."
# All terminals: Reality Checker (final validation)
claude "Activate Reality Checker. Run mandatory checks..."
병렬 실행을 통해 6-8시간 대신 2-4시간 내에 워크플로우를 완료할 수 있습니다.
구축한 것
구축한 것| 결과물 | 에이전트 | 출력 |
|---|---|---|
| API 설계 | 백엔드 아키텍트 | OpenAPI 사양, 데이터베이스 스키마, 폴더 구조 |
| 스키마 최적화 | 데이터베이스 최적화자 | 인덱스 권장 사항, 추가 테이블, 제약 조건 |
| 프론트엔드 | 프론트엔드 개발자 | React 컴포넌트, API 클라이언트, 오류 경계 |
| 보안 감사 | 코드 검토자 | 취약점 보고서, 타입 안전성 수정 사항 |
| 최종 유효성 검사 | 현실 검증자 | 스크린샷 증거, PASS/FAIL 인증 |
다음 단계
다음 단계API 배포:
연결 풀링을 사용하여 프로덕션 PostgreSQL 설정비밀을 위한 환경 변수 구성상태 확인 엔드포인트 추가모니터링 설정 (Prometheus, Grafana)
워크플로우 확장:
부하 테스트를 위한 성능 벤치마커 에이전트 추가문서화를 위한 기술 작가 에이전트 추가CI/CD 파이프라인을 위한 DevOps 자동화 에이전트 추가
패턴 재사용:
프롬프트를 템플릿으로 저장에이전트 세션을 연결하는 워크플로우 스크립트 생성팀과 공유
5가지 전문 에이전트. 하나의 완전한 API. 일반적인 조언은 없습니다.
이것이 바로 전문화의 힘입니다. 각 에이전트는 자신의 도메인을 알고 있습니다. 각 에이전트에는 체크리스트가 있습니다. 각 에이전트는 특정 결과물을 생성합니다.
이제 당신의 차례입니다: 프로젝트를 선택하고, 에이전트를 활성화하고, 더 빠르게 배포하세요.
핵심 요점
핵심 요점전문 에이전트가 일반 비서보다 우수합니다 — 각 에이전트는 도메인 전문성, 체크리스트, 특정 결과물을 가지고 있습니다.순차적 워크플로우는 품질을 보장합니다 — 백엔드 아키텍트가 설계하고, 데이터베이스 최적화자가 검토하며, 프론트엔드 개발자가 구축하고, 코드 검토자가 감사하며, 현실 검증자가 유효성을 검사합니다.증거 기반 승인은 버그를 방지합니다 — 현실 검증자는 PASS 인증 전에 스크린샷 증명, grep 결과, 성능 지표를 요구합니다.병렬 실행은 총 시간을 단축합니다 — 6-8시간 대신 2-4시간 내에 완료하기 위해 4개의 터미널을 동시에 실행하세요.프롬프트를 템플릿으로 저장 — 프로젝트 전반에 걸쳐 일관된 결과를 위해 동일한 에이전트 활성화를 재사용하세요.
자주 묻는 질문
자주 묻는 질문개발자를 위한 AI 에이전트는 무엇인가요?AI 에이전트는 도메인 전문 지식을 갖춘 전문 AI 비서입니다. 일반적인 챗봇과 달리 백엔드 아키텍트나 코드 검토자와 같은 에이전트는 특정 체크리스트를 가지고 일관된 결과물을 생성합니다.
The Agency의 에이전트를 어떻게 설치하나요?`github.com/msitarzewski/agency-agents`에서 리포지토리를 복제한 다음, Claude Code의 경우 `.md` 파일을 `~/.claude/agents/`에 복사하거나 다른 도구의 경우 설치 스크립트를 사용하세요.
현실 검증자 에이전트는 무엇인가요?현실 검증자는 증거 기반 QA 에이전트로, 증거 없이는 작업을 승인하지 않습니다. PASS 인증을 주기 전에 스크린샷, grep 결과, 성능 지표를 요구합니다.
여러 에이전트를 병렬로 실행할 수 있나요?네. 여러 터미널을 열고 각 터미널에서 다른 에이전트를 활성화하세요. 출력을 복사하여 전달하거나 MCP 메모리를 사용하여 자동 핸드오프를 할 수 있습니다.
에이전트 간에 컨텍스트를 어떻게 전달하나요?한 에이전트의 출력을 복사하여 다음 에이전트의 입력으로 붙여넣으세요. 자동 핸드오프를 위해서는 MCP 메모리를 사용하여 다음 에이전트가 불러올 수 있는 결과물을 저장하세요.
에이전트가 NEEDS WORK라고 하면 어떻게 해야 하나요?에이전트가 식별한 차단 문제를 수정한 다음 에이전트를 다시 실행하세요. 현실 검증자는 특히 PASS 인증 전에 수정해야 할 사항을 나열합니다.
모든 프로젝트에 5개의 에이전트가 모두 필요한가요?아니요. API 프로젝트의 경우 백엔드 아키텍트와 코드 검토자로 시작하세요. 복잡한 스키마에는 데이터베이스 최적화자를, UI 작업에는 프론트엔드 개발자를, 배포 전에는 현실 검증자를 추가하세요.
