Skip to main content

지난 장에서 다룬 것은 클로드 코드를 어디서 실행할 것인가였다. 이번 장의 질문은 다르다. 클로드 코드를 무엇 속에 넣을 것인가다. 내 터미널에서만 잘 쓰는 단계는 이미 지났다. 이제는 제품 운영, 배치 작업, 사내 도구, 팀용 버튼, 슬랙 봇, 관리용 웹 화면 속에 클로드 코드를 심어야 한다.

이 전환은 생각보다 중요하다. 터미널에서 직접 프롬프트를 치는 동안에는 내가 중심이다. 하지만 SDK와 헤드리스 실행으로 넘어가면 시스템이 중심이 된다. 매일 아침 돌아가는 리뷰 리포트, 에러 로그를 읽고 초안을 만드는 야간 작업, PM이 버튼 하나로 PRD를 기능 태스크로 바꾸는 내부 도구. 이런 것들이 생기면 클로드 코드는 더 이상 "똑똑한 도우미"가 아니라 내 제품의 일부가 된다.

솔로 빌더에게 이 변화는 특히 크다. 사람을 채용하지 않고도, 내가 만든 시스템 안에 작은 디지털 작업자를 심을 수 있기 때문이다.

[6부] SDK로 나만의 에이전트 만들기

[6부] SDK로 나만의 에이전트 만들기

19.1 LangChain/CrewAI 대신 Claude Code SDK를 쓰는 이유

많은 개발자가 자동화를 생각하면 먼저 범용 에이전트 프레임워크를 떠올린다. LangChain, CrewAI, 혹은 직접 만든 오케스트레이터 말이다. 물론 이런 도구들은 유용하다. 하지만 코드 저장소를 읽고, 파일을 고치고, 명령을 실행하고, 세션을 이어가며, 컨텍스트를 관리하는 코딩 에이전트를 만들고 싶다면 이야기가 달라진다.

Claude Code SDK의 핵심 장점은 여기 있다. 이건 단순히 모델 API를 감싼 얇은 포장지가 아니다. Claude Code가 이미 갖고 있는 에이전트 루프, 도구 사용 방식, 컨텍스트 관리, 세션 지속 개념을 그대로 프로그래밍 방식으로 꺼내 쓰게 해준다. 다시 말해, 솔로 빌더가 제일 귀찮아하는 부분을 처음부터 다시 조립하지 않아도 된다.12

쉽게 말하면 이런 차이다. 범용 프레임워크로 시작하면, 내가 직접 "어떤 파일을 읽게 할지", "어떤 시점에 Bash를 허용할지", "대화 상태를 어떻게 이어갈지", "출력을 어떤 형태로 강제할지"를 하나씩 설계해야 한다. 반면 Claude Code SDK 쪽은 이미 코딩 작업에 맞게 조립된 작업대를 빌려 쓰는 느낌에 가깝다.1

특히 솔로 빌더에게는 이게 치명적으로 중요하다. 혼자 일할 때는 우아한 추상화보다, 오늘 저녁 안에 돌아가는 자동화가 더 값지다. 저장소 안에서 코드를 읽고 바꾸는 작업이 주된 목적이라면, 가장 짧은 길로 가는 편이 대개 이긴다.

또 하나 기억할 점이 있다. 이 장에서 말하는 "SDK"는 꼭 화려한 TypeScript나 Python 라이브러리만 뜻하지 않는다. 사실 대부분의 솔로 빌더는 더 단순한 곳에서 시작하는 편이 낫다. 바로 claude -p다. 공식 문서 기준으로 Claude Code는 -p 플래그를 통해 비대화형, 즉 헤드리스 방식으로 실행될 수 있고, 필요하면 Python과 TypeScript 패키지로 더 깊게 통합할 수도 있다.2

순서를 거꾸로 잡으면 일이 어려워진다. 처음부터 "우리 회사만의 AI 오케스트레이션 레이어"를 만들려 하지 말자. 먼저 터미널 명령 하나를 안정적으로 돌리는 것부터 시작하는 편이 훨씬 낫다. 스크립트가 되고, 스크립트가 잡이 되고, 잡이 도구가 되고, 도구가 제품 기능이 된다. 에이전트 시스템은 대개 이런 식으로 자란다.

