AI Agent

에이전트와 실제로 일하는 법 — 아젠틱 엔지니어링 실무 완전 가이드

cell-devlog 2026. 5. 28. 09:20
반응형

개념은 됐다. 이 글은 Claude Code·Codex로 실제 개발하는 개발자가 매일 부딪히는 구체적인 문제들을 다룬다. CLAUDE.md를 어떻게 써야 에이전트가 내 말을 듣는지, 컨텍스트 창이 꽉 찼을 때 어떻게 대처하는지, 언제 에이전트를 믿고 언제 직접 잡아야 하는지. 바이브 코딩에서 아젠틱 엔지니어링으로 넘어간 개발자들이 실제로 쓰는 패턴 총정리다.


핵심 요약

→ 아젠틱 엔지니어링의 핵심 제약: LLM 성능은 컨텍스트가 채워질수록 저하됨 — 컨텍스트 창은 모든 메시지·파일·커맨드 출력을 담고 있으며, 가득 찰 때 에이전트는 초기 지시를 "잊기" 시작
→ CLAUDE.md에서 가장 흔한 실수: SOLID·KISS·YAGNI 같은 추상적 원칙 나열 — AI는 그 의미를 알지만 구체적으로 매칭할 것이 없음. "외부 API 호출을 항상 try/catch로 감싸고 console.log 대신 프로젝트 레벨 Logger 사용" 같이 즉각적으로 출력에 반영되는 지시가 효과적
→ 최고의 Claude Code 패턴 69개를 정리한 GitHub 리포가 2026년 3월 트렌딩 1위 — 핵심 메시지: "바이브 코딩에서 아젠틱 엔지니어링으로"
→ DHH(Ruby on Rails 창시자)의 에이전트 워크플로우: 빠른 모델(Gemini)과 고성능 모델(Opus)을 병렬 실행, Neovim에서 diff를 실시간 검토 — 250개 대기 PR 중 100개를 90분에 처리
→ 작업 단위는 유저 스토리로 — "모든 상품 목록 기능"과 "새 상품 생성 기능"은 별도 세션. 단일 컨텍스트 창에 맞는 크기로 분해하는 게 핵심
→ 에이전트가 틀렸을 때의 3가지 신호: 불필요한 추상화 추가, 존재하지 않는 라이브러리 사용, 기존 패턴 무시


1. CLAUDE.md — 에이전트가 실제로 따르는 지시 작성법

모든 지시에 적용할 테스트: AI가 이것을 문자 그대로 따랐을 때 내가 원하는 것이 정확히 나오는가? 답이 "경우에 따라 다르다"로 시작한다면, 더 구체적인 지시가 필요하다.

# ❌ 에이전트가 무시하는 CLAUDE.md (추상적 원칙 나열)

## 코딩 원칙
- SOLID 원칙 준수
- 클린 코드 작성
- 적절한 에러 처리
- 좋은 변수명 사용
# ✅ 에이전트가 실제로 따르는 CLAUDE.md (행동 앵커)

## 프로젝트 개요
- Python 3.12, FastAPI 0.115, PostgreSQL 16
- 패키지 매니저: uv (pip 아님 — 절대 pip install 쓰지 말 것)
- 테스트 러너: pytest (unittest 아님)

## CRITICAL 규칙 (절대 위반 금지)
- NEVER: console.log 또는 print() 로깅 — 반드시 `from app.core.logger import logger` 사용
- NEVER: bare `except:` — 반드시 구체적인 예외 타입 명시
- NEVER: os.environ 직접 접근 — 반드시 `from app.core.config import settings` 사용
- NEVER: 테스트 없는 비즈니스 로직 추가

## 코딩 패턴
- 외부 API 호출: 항상 httpx.AsyncClient + timeout=30.0 + retry 3회
- DB 쿼리: 항상 AsyncSession, 절대 동기 Session 쓰지 말 것
- 응답 모델: 항상 Pydantic BaseModel, dict 반환 금지
- 에러 코드: app/constants/errors.py의 ErrorCode enum만 사용

## 디렉토리 구조 (수정 금지 디렉토리)
- /app/core — 절대 수정 금지, 읽기만 가능
- /migrations — alembic이 관리, 직접 수정 금지

## 테스트 작성 규칙
- 파일명: test_{기능명}.py
- 픽스처: conftest.py에 정의, 각 테스트 파일에 중복 금지
- 외부 의존성: 반드시 mock 처리 (실제 DB/API 호출 금지)
# CLAUDE.md 즉각 효과 테스트법
# 아래 두 프롬프트로 A/B 테스트

