본문으로 건너뛰기

AI 하네스: 반복 가능한 에이전트 개발 환경 만들기

AIAI 에이전트AI 하네스TMS
TMS강수아2026년 7월 13일

모든 팀원이 같은 기준으로 업무를 시작하고, 질문하고, 완료한다면 어떨까요? 요구사항 정리부터 구현, 테스트, MR, JIRA 정리까지 말이죠. 저희가 AI 하네스를 만들며 바란 건 이것이었습니다.

안녕하세요 UMOSONE TMS 개발팀의 Frontend engineer 강수아입니다.

이 글에서는 저희 팀이 AI 하네스를 만들면서 어떤 문제를 해결하려 했고, 실제로 운영하면서 무엇이 바뀌었는지 공유합니다.

Capora TMS

본론에 앞서 저희 팀이 만드는 제품을 짧게 소개합니다. Capora TMS는 화물 운송이 필요한 기업(화주)과 화물차 기사(차주)를 연결하는 운송 관리 플랫폼입니다. "운송의 모든 흐름을 AI로 연결한다"는 방향 아래, 오더 등록부터 배차, 운송, 정산까지를 하나의 플랫폼에서 처리합니다. 사용자에 따라 세 개의 서비스로 나뉩니다.

서비스사용자핵심 역할
OMS화주 (물류 의뢰 기업)오더 등록, 운송 현황 추적
Admin내부 운영팀배차, 차량 관제, 정산, 회원 관리
Driver App차주 (화물차 기사)오더 수락, GPS 운송, 정산 조회

하나의 오더는 세 서비스를 가로질러 흐릅니다. 화주가 OMS에서 오더를 등록하면 운영자가 Admin에서 배차하고, 차주가 Driver App으로 수락해 운송하고, 하차가 확인되면 정산으로 이어집니다. 웹 프론트엔드 두 개와 모바일 앱, 이를 받치는 백엔드까지 — 배차 정책, 관제, 정산, 세금계산서 같은 물류 도메인이 얽혀 있어 요구사항을 정확히 이해하는 것이 개발의 절반입니다. AI 하네스가 필요했던 이유도 여기서 출발합니다.

왜 AI 하네스를 만들었을까요?

처음에는 AI를 쓰는 사람이 늘어나는 것만으로도 충분히 좋아질 거라고 생각했습니다. 실제로 작은 작업에서는 효과가 바로 보였습니다. 요구사항을 요약하고, 기존 코드를 찾고, 테스트 초안을 만드는 속도는 확실히 빨라졌습니다. 그런데 팀 단위로 쓰기 시작하자 다른 문제가 보였습니다.

AI로 개발해 본 팀이라면 아마 공감하실 겁니다. 팀원마다 AI를 쓰는 방식이 전부 다릅니다. 누구는 JIRA 티켓을 정리한 뒤 시작하고, 누구는 바로 구현부터 시킵니다. 누구는 Figma나 Confluence를 같이 넣고, 누구는 코드만 보여줍니다. BE 엔지니어와 FE 엔지니어가 일을 처리하는 방식도 다릅니다. 그러다 보니 같은 티켓을 다뤄도 산출물의 품질이 사람에 따라 흔들렸습니다.

가장 문제가 됐던 건 AI가 애매한 요구사항을 스스로 판단해서 몰래 채워 넣는 것이었습니다. 예를 들어 "오더 취소" 기능을 요청하면, 취소 가능한 배차 상태나 수수료 정책이 비어 있어도 AI는 그럴듯한 기준을 만들어 구현을 이어갑니다. 겉으로는 빠르게 진행되는 것처럼 보이지만, 다 완성되고 나서야 잘못된 방향이었다는 걸 알게 됩니다. 테스트를 끝까지 돌려보지 않은 채로 "구현했습니다"라고 말하는 것도 마찬가지였습니다. 말로는 완료인데, 실제로 돌려보면 아니었습니다.

AI 하네스를 만든 이유

그래서 저희는 프롬프트 문장이 아니라 작업 방식을 고정하려고 했습니다. AI가 무엇을 보고 시작하는지, 어느 단계에서 질문하는지, 어떤 산출물을 남기는지, 어떤 검증이 실패하면 멈추는지를 팀의 흐름으로 만들기 시작했습니다.

하네스가 맡은 역할

저희가 생각하는 하네스는 AI를 감싸는 실행 환경입니다. 입력을 넣으면 결과만 나오는 검은 상자가 아니라, AI가 어떤 순서로 일했고 무엇을 근거로 판단했는지 남기는 장치에 가깝습니다.

현재 흐름은 크게 다섯 단계로 나뉩니다.