19.2 헤드리스 모드와 -p 플래그로 배치 작업 돌리기

헤드리스 모드는 말 그대로 화면 없이 Claude Code를 돌리는 방식이다. 대화형 세션을 열지 않고, 프롬프트를 명령줄에서 바로 넘기고, 결과를 표준 출력으로 받고 끝낸다. 사람 손이 아니라 스크립트, CI, 크론, 내부 API가 호출하기 좋은 형태다.2

가장 기본적인 형태는 이렇다.

claude -p "Summarize this project"

이 한 줄이 중요한 이유는, 여기서부터 Claude Code가 "내가 쓰는 도구"에서 "시스템이 부르는 함수"처럼 바뀌기 때문이다.

조금만 더 나가면 구조화된 출력도 받을 수 있다.

claude -p "Summarize this project" --output-format json

이제 결과는 사람이 읽는 문장만이 아니라, 파이프라인이 읽을 수 있는 JSON이 된다. 세션 ID, 메타데이터, 결과 텍스트를 함께 다룰 수 있어서 후속 스크립트 연결이 쉬워진다.2

더 실전적인 패턴은 JSON Schema를 붙이는 것이다.

claude -p "Analyze today's support feedback and extract product issues"   
  --output-format json   
  --json-schema '{
    "type":"object",
    "properties":{
      "issues":{"type":"array","items":{
        "type":"object",
        "properties":{
          "title":{"type":"string"},
          "severity":{"type":"string"},
          "next_action":{"type":"string"}
        },
        "required":["title","severity","next_action"]
      }}
    },
    "required":["issues"]
  }'

이렇게 하면 "그럴듯한 문장"이 아니라 후속 시스템이 바로 쓸 수 있는 정해진 구조를 만들 수 있다.2 솔로 빌더에게 이 차이는 엄청 크다. 그럴듯한 텍스트는 결국 사람이 다시 읽어야 하지만, 구조화된 출력은 데이터베이스에 넣거나 이슈 생성기로 바로 넘길 수 있기 때문이다.

긴 작업에서는 스트리밍도 유용하다. stream-json 형식을 쓰면 생성 중인 이벤트를 실시간으로 받을 수 있다. 콘솔에 진행 상태를 띄우거나, 웹 대시보드에서 "지금 뭘 하고 있는지" 보여주고 싶을 때 아주 편하다.2

claude -p "Review the release diff for risks"   
  --output-format stream-json   
  --verbose   
  --include-partial-messages

그리고 헤드리스 모드는 생각보다 대화형이다. 세션을 한 번 시작한 뒤 --continue나 --resume으로 이어갈 수 있다. 첫 번째 실행에서는 문제를 넓게 훑고, 두 번째 실행에서는 DB 쿼리만 파고들고, 마지막에는 요약만 뽑는 식으로 다단계 배치 작업을 만들 수 있다.2

session_id=$(claude -p "Start a performance review" --output-format json | jq -r '.session_id')
claude -p "Now focus only on database queries" --resume "$session_id"
claude -p "Generate a final summary" --resume "$session_id"

이 패턴이 좋은 이유는 간단하다. 큰 작업을 한 번에 몰아치지 않고, 작은 단계로 나눠서 다시 불러올 수 있기 때문이다. 제품 운영에서는 이게 안전하다. 실패 지점도 분리되고, 재시도도 쉬워진다.

여기서 초보자가 가장 많이 하는 실수는 권한을 너무 크게 여는 것이다. 무심코 모든 확인을 건너뛰는 위험한 실행 방식으로 가기 쉽다. 하지만 대부분의 자동화는 그렇게까지 세게 열 필요가 없다. 보통은 --allowedTools로 필요한 도구만 화이트리스트로 허용하는 편이 훨씬 낫다.2

claude -p "Review staged changes and suggest a commit message"   
  --allowedTools "Bash(git diff *),Bash(git status *),Read"   
  --output-format json

이렇게 하면 에이전트가 할 수 있는 일을 좁혀둘 수 있다. 솔로 빌더의 자동화는 강한 것보다 예측 가능한 것이 더 중요하다.