# A: CLAUDE.md 없이
claude "stripe webhook 핸들러 만들어줘"
→ print()로 로깅, dict 반환, 에러 처리 없음

# B: CLAUDE.md 있을 때
claude "stripe webhook 핸들러 만들어줘"  
→ logger 사용, Pydantic 응답 모델, 구체적 예외 처리
# 차이를 보면 어느 규칙이 효과적인지 바로 알 수 있음

2. 컨텍스트 관리 — 가장 중요한 실무 기술

단일 디버깅 세션이나 코드베이스 탐색만으로 수만 토큰을 생성하고 소모할 수 있다. 컨텍스트가 가득 찰 때 Claude는 초기 지시를 "잊기" 시작하거나 더 많은 실수를 할 수 있다.

# 컨텍스트 창 상태 체크

# 에이전트가 초반 지시를 무시하기 시작하면 컨텍스트 오염 신호
# 주요 증상:
# - CLAUDE.md에 명시된 패턴을 갑자기 안 따름
# - 앞에서 쓴 방식과 다른 방식으로 코드 생성
# - "아까 말했잖아요"가 필요한 상황 반복

# 해결책 1: /compact — 컨텍스트 압축 (핵심만 보존)
/compact
# Claude가 현재 세션의 중요 정보를 요약하고 컨텍스트를 압축
# → 중요한 결정, 미해결 버그, 구현 세부사항 보존
# → 반복적인 도구 출력 등 노이즈 제거

# 해결책 2: 새 세션 시작 + 핵심 컨텍스트 명시 주입
claude "
지금까지 작업:
- /app/api/payments.py 에 Stripe 웹훅 핸들러 구현 완료
- /tests/test_payments.py 에 6개 테스트 작성, 모두 통과
- 다음 할 일: 이 핸들러를 FastAPI 라우터에 등록하고 통합 테스트 추가

계속해서 라우터 등록해줘
"
# .claudeignore — 에이전트가 읽지 않아도 되는 파일 제외

cat > .claudeignore << 'EOF'
# 빌드 산출물 (에이전트가 읽을 필요 없음)
dist/
build/
*.egg-info/

# 의존성 (컨텍스트 낭비)
node_modules/
venv/
.venv/

# 대용량 데이터 파일
*.csv
*.parquet
fixtures/large_*.json

# 에이전트가 건드리면 안 되는 것들
.env
.env.*
*.pem
*.key
EOF

# 효과: 에이전트가 megabytes의 불필요한 파일을 읽지 않음
# → 실제 작업에 컨텍스트 집중
# 서브에이전트로 컨텍스트 격리

# .claude/agents/security-reviewer.md 생성
cat > .claude/agents/security-reviewer.md << 'EOF'
---
name: security-reviewer
description: PR의 보안 취약점 검토 (SQL 인젝션, XSS, 인증 누락 등)
tools: Read, Grep, Glob
model: opus
---
시니어 보안 엔지니어로서 코드를 검토합니다.
OWASP Top 10 기준으로 취약점을 찾습니다.
각 취약점: 위치, 심각도(HIGH/MEDIUM/LOW), 수정 방법을 명시합니다.
EOF

# 사용: 메인 세션 컨텍스트 오염 없이 독립 검토
claude "security-reviewer로 방금 작성한 payments.py 보안 검토해줘"

3. 작업 분해 — 에이전트가 실패하는 진짜 이유

작업 분해에서 중요한 목표는 각 변경사항이 단일 컨텍스트 창에 맞도록 하는 것이다. 유저 스토리를 작업 단위로 사용하는 것이 효과적이다. 유저 스토리가 작성되는 방식이 에이전트에게 작업을 검증하는 자연스러운 방법을 제공한다.

# ❌ 에이전트가 실패하는 큰 덩어리 태스크

"결제 시스템 구현해줘"
→ 너무 모호함
→ 컨텍스트 폭발
→ 중간에 방향 잃음
→ 결과물이 일관성 없음

# ✅ 유저 스토리 단위 분해

작업 1 (별도 세션):
"카드 결제 처리 함수 구현해줘
 AS A: 사용자가
 WANT TO: 신용카드로 결제할 수 있도록
 SO THAT: 구매를 완료할 수 있음
 
 수락 기준:
 - Stripe API로 결제 처리
 - 성공/실패 반환
 - 단위 테스트 포함
 완료 시 테스트 통과 보여줘"

작업 2 (별도 세션):
"웹훅 이벤트 처리 구현해줘
 AS A: 시스템이
 WANT TO: Stripe로부터 결제 상태 업데이트를 받아
 SO THAT: DB 주문 상태가 동기화됨
 
 수락 기준:
 - payment_intent.succeeded 이벤트 처리
 - payment_intent.payment_failed 이벤트 처리
 - 서명 검증 포함
 - 멱등성 보장 (중복 웹훅 안전 처리)"