단계책임남겨야 하는 것
start작업 시작 상태를 고정합니다.브랜치, 티켓 맥락, 현재 상태
spec요구사항을 구현 가능한 수준으로 정리합니다.요구사항 요약, AC, 예외 케이스, 질문 목록
plan코드 작성 전에 변경 범위와 검증 전략을 정합니다.변경 파일, API 계약, 테스트 계획, 구현 순서
implement계획을 task 단위로 쪼개 구현합니다.코드 변경, task 체크리스트, 빌드타임 검증
test실제 실행 결과로 완료 가능 여부를 판단합니다.API smoke, 브라우저 확인, 테스트 결과, 커밋 가능 여부

중요한 점은 각 단계가 산출물과 통과 조건을 가진다는 것입니다. spec 단계에서 모호함이 남아 있으면 plan으로 넘어가지 않습니다. plan이 확정되지 않으면 코드를 먼저 짜지 않습니다. 필요한 테스트가 실패하면 commit이나 MR로 넘어가지 않습니다.

이 구조는 전부 repository 안의 .agents 디렉토리에 들어 있습니다. 특정 도구 전용 설정이 아니라 팀 공용 자산으로 두기 위해서입니다. Claude Code에서는 .claude/skills가 이 디렉토리를 가리키는 symlink로 연결됩니다.

.agents/
├── constitution.md # 팀이 지키는 원칙
├── domain/ # 물류 도메인 지식 (용어, 정산, 배차 …)
├── guides/ # 워크플로우, 아키텍처 가이드
├── patterns/ # 반복되는 코드 패턴
├── skills/ # 반복 판단을 문서화한 스킬
│ ├── feature-workflow/ # spec→plan→implement→test 오케스트레이터
│ ├── feature-spec/ # 단계별 스킬 (spec, start, plan, implement, test)
│ ├── browser-test/ # 브라우저 · Figma 검증
│ ├── ...
│ └── creating-mr/ # MR 생성
└── scratch/{TICKET}/ # 티켓별 산출물 (state, spec, plan, tasks)

스킬은 반복되는 판단을 문서화해 AI에게 "이런 일을 할 수 있다"고 알려주는 능력이고, scratch의 산출물은 다음 사람이나 다음 AI가 이어서 볼 수 있는 기록입니다. 도구가 Claude든 Codex든 Gemini든, 같은 팀 지식을 읽고 시작합니다.

하네스가 책임져야 하는 범위는 생각보다 넓었습니다. 단순히 코드를 생성하는 것이 아니라, 입력 맥락을 모으고, 누락된 질문을 드러내고, 기존 패턴을 먼저 찾고, 실행 결과를 남기고, 실패했을 때 어디서 멈췄는지 재현 가능하게 만들어야 했습니다.

실행과 검증을 분리하자

AI 에이전트의 실행 로그는 금방 사라집니다. 터미널 출력, 중간 대화, 임시 판단은 그 순간에는 유용하지만 다음 사람이 보기에는 맥락이 부족합니다. 그래서 하네스에서는 실행과 검증을 분리했습니다.

실행은 AI가 합니다. JIRA를 읽고, Figma를 확인하고, 기존 코드를 검색하고, 파일을 수정하고, 테스트를 실행합니다. 검증은 산출물이 맡습니다. spec에는 무엇이 요구사항이고 무엇이 아직 질문인지 남깁니다. plan에는 어떤 파일을 왜 바꿀지, 어떤 테스트로 확인할지 남깁니다. tasks에는 실제 구현 단계를 체크박스로 남기고, test 결과에는 어떤 검증을 실행했고 무엇이 실패했는지 남깁니다.

이렇게 나누면 몇 가지 장점이 생깁니다.

  • 긴 대화를 다시 읽지 않아도 현재 작업 상태를 파악할 수 있습니다.
  • 다른 AI 도구나 다른 개발자가 이어받아도 같은 기준으로 판단할 수 있습니다.
  • 실패했을 때 "왜 그렇게 구현했는지"를 역추적할 수 있습니다.
  • 빠른 경로를 탔더라도 무엇을 생략했는지 기록할 수 있습니다.

컨텍스트 비용을 줄이는 데도 도움이 됐습니다. 모든 히스토리를 계속 AI에게 먹이는 대신, 산출물만 남기고 필요한 순간에 다시 읽게 하면 됩니다. 작업이 길어질수록 이 차이가 컸습니다. 하네스는 더 많은 맥락을 한 번에 넣는 장치가 아니라, 필요한 맥락만 다시 꺼낼 수 있게 정리하는 장치에 가까웠습니다.

평가 기준은 명확한 게이트로

AI가 만든 결과를 믿으려면 완료의 기준이 말로만 남아 있어서는 안 됐습니다. 그래서 완료 기준을 실행 가능한 게이트로 옮겼습니다.