배치 작업을 실제 운영에 넣을 때는 세 가지 원칙이 거의 필수다.34

  • 실행 한도를 반드시 둔다. 턴 수, 벽시계 시간, 토큰 예산을 제한하지 않으면 밤새 루프를 도는 황당한 사고가 난다.

  • 재실행에 안전하게 만든다. 같은 잡이 두 번 돌았을 때 중복 PR, 중복 리포트, 중복 커밋을 만들지 않도록 프롬프트에 멱등성 조건을 넣는다.

  • 출력은 자연어보다 구조를 우선한다. 사람 눈에는 예쁜 문장보다 JSON Lines와 구조화 로그가 운영에서 훨씬 덜 아프다.

예를 들어 "오늘 리포트가 이미 있으면 성공으로 종료하라"는 문장 하나만 앞에 넣어도, 재실행 사고를 꽤 줄일 수 있다.3

스케줄링은 그다음 문제다. 크론, systemd timer, GitHub Actions 중 뭐든 상관없다. 중요한 건 Claude Code를 정해진 시간에, 정해진 폴더에서, 정해진 권한으로 돌리는 것이다. 크론을 쓸 때는 PATH와 환경 변수가 빈약하므로 전체 경로를 쓰고, 로그를 파일로 남기고, 먼저 터미널에서 같은 명령을 수동으로 검증하는 습관이 좋다.4

솔로 빌더가 바로 써먹기 좋은 배치 작업은 대개 이런 종류다.

  • 매일 아침: 어제 커밋과 운영 로그를 읽고 위험 신호 요약

  • 배포 직후: 변경 diff를 검토하고 롤백 포인트 후보 정리

  • 매주 금요일: 고객 피드백을 기능 요청 초안으로 변환

여기서 중요한 건 거창한 자동화가 아니다. 반복되지만 미루기 쉬운 일을 먼저 빼앗아 오는 것이다. 혼자 만드는 사람은 대개 구현보다 정리, 검토, 후속 문서화에서 진이 빠진다. 헤드리스 모드는 바로 그 잡일을 기계 쪽으로 밀어 넣는 기술이다.

19.3 비개발자를 위한 내부 도구 만들기

이제 한 단계 더 가보자. 배치 작업이 "정해진 시간에 돌아가는 Claude Code"라면, 내부 도구는 "다른 사람이 눌러서 쓰는 Claude Code"다.

여기서 많은 사람이 착각한다. 내부 도구를 만든다고 하면 대시보드부터 떠올린다. 하지만 처음부터 예쁜 관리 화면은 필요 없다. 내부 도구의 본질은 좋은 프롬프트를 안전한 인터페이스 뒤에 숨기는 것이다.

예를 들어 PM이 매번 터미널을 열어 이런 일을 할 필요는 없다.

"이번 주 사용자 피드백 12개를 묶어서 기능 제안 3개로 정리하고, 각 제안에 성공 지표와 우선순위를 붙여줘."

대신 PM은 노션 페이지 URL이나 텍스트를 붙여 넣고 버튼 하나만 누르면 된다. 뒤에서는 서버가 claude -p를 호출하고, 결과는 구조화된 JSON으로 받아서 템플릿에 맞는 문서나 이슈 초안으로 뿌려주면 된다. 이것이 내부 도구다.

좋은 내부 도구는 네 가지 층으로 생각하면 쉽다.

  • 입력면은 사람이 만지는 부분이다. 폼, 슬랙 명령, 웹훅, 관리자 버튼이 여기에 들어간다.

  • 실행면은 Claude Code가 실제로 도는 부분이다. 처음에는 claude -p 래퍼로 충분하고, 더 복잡해지면 Python이나 TypeScript 통합으로 넘어가면 된다.2

  • 출력면은 시스템이 소비할 결과다. 자유문보다 JSON Schema가 유리하고, 최종 표시용으로는 마크다운이나 HTML로 다시 렌더링하면 된다.

  • 통제면은 권한, 로그, 승인 절차다. 읽기 전용으로 시작하고, 쓰기 작업은 반드시 드래프트나 승인 게이트를 두는 편이 좋다.