4. Plan Mode — 프로덕션 코드에서 필수

Plan Mode에서 Claude Code는 의도한 작업 — 수정할 파일, 변경 내용, 순서 — 의 구조화된 계획을 먼저 제시한다. 계획을 검토하고, 질문하고, 접근 방식을 수정하고, 그 다음에만 실행을 승인한다.

# Plan Mode 활성화
claude --plan "payments.py 리팩토링해서 retry 로직 추가해줘"

# Claude가 실행 전 제시하는 계획 예시:
"""
계획:
1. payments.py 읽기 → 현재 구조 파악
2. 외부 API 호출 3곳 식별:
   - stripe.PaymentIntent.create (line 45)
   - stripe.PaymentIntent.confirm (line 78)  
   - stripe.Refund.create (line 112)
3. 각 호출에 tenacity 라이브러리로 retry 데코레이터 추가
   - 최대 3회 재시도
   - 지수 백오프 (1s, 2s, 4s)
   - stripe.error.RateLimitError, stripe.error.APIConnectionError만 재시도
4. 기존 테스트 실행 → 통과 확인
5. retry 실패 케이스 테스트 추가

진행할까요?
"""

# ← 여기서 판단: "line 78은 건드리면 안 됨" 같은 수정 가능
# 계획 검토 후 승인해야 실행 시작
# Plan Mode 사용해야 할 때 vs 생략해도 될 때

Plan Mode 필수
→ 여러 파일을 동시에 수정하는 리팩토링
→ DB 스키마 변경
→ 인증/보안 관련 코드
→ 처음 보는 레거시 코드베이스
→ 아키텍처 변경

Plan Mode 생략 가능
→ 새 파일 단독 생성
→ 테스트 추가
→ 문서 작성
→ 이미 여러 번 검증된 반복적 패턴

5. 에이전트 출력물 검토 — 무엇을 어떻게 보는가

# 에이전트 출력물에서 반드시 확인해야 할 것들

# ──────────────────────────────────────────
# 🔴 즉시 거부해야 할 패턴

# 1. 존재하지 않는 라이브러리
import nonexistent_library  # pip install 해봐야 404
# → 에이전트가 없는 라이브러리를 자신있게 쓰는 경우 있음

# 2. 마법 같은 에러 처리
try:
    result = external_api_call()
except Exception:
    pass  # ← 에러를 삼켜버림, 절대 안 됨
    
# 3. 테스트가 항상 통과하는 가짜 구현
def get_user(user_id: int):
    return {"id": user_id, "name": "test"}  # 실제 DB 없이 하드코딩

# 4. 불필요한 추상화 추가
class AbstractPaymentProcessorFactory:  # 실제로 필요한가?
    def create_processor(self): ...

# ──────────────────────────────────────────
# 🟡 주의해서 검토해야 할 패턴

# 1. 새로운 의존성 추가
import new_library  # 이 라이브러리가 정말 필요한가? 기존 거로 못 하나?

# 2. 기존 패턴을 무시한 새 패턴
# 프로젝트 전체가 asyncio를 쓰는데 갑자기 threading 사용

# 3. 성능 영향이 있는 쿼리
# N+1 쿼리, 인덱스 없는 컬럼 필터링

# ──────────────────────────────────────────
# ✅ 에이전트가 잘 하는 것 (믿어도 됨)

# 1. 기계적 변환 (타입 추가, 이름 변경, 포맷팅)
# 2. 기존 패턴 반복 (같은 스타일의 새 엔드포인트)
# 3. 테스트 케이스 나열 (경계 조건 발견)
# 4. 보일러플레이트 생성
# 5. 정규식 작성

6. 병렬 에이전트 워크플로우 — DHH 패턴

DHH는 두 모델을 병렬 실행한다 — 빠른 반복을 위한 빠른 모델(Gemini)과 복잡한 추론을 위한 Opus. Neovim에서 diff를 실시간 검토한다. 릴리즈 전 250개 대기 PR 중 100개를 90분에 처리했다.

# Git Worktree로 병렬 에이전트 실행 (파일 충돌 없이)

# 준비: 같은 리포를 여러 워킹 트리로 분리
git worktree add ../feature-auth origin/main
git worktree add ../feature-payments origin/main
git worktree add ../bugfix-api origin/main

# 터미널 3개에서 동시 실행
# 터미널 1
cd ../feature-auth && claude "JWT 인증 미들웨어 구현해줘"

# 터미널 2  
cd ../feature-payments && claude "Stripe 결제 플로우 구현해줘"