화주가 쓰는 오더 등록 화면이라면 단위 테스트만으로는 부족합니다. 타입과 lint가 통과해도 실제 브라우저에서 레이아웃이 깨질 수 있고, Figma가 있는 화면이라면 구현 결과가 디자인과 맞는지도 봐야 합니다. 배차나 정산 API라면 단위 테스트에 더해 API smoke, OpenAPI 계약, 예외 응답까지 확인해야 합니다.

그래서 test 단계는 단순히 테스트 명령을 실행하는 역할이 아니라 커밋 가능 여부를 판단하는 게이트가 됐습니다. 필요한 검증이 실패하면 commit이나 MR로 넘어가지 못하고, 실패를 사람이 명시적으로 승인하지 않는 한 완료로 포장하지 않습니다. 게이트에서 확인하는 기준은 대략 이렇습니다.

  • 요구사항이 충분히 구체화됐는가
  • 기존 코드 패턴을 먼저 확인했는가
  • 계획 밖 구현이 섞이지 않았는가
  • 테스트와 브라우저 검증이 실제로 실행됐는가
  • 실패한 검증을 숨기지 않고 기록했는가
  • MR과 JIRA에 다음 사람이 볼 수 있는 요약이 남았는가

이 기준은 코드, 스킬, hook, 문서로 나눠 남겼습니다. 스킬은 AI가 어떻게 판단해야 하는지 알려주고, hook은 사람이 잊어도 특정 이벤트에서 검증이 실행되게 만들고, 문서는 왜 그런 기준이 필요한지 설명합니다.

기준이 지나치게 많아지는 것도 경계했습니다. 하네스가 무거워지면 아무도 쓰지 않습니다. 그래서 모든 작업에 같은 깊이의 검증을 강제하기보다, 작업 크기와 위험도에 따라 quick mode와 standard mode를 나눴습니다. 문구 수정 같은 작은 작업은 quick mode로 빠르게 지나가고, 정책이 걸린 작업은 standard mode로 전 단계를 밟습니다. 대신 quick mode를 탔다면 무엇을 생략했는지 남기게 했습니다.

계속 성장하는 하네스

운영하면서도 지속적인 수정이 필요했습니다. 예를 들어 화면 구현에서, 코드상으로는 구현이 끝났지만 Figma와 실제 화면이 미묘하게 다른 일이 있었습니다. 이후 browser-test 흐름으로 viewport, Figma, 브라우저 결과를 같이 확인하고 report를 남기는 쪽으로 바꿨습니다.

스킬 자체도 운영 대상이었습니다. 만들어둔 스킬이 실제 작업에서 호출되지 않으면 없는 것과 같습니다. 그래서 스킬 사용량을 보고, 잘 쓰이지 않는 스킬은 trigger를 고치거나 내용을 줄이거나 제거합니다. 스킬을 많이 만드는 게 목표가 아니라, 반복되는 판단이 실제 작업 안에서 자연스럽게 호출되게 만드는 게 목표이기 때문입니다.

이런 수정은 한 번으로 끝나지 않습니다. 모델이 바뀌고, 도구가 바뀌고, 팀의 작업 방식이 바뀌면 같은 티켓도 다른 결과를 낼 수 있기 때문입니다.

사람이 책임져야 할 부분

가장 크게 바뀐 기준은 AI와 사람의 책임 경계였습니다. 처음에는 AI가 더 많은 일을 하면 좋다고 생각했지만, 운영해 보니 중요한 건 AI가 어디까지 할 수 있느냐보다 사람이 어디에서 최종 판단해야 하느냐였습니다.

AI와 사람의 책임 경계

AI가 잘하는 일은 초안을 만들고, 흩어진 맥락을 모으고, 누락된 질문을 찾아내고, 검증을 실행해 결과를 정리하는 일입니다. 반대로 spec을 최종 확정하는 일, 질문에 답하고 범위를 결정하는 일, 아키텍처를 판단하는 일, gate 통과나 재작업을 결정하는 일, MR을 승인하고 머지하는 일은 개발자의 책임으로 남습니다.

하네스는 이 경계를 더 선명하게 만들기 위해 만든 것입니다. AI가 더 많은 초안을 만들수록 사람이 봐야 할 근거가 더 중요해집니다. 그래서 하네스의 산출물은 AI가 자신 있게 말한 문장이 아니라, 사람이 확인할 수 있는 질문, 결정, 테스트 결과, 실패 기록이어야 합니다.

특히 고민했던 것들