예를 들어 고객 지원팀용 "피드백 → 기능 요청" 도구를 만든다고 해보자. 화면은 아주 단순해도 된다. 고객 메시지 몇 개를 붙여 넣고 "초안 만들기"를 누르면 끝이다. 뒤에서는 이런 작업이 일어난다.

claude -p "Transform the following customer feedback into product issue drafts. Return only structured output."   
  --output-format json   
  --json-schema '{
    "type":"object",
    "properties":{
      "drafts":{"type":"array","items":{
        "type":"object",
        "properties":{
          "title":{"type":"string"},
          "problem":{"type":"string"},
          "impact":{"type":"string"},
          "acceptance_criteria":{"type":"array","items":{"type":"string"}}
        },
        "required":["title","problem","impact","acceptance_criteria"]
      }}
    },
    "required":["drafts"]
  }'

이 결과를 받아서 GitHub 이슈 초안, Notion 문서 초안, 혹은 슬랙 메시지 카드로 바꾸면 된다. 중요한 건 이때 바로 발행하지 않는 것이다. 사람 검토 후 승인 버튼을 누르게 해야 한다. 내부 도구는 사람을 없애는 기계가 아니라, 사람의 판단이 필요한 지점까지 일을 밀어주는 장치다.

비개발자를 위한 도구를 만들 때는 "기능 수"보다 "반복성"이 더 중요하다. 매일 반복되는 불편 하나를 줄이는 도구가, 가끔 쓰는 거대한 플랫폼보다 훨씬 가치 있다. Claude Code 덕분에 이런 초개인화된 내부 도구의 제작 비용은 아주 많이 낮아졌다. 예전 같으면 한참 고민하다 포기했을 작은 문제들도, 이제는 한두 시간 안에 실제 도구로 바꿔볼 수 있다.5

다만 내부 도구를 만들수록 새로운 문제가 생긴다. 아무도 그 도구가 있는지 모른다는 문제다. 그래서 사내 도구든, 개인 도구든, 저장소 어딘가에 "이 도구는 언제 쓰고, 어떤 입력을 넣고, 어떤 결과가 나오는가"를 적어두는 습관이 필요하다. README든 운영 문서든 CLAUDE.md든 상관없다. 중요한 건 사람과 에이전트가 둘 다 그 도구의 존재를 알게 만드는 것이다.5

처음에는 거창하게 만들지 말자. 가장 좋은 내부 도구 1호는 화려한 SaaS가 아니라, 이런 식일 가능성이 높다.

"매주 월요일 오전 9시에 지난주 사용자 피드백을 요약해 PM용 문서 초안을 만든다."

혹은 이럴 수도 있다.

"운영자가 장애 로그를 붙여 넣으면, 원인 후보와 즉시 확인할 항목 5개를 뽑아준다."

또는 더 소박하게,

"내가 스테이징한 변경 사항을 보고 커밋 메시지 초안을 만들어준다."

이런 작은 도구 하나가 생기면, 클로드 코드는 더 이상 대화 상대가 아니다. 내 시스템 안에서 정해진 책임을 가진 작업자가 된다.

결국 이 장의 핵심은 하나다. 클로드 코드를 쓰는 단계에서, 클로드 코드를 넣는 단계로 넘어가라.

터미널에서 잘 쓰는 것은 출발점이다. 진짜 차이는 그다음에 난다. 내가 자는 동안 돌고, 버튼 뒤에서 움직이고, 다른 사람이 내 대신 호출할 수 있고, 제품 운영의 반복 업무를 조용히 먹어 치우는 구조. 거기까지 가면 비로소 Claude Code는 도구를 넘어 인프라가 된다.

참고

1The Rise of the Headless Coder: An Analysis of the Claude Code SDK's Role in Orchestrating Agentic Software Development

2헤드리스 모드

3Headless & Programmatic Claude Code: SDK & Automation

4What Is Claude Code Headless Mode? How to Run AI Agents Without a Terminal

5Build Effective Internal Tooling with Claude Code

책 목록

클로드 코드 솔로 빌더: 혼자 만들고 운영하는 AI 제품 개발 시스템

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기