# 터미널 3
cd ../bugfix-api && claude "user API의 N+1 쿼리 문제 찾아서 고쳐줘"

# 각 에이전트가 독립적인 파일시스템에서 작업
# → 서로 덮어쓰는 문제 없음
# → 결과 merge는 사람이 검토 후 결정
# Claude Code Agent Teams — 오케스트레이터 패턴

# 복잡한 피처를 오케스트레이터가 서브에이전트에 분배
claude "
이 PR을 분석해줘:
1. security-reviewer 에이전트로 보안 취약점 검토
2. 테스트 커버리지 90% 이상인지 확인
3. 성능 영향 있는 쿼리 있으면 찾아줘
세 작업 동시에 진행하고 결과 합쳐줘
"
# 오케스트레이터가 3개 서브에이전트를 병렬 실행
# → 순차 실행 대비 3배 빠름

7. 실제로 많이 하는 실수와 해결책

# 실수 1: 에이전트에게 모호한 목표 주기

❌ "이 코드 좋게 만들어줘"
✅ "이 함수의 순환 복잡도를 10 이하로 줄이고,
    각 분기를 별도 함수로 추출해줘.
    리팩토링 후 기존 테스트가 모두 통과해야 함"

# 실수 2: 에이전트 출력을 검토 없이 PR에 올리기

❌ 에이전트가 생성 → 바로 git push
✅ 에이전트가 생성 → diff 검토 → 테스트 실행 → PR

# 실수 3: 컨텍스트 오염 무시하기

신호: 에이전트가 CLAUDE.md 규칙을 갑자기 안 따름
❌ 더 구체적인 프롬프트로 재시도 반복
✅ /compact 또는 새 세션 시작

# 실수 4: 에이전트에게 너무 큰 작업 주기

❌ "전체 인증 시스템 구현해줘" (하나의 세션)
✅ 유저 스토리별 분리: 
   세션1: 회원가입 API
   세션2: 로그인 API  
   세션3: JWT 미들웨어
   세션4: 통합 테스트

# 실수 5: 에이전트가 만든 테스트를 테스트하지 않기

❌ pytest → 통과 → 끝
✅ 테스트가 실제로 실패 케이스를 잡는지 확인
   → 의도적으로 구현 코드를 망가뜨려서 테스트가 실패하는지 확인
   → 통과만 하는 가짜 테스트 걸러내기

8. 아젠틱 엔지니어링 데일리 루틴 — 실제 하루 워크플로우

# 아침: 세션 준비

1. CLAUDE.md 확인/업데이트
   → 어제 발견한 새 패턴/규칙 추가
   → "어제 에이전트가 틀린 것" 규칙화

2. 오늘 할 태스크를 유저 스토리로 분해
   → 각 스토리가 1~2시간 단위인지 확인
   → 수락 기준 미리 작성 (에이전트 검증 기준)

# 작업 중: 에이전트 루프

태스크 시작
  ↓
Plan Mode로 계획 확인
  ↓
계획 승인 or 수정
  ↓
에이전트 실행
  ↓
diff 검토 (5~10분)
  ├── 🔴 즉시 거부 패턴 있으면 → 수정 지시
  ├── 🟡 의심스러운 패턴 → 질문해서 확인
  └── ✅ 문제 없으면 → 테스트 실행
  ↓
테스트 통과 확인
  ↓
다음 태스크

# 주의 신호 (즉시 세션 리셋)
- 에이전트가 같은 실수를 3번 이상 반복
- CLAUDE.md 규칙을 무시하기 시작
- 점점 더 복잡한 해결책을 제시

# 저녁: 학습 축적

오늘 에이전트와 해결한 문제 TIL에 기록
→ 내일 CLAUDE.md에 반영
→ 좋은 프롬프트는 prompts/ 디렉토리에 저장

✅ 결론 — 지금 당장 적용할 것 3가지

CLAUDE.md를 오늘 다시 써라 — 추상적 원칙 → 구체적 행동 앵커로 전환
작업을 유저 스토리로 쪼개라 — 에이전트 실패의 80%는 태스크가 너무 큰 것
diff 검토 루틴을 만들어라 — 5분 검토가 2시간 롤백을 막음

❌ 컨텍스트 오염 신호 무시 → 더 많은 프롬프트 추가 금지
❌ 테스트 없는 에이전트 출력 PR 올리기 금지
❌ 에이전트가 생성한 테스트를 검증 없이 신뢰하기 금지


 

관련 글 

 

바이브 코딩은 끝났다 — 아젠틱 엔지니어링 시대의 개발자 생존 전략


https://cell-devlog.tistory.com/294

 

 

반응형