
2주 동안 7개 프로젝트를 만들면서 계속 같은 질문에 부딪혔다. Claude API를 직접 호출할까, 아니면 Claude Code를 헤드리스 모드로 쓸까. 블로그 자동 발행, 논문 번역, 자막 교정, SNS 콘텐츠 배포까지. 프로젝트마다 선택이 달랐고 그 이유도 제각각이었다.
결론부터 말하면 대부분의 경우 Claude Code 헤드리스를 골랐다. API가 더 나은 상황도 분명히 있지만 "도구를 써야 하는 자동화"에서는 헤드리스 쪽이 압도적으로 편했다. 왜 그랬는지 실제 사례를 놓고 정리해본다.
Claude를 프로그래밍 방식으로 쓰는 방법은 크게 두 갈래다.
Claude API 직접 호출은 HTTP로 messages.create를 보내는 전통적인 방식이다. 요청 파라미터를 세밀하게 제어할 수 있고 스트리밍 응답도 받을 수 있다. 하지만 도구(tool use)를 쓰려면 도구 정의, 호출 처리, 결과 반환 루프를 직접 구현해야 한다.
Claude Code 헤드리스 모드는 claude -p "명령"처럼 CLI를 subprocess로 실행하는 방식이다. Claude Code가 이미 갖고 있는 도구(파일 읽기/쓰기, Bash 실행, MCP 서버 연동)를 그대로 활용할 수 있다. CLAUDE.md 파일로 프로젝트별 규칙을 주입하고 --json-schema로 structured output을 받을 수도 있다.
각 프로젝트의 핵심 요구사항과 그에 따른 선택을 비교해보자.
선택: Claude Code 헤드리스 (서브에이전트)
블로그 글을 쓰고 PayloadCMS에 저장하는 파이프라인이다. 글감 파일을 읽고, Lexical JSON으로 본문을 작성하고, ComfyUI로 이미지를 만들고, MCP를 통해 CMS에 올린다. 이걸 API로 하려면 파일시스템 접근, ComfyUI API 호출, PayloadCMS REST API 호출을 전부 직접 오케스트레이션해야 한다.
Claude Code를 쓰면 이 모든 게 CLAUDE.md 하나에 정의된다. 에이전트가 Read 도구로 글감을 읽고, Bash로 ComfyUI를 제어하고, MCP로 PayloadCMS에 접근한다. 내가 짠 코드는 거의 없다.
선택: Claude Code 서브에이전트 (Sonnet 모델)
"K8s 주제로 글 써줘"라고 말하면 서브에이전트가 프롬프트 가이드를 읽고, 초안을 생성하고, PayloadCMS MCP로 draft를 저장하는 구조다. mcp-remote 패키지로 PayloadCMS의 MCP 엔드포인트에 연결했는데, API 직접 호출이었으면 Lexical JSON 스키마 변환 로직을 별도로 짰어야 한다. MCP를 쓰니 에이전트가 CMS 스키마를 자동으로 이해한다.
선택: Claude Code Agent Teams
museck(블로그), comfy(이미지), postiz(SNS), n8n(워크플로우), homelab(인프라) 5개 에이전트를 팀 리더가 조율하는 구조다. 각 에이전트가 독립된 프로젝트 디렉토리에서 동작하며, 콘텐츠 생성 에이전트에는 Opus를, 인프라 관리에는 Sonnet을 배정했다.
API로 이걸 구현하려면 멀티 에이전트 프레임워크부터 만들어야 한다. Claude Code의 서브에이전트 시스템은 YAML 정의 파일 하나로 모델, 도구, MCP 서버, 작업 디렉토리를 지정할 수 있어서 프레임워크가 필요 없다.
선택: Claude Code 서브에이전트 + Python 스크립트
서브에이전트(Haiku)가 논문 텍스트에서 용어를 추출하고, 메인 에이전트(Opus)가 검수한 뒤 Python 스크립트로 마스터 용어 사전에 병합하는 워크플로우다. 처음에는 서브에이전트가 파일까지 직접 저장하게 했다가 동시 쓰기 충돌로 데이터가 날아갔다. "서브에이전트는 JSON dict만 반환, 파일 I/O는 메인만" 원칙으로 역할을 분리했다.
여기서 핵심은 Scatter-Gather 패턴이다. 대용량 논문을 페이지 범위로 분할해 여러 서브에이전트가 병렬로 용어를 추출하고, 결과를 병합한다. API로도 가능하지만 Claude Code의 서브에이전트 시스템이 이 패턴을 자연스럽게 지원한다.
선택: Claude Code 헤드리스 + FastAPI
Zotero 플러그인에서 PDF를 선택하면 FastAPI 서버가 claude -p "번역해줘" --output-format json --json-schema를 subprocess로 실행해 전체 번역 파이프라인을 돌린다. Claude Code가 CLAUDE.md에 정의된 번역 규칙을 따라 용어 사전 확인, TranslateGemma 호출, 결과 저장까지 알아서 한다.
API를 직접 호출했으면 이 과정을 전부 코드로 짜야 한다. 용어 사전 있는지 확인하고, 없으면 추출하고, 검수하고, CSV 생성하고, 번역 모델 호출하고. Claude Code 헤드리스는 이걸 프롬프트 한 줄로 해결한다.
선택: Claude Code 서브에이전트 (역할 분리)
이 프로젝트에서 배운 교훈이 있다. 하나의 에이전트에 모든 역할을 주면 프롬프트가 복잡해지고 역할 혼동이 생긴다. 서브에이전트는 추출만, 메인은 검수와 실행만 담당하도록 분리했더니 각각의 프롬프트가 단순해졌다. Short-Circuit 패턴으로 용어 사전이 이미 있으면 전체 과정을 스킵하는 최적화도 넣었다.
선택: Claude Code 헤드리스 (--json-schema)
음성 인식 결과를 Claude Code 헤드리스로 교정하는 기능이다. --json-schema로 출력 형식을 강제하고 --system-prompt로 교정 규칙을 분리했다. 여기서 삽질이 있었는데, --max-turns 1로 설정하면 Claude Code가 내부적으로 첫 턴을 소모해서 실제 응답 없이 종료된다. 2로 올려야 정상 동작한다.
또 하나. --json-schema 사용 시 결과가 result 필드가 아니라 structured_output 필드에 들어간다. 문서에 안 나와 있어서 실험으로 알아냈다. 이런 부분이 헤드리스 모드의 단점이다. 문서화가 부족하고 동작이 바뀔 수 있다.
7개 프로젝트를 거치며 나름의 기준이 생겼다.
CLAUDE.md에 워크플로우를 정의하면 에이전트가 따라간다.CLAUDE.md에 코딩 규칙, 배포 절차, API 스키마를 넣으면 매번 프롬프트에 반복할 필요가 없다.CLAUDE.md 로딩 등. 단순 텍스트 변환은 API가 훨씬 빠르다.CLAUDE.md와 도구 정의가 추가되어 토큰 소비가 크다. 대량 처리에서는 API로 필요한 컨텍스트만 보내는 게 경제적이다.--output-format json은 프로세스 종료 시 한 번에 반환한다.API를 쓸 때 가장 번거로운 게 프롬프트 관리다. 시스템 프롬프트를 어디에 저장하고, 버전 관리는 어떻게 하고, 프로젝트마다 다른 규칙은 어떻게 주입하나. Claude Code에서는 CLAUDE.md가 이 역할을 한다. Git으로 버전 관리되고, 프로젝트 디렉토리에 있으니 자동으로 로딩된다. 프롬프트 관리 인프라를 따로 만들 필요가 없다.
논문 번역 프로젝트에서 뼈아프게 배웠다. 서브에이전트에 "용어 추출하고 파일 저장하고 검수도 해줘"라고 시키면 역할 혼동이 생긴다. 특히 여러 서브에이전트가 병렬로 도는 경우 파일 충돌까지 난다. 서브에이전트는 결과 데이터만 반환하게 하고, 파일 I/O와 의사결정은 메인이 담당하는 구조가 안정적이다.
--json-schema는 강력하지만 함정이 있다. --max-turns 기본값이 내부 턴을 고려하지 않고, 결과 필드 이름이 문서와 다를 수 있다. 방어적 파싱은 필수다. structured_output을 먼저 확인하고, 없으면 result를 확인하고, 그래도 없으면 디렉토리를 직접 스캔하는 3단계 폴백을 두는 게 현실적이다.
Claude API와 Claude Code 헤드리스는 경쟁 관계가 아니다. 쓰임새가 다르다. 단순 텍스트 변환이나 대량 처리에는 API가 맞고, 도구를 쓰는 복잡한 파이프라인에는 Claude Code가 맞다.
나한테 결정적이었던 건 MCP 연동과 CLAUDE.md 두 가지다. MCP 서버만 연결하면 에이전트가 외부 시스템을 이해하고 조작할 수 있다는 점, 프로젝트 규칙을 파일 하나에 넣으면 끝이라는 점. 이게 "프레임워크 없이 에이전트를 만드는" 가장 실용적인 방법이었다.
물론 단점도 있다. 문서화가 부족하고 CLI의 undocumented 동작에 삽질하는 시간이 든다. 하지만 직접 API 클라이언트와 도구 실행 루프를 짜는 시간에 비하면 훨씬 적다. 적어도 내 경험에서는 그랬다.