명령어 하나로 코드를 수정하고 브랜치를 올리는 AI 에이전트, 어제까지만 해도 완벽하게 돌던 녀석이 오늘 돌연 `Invalid argument`를 내뱉으며 멈춰 선 경험 있으신가요? 사람이 쓰는 CLI 도구를 에이전트에게 그대로 쥐여줬을 때 흔히 겪는 일입니다.
2026년, Claude Code, Gemini CLI, Codex 등 ‘CLI First’ 에이전트가 대세로 자리 잡으면서, 도구를 만드는 기준 자체가 **사람의 편의성(Human DX)**에서 **에이전트의 안정성(Agent DX)**으로 넘어가고 있습니다. “사람이 쓰기 편한 툴”과 “AI가 쓰기 안전한 툴”은 전혀 다릅니다.
이 글에서는 사람이 타이핑하기 좋은 수명 짧은 CLI가 아니라, AI 에이전트가 1만 번을 호출해도 깨지지 않는 ‘Agent DX’ 관점의 CLI 설계 3원칙(JSON, Schema, Dry-run)과 실수 방지 체크리스트를 정리합니다. 내 자동화 스크립트가 왜 자꾸 AI 손에서 망가지는지 궁금하셨다면 이 3가지를 먼저 점검해 보세요.
지금 결론
| 항목 | Human DX (기존) | Agent DX (2026 최신) |
|——|—————–|———————-|
| 입력 방식 | 여러 개의 `–flag` 조합 | 단일 `JSON` 페이로드 |
| 사용법 파악 | `–help` 플래그 (텍스트) | 런타임 `Schema` 조회 (JSON) |
| 안전 장치 | Y/N 프롬프트 확인 | 완벽하게 일치하는 `–dry-run` |
| 결과 출력 | 예쁜 컬러, 테이블 포맷 | 기계가 파싱 가능한 구조화된 `JSON` |
에이전트용 CLI 설계의 핵심은 **”추측을 배제하라”**입니다. 에이전트에게 사람이 읽을 매뉴얼 텍스트를 던져주고 유추하게 만들지 마세요. 기계가 즉각적으로 읽고, 검증하고, 재시도할 수 있는 ‘구조’를 반환하는 것이 Agent DX의 시작입니다.
—
핵심 비교 / 판단 기준: 사람이 편한 것 vs AI가 안전한 것
사람은 오타를 내면 직관적으로 고칩니다. 에이전트는 맥락 창(Context Window) 안에서 과거 기록을 뒤지며 헤매기 시작합니다. Agent DX는 다음과 같은 설계 패러다임의 차이에서 출발합니다.
**1. 파라미터 전달의 복잡성**
**2. 에러의 해석 가능성**
**3. 대화를 통한 확인(Interactive Prompting)**
—
본문 필수 조건 1: 단일 JSON 페이로드 입력
여러 개의 옵션 플래그를 제공하는 것은 에이전트를 혼란스럽게 만듭니다. 2026년 Agent DX의 기본은 모든 입력 값을 단일 JSON 페이로드(Payload) 파일 또는 텍스트로 치환하는 것입니다.
**직접 써보니** 내부 파이프라인에서 7개의 플래그를 조합해야 하는 배포 스크립트를 에이전트에게 위임했습니다. 스크립트가 10번 중 2번 꼴로 이스케이프 오류나 존재하지 않는 옵션 조합 문제를 일으켰습니다. 이를 `–config input.json` 하나로 바꾸고, 에이전트가 JSON 파일만 생성하도록 구조를 바꿨더니 50건의 연속 테스트에서 단 하나의 옵션 오류도 발생하지 않았습니다.
**적용 포인트**
—
본문 필수 조건 2: 런타임 Schema 통신
에이전트가 도구를 호출할 때 `tool description`만 보고 작동 방식을 유추하게 두면 사고가 납니다. CLI 자체에 자신이 받을 수 있는 입력의 ‘스키마(Schema)’를 내뱉는 기능이 있어야 합니다.
**왜 중요한가?** 에이전트가 CLI의 `–schema` 명령어를 호출 시, OpenAPI나 JSON Schema 스펙으로 런타임 구조를 반환하면, 에이전트는 프롬프트 밖에서 스스로 입력 타입을 교정합니다.
“`json
// CLI가 반환하는 스키마 예시
{
“type”: “object”,
“properties”: {
“target_dir”: { “type”: “string”, “description”: “절대 경로만 허용” },
“force”: { “type”: “boolean”, “default”: false }
},
“required”: [“target_dir”]
}
“`
프롬프트에 마크다운 표로 사용법을 구구절절 써놓는 것보다, CLI 자체가 기계어로 자신을 설명(Introspection)하게 만드는 것이 최신의 패턴입니다.
—
본문 필수 조건 3: 완벽한 Parity를 가진 Dry-run
안전 장치 없는 상태 변경(State mutation) 권한을 에이전트에게 주는 것은 시한폭탄과 같습니다. 에이전트는 항상 파괴적인 행동 전에 `–dry-run`을 호출해 영향을 파악해야 합니다.
**실패 포인트** 많은 CLI 도구의 `–dry-run`은 그저 `print(“Will do X”)` 수준의 사람을 위한 텍스트를 출력합니다. 에이전트는 이 텍스트를 보고 실제로 몇 개의 파일이 지워질지 리스크를 정량화하지 못합니다.
**성공적인 Dry-run 설계** `–dry-run`의 출력은 실제 실행 결과의 포맷과 100% 동일(Parity)해야 하며, 상태 코드를 포함한 JSON이어야 합니다.
이 결과를 받아야 에이전트가 스스로 “위험도가 높으니 사용자의 💡승인을 기다리자(Human-in-the-loop)”고 판단할 수 있습니다.
—
실수 TOP 4
**실수 1. 예쁜 컬러와 Progress Bar 적용** — 사람이 보기엔 좋지만, 에이전트가 파싱하려 시도할 때 ANSI 이스케이프 코드는 정규식을 박살 냅니다. 에이전트 환경(예: CI/CD, 비대화형 환경)에서는 반드시 `–no-color`와 `JSON` 출력을 강제하세요.
**실수 2. 에러 텍스트만 뱉고 비정상 종료 안 함** — 로직이 실패했음에도 `exit 0`으로 종료하면서 에러를 단순 텍스트 로그로 남기면, 에이전트는 “실행 성공”으로 간주하고 쓰레기값을 다음 프로세스에 넘깁니다. Semantic exit code(의미론적 종료 코드)를 적극 활용해야 합니다.
**실수 3. 대화형 Y/N 프롬프트 방치** — `–yes` 또는 `–force` 같은 비대화형 플래그를 기본으로 내장하지 않으면, 에이전트의 파이프는 영원히 행(hang) 상태에 빠져 막대한 토큰 낭비와 타임아웃을 초래합니다.
**실수 4. 너무 긴 출력 (Verbose by default)** — 에이전트의 컨텍스트 윈도우 한도를 고려하지 않고 수천 줄의 로그를 쏟아내면, 에이전트의 작업 기억 공간(Working memory)이 포화되어 이후 엉뚱한 결정을 내립니다. 출력은 요약본만 제공하고 상세 내역은 파일 위치(path)로 반환하세요.
—
언제 이 선택이 맞고, 언제 아닌가
**적용해야 할 때 (Agent DX)**
**안 써도 될 때 (Human DX)**
—
FAQ
**Q1. 에이전트용과 사람용 CLI를 두 개 따로 만들어야 하나요?** 아닙니다. 기존 CLI에 `–json` 플래그 하나만 제대로 지원하도록 추가하고, 출력을 구조화하는 형태로 한 도구에서 대응하는 것이 유지보수에 유리합니다.
**Q2. Schema를 꼭 OpenAPI 형태로 제공해야 하나요?** 복잡하게 갈 필요는 없습니다. 단순한 JSON Schema 규격만 지켜도 강력합니다. 핵심은 에이전트가 “이 툴에 어떤 입력이 가능하지?”를 텍스트 매뉴얼이 아닌 명령어 한 줄로 즉시 구조화된 포맷으로 받을 수 있게 만드는 것입니다.
**Q3. 에이전트가 생성한 JSON 입력이 문법적으로 깨지면 어떡하나요?** CLI단에서 JSON 파싱 에러 발생 시, “Invalid JSON at line 3” 같이 힌트가 명확한 에러를 반환하세요. 최신 에이전트들은 에러 메시지를 학습해 곧바로 올바른 JSON으로 수정한 후 스스로 재시도합니다.
**Q4. Dry-run을 구현하기 너무 무거운 작업 아닌가요?** 실제 API 타깃을 치기 전에 멈추고 파라미터만 리턴하도록 래핑(Wrapping)하면 됩니다. Dry-run은 ‘완벽한 시뮬레이션’이 아니라 ‘무엇을 할지’ 의도를 에이전트와 교환하는 영수증 역할을 합니다.
**Q5. MCP(Model Context Protocol)와 이런 CLI 설계는 어떻게 다른가요?** MCP는 저장소를 읽거나 상태를 확인하는 ‘안전한 Read’에 주로 쓰입니다. 반면 실제로 시스템 상태를 변경해야 하는 ‘Write/Execute’ 작업은, 리스크 컨트롤(Dry-run)과 구조화된 계약(JSON Schema)을 갖춘 CLI가 여전히 더 확실한 제어 수단입니다. 이 둘은 배타적이지 않으며 상호보완적입니다.
—
참고 자료
—