가장 많이 고민한 것은 스킬을 얼마나 잘게 나눌지였습니다. FE는 React/TypeScript, BE는 Kotlin/Spring WebFlux로 스택이 다르지만, 티켓을 읽고, 요구사항을 정리하고, 계획을 세우고, 구현하고, 테스트하는 흐름은 같습니다. 그래서 workflow는 하나로 두고 스택 차이는 reference 문서로 분기했습니다. 한 번 고친 운영 원칙이 양쪽에 같이 반영되게 하기 위해서입니다.

두 번째는 요구사항 stress test였습니다. AI는 애매한 요구사항을 보면 질문보다 추정을 택합니다. 그래서 spec 단계에서 사용자, 발생 조건, 필요한 데이터, 정책, 예외, 검증 순서로 질문하게 만들었습니다. 질문을 하나씩 흩뿌리면 답이 누락되기 쉬워서, 가능한 한 묶어서 던지고 답이 없으면 plan으로 넘어가지 않는 기준을 뒀습니다.

세 번째는 기록의 양이었습니다. 전부 남기면 읽히지 않고, 너무 적게 남기면 이어받을 수 없습니다. 그래서 다음 단계가 실제로 읽는 spec, plan, tasks, test 위주로 남기고 중간 대화는 과감히 줄였습니다.

네 번째는 도구 중립성입니다. 특정 AI 도구의 설정에만 묶이면 팀의 지식이 도구 안에 갇힙니다. 도구는 바뀔 수 있지만, 팀의 판단 기준은 repository 안에 남아야 한다고 봤습니다. 원칙과 스킬을 .agents 아래에 둔 이유입니다.

마지막은 하네스 자체의 비용입니다. 하네스가 너무 무거우면 작은 수정에도 부담이 됩니다. 그래서 모든 작업에 풀코스를 강제하기보다 작업의 위험도에 따라 경로를 나누되, 빠른 경로를 탔다는 사실과 생략한 검증은 남깁니다. 빠르게 가더라도 무엇을 믿을 수 있고 무엇을 다시 확인해야 하는지는 보여야 하기 때문입니다.

앞으로 나아가야 할 방향

지금의 하네스는 feature 개발 흐름에서 시작했지만, 화면 구현, 코드리뷰, 문서화, 장애 리포트처럼 입력과 산출물과 검증 기준이 반복되는 업무라면 같은 구조를 적용할 수 있습니다. 저희는 두 가지를 준비하고 있습니다.

첫째는 대표 작업 기준의 회귀 평가입니다. 모델이나 스킬을 바꾼 뒤 "대체로 좋아졌다"고 말하는 대신, 이전에 처리했던 대표 티켓을 다시 실행해 질문 품질, 계획 품질, 검증 누락이 어떻게 달라졌는지 비교하려 합니다. AI 하네스도 테스트 대상이 되어야 합니다.

둘째는 결과 정확도를 높이는 반복 루프입니다. 한 번의 실행으로 끝내지 않고, 실행 결과를 평가하고 부족한 부분을 찾아 다시 실행하는 루프를 하네스 안에 넣으려 합니다. 사람이 매번 결과를 뜯어보며 재작업을 지시하는 대신, 평가와 재실행이 구조 안에서 돌게 만드는 것입니다.

하네스의 다음 단계는 "AI가 더 많은 일을 하게 하기"가 아니라 **"AI가 한 일을 더 잘 검증하고 다시 사용할 수 있게 하기"**라고 생각합니다. 팀의 좋은 판단이 한 사람의 프롬프트 창에만 남지 않고, 다음 작업에서도 반복될 수 있어야 합니다.

마치며

하네스를 만들며 배운 가장 큰 교훈은 신뢰는 말이 아니라 구조에서 나온다는 점이었습니다. AI가 그럴듯하게 설명해도 실행 결과가 없으면 믿을 수 없습니다. 테스트가 실패했는데 완료라고 말하면 안 됩니다. 요구사항이 애매한데 질문 없이 구현하면 빠른 게 아니라 위험한 것입니다.

하네스는 AI를 더 자유롭게 풀어놓기 위한 장치가 아닙니다. 같은 순서, 같은 기준, 같은 멈춤 조건을 만들어 AI와 사람이 함께 일할 수 있는 환경을 만드는 일입니다.

속도는 AI가 올릴 수 있습니다. 하지만 책임은 사람이 가져야 합니다. 저희가 하네스를 계속 다듬는 이유도 여기에 있습니다. 더 빠른 개발보다 반복 가능한 개발, 더 많은 자동화보다 검증 가능한 자동화. 그 방향으로 팀의 작업 방식을 조금씩 옮겨가고 있습니다.

물론 저희 방식이 정답은 아닙니다. 팀마다 제품도, 도메인도, 일하는 방식도 다르니까요. 비슷한 고민을 하고 있는 팀이 있다면 공유해주세요.

긴 글 읽어주셔서 감사합니다 😊