최근 AI를 사용하여 개발부터 회사 운영까지 거의 혼자 전 과정을 자동화하고 있다는 이야기를 들었습니다.
정말 대단한 시대가 된 것 같습니다.
확실히 소프트웨어 개발이 지향하는 방향 중 하나는 그럴 수도 있을 것입니다.
하지만 저희 Shizen Connect가 개발하고 있는 것은 전력 리소스를 제어하는 VPP(Virtual Power Plant) 시스템입니다. 외부 장치와의 연동이나 장애 발생 시의 동작이 중요한 미션 크리티컬(mission critical) 시스템이기 때문에, 현재로서는 전 자동화 개발에 나서기 어렵다고 느낍니다.
그렇다고 해도 참고할 점은 매우 많습니다. 특히 결합 테스트나 E2E 테스트까지 '저렴하게' CI를 통해 돌리는 방법이나, 여러 AI에 의한 감사 및 리뷰 등은 적극적으로 도입하고 싶습니다.
또한, 니시오 야스카즈(西尾泰和) 님의 '인간의 AI에 대한 판단 위임'이라는 글도 많은 생각을 하게 했습니다.
AI에게 어디까지 판단을 맡길 것인가. '최종 판단은 인간이 한다'고 말하는 것은 쉽지만, AI의 능력이 향상됨에 따라 그 경계는 변화할 수밖에 없을 것입니다.
저 자신은 코드를 작성하는 것은 AI에게 맡기더라도, 코드를 이해하는 것은 아직 포기하고 싶지 않고, 포기할 수 없다고 생각합니다.
그렇다면, AI가 개발의 많은 부분을 담당하면서도 인간이 시스템을 이해하고 품질에 책임을 지려면 어떻게 해야 할까요?
이번에는 다양한 AI 개발 방법론의 지견을 참고하여, Shizen Connect에서 진행하고 있는 'AI Loop'라는 개발 방법을 소개합니다.
AI Loop는 인간이 요청/판단/승인/이해에 집중하고, 조사/사양 초안 작성/계획/구현/검증은 AI에게 맡기는 개발 방법론입니다.
현재는 Claude Code를 이용하고 있습니다. 전체 과정은 8단계로 구성되어 있습니다.
이 중에서도 특히 중요하게 생각하는 부분은 AI와 인간이 함께 사양(Spec)을 만들어 나가는 과정과, AI가 작성한 구현 코드를 인간이 이해하는 과정입니다.
AI Loop에서는 처음부터 사람이 상세한 사양서를 쓸 필요는 없습니다.
먼저 이슈에 '무엇을 하고 싶은지', '왜 필요한지'를 간단하게 적습니다. 예를 들면,
하고 싶은 것
외부 API가 타임아웃했을 경우 재시도(retry)할 수 있도록 하고 싶다.
이유
일시적인 통신 장애로 인해 처리가 실패하여 운영상의 부담이 되고 있다.
이 정도만으로 충분합니다.
Claude Code에게 다음과 같이 지시합니다.
독자적인 investigate Skill에 의해, AI는 기존 코드, 테스트, 설계 자료, Git 히스토리 등을 조사하여 Feature Spec 초안을 작성합니다. 사양에는 다음과 같은 내용이 포함됩니다.
- Goal: 무엇을 실현할 것인가
- Scenario: 어떤 동작을 기대하는가
- Acceptance Criteria (AC): 무엇을 충족해야 완성인가
- Failure cases: 장애 시 어떻게 움직여야 하는가
- Constraints: 제약 사항
- Open questions: 인간의 판단이 필요한 부분
- Decisions: 무엇을, 왜 결정했는가
여기서 중요한 것은 AI가 작성한 사양을 그대로 올바른 것으로 취급하지 않는 것입니다.
AI는 코드를 조사하여 사양을 추측할 수는 있지만, 코드에 적혀있지 않은 업무상의 의도나 운영상의 제약까지 반드시 이해할 수 있는 것은 아닙니다. 게다가 AI가 작성하는 글은 너무 그럴듯해서, 그것이 추측이라는 사실을 인지하기 어렵습니다.
그래서 조사로 근거를 찾지 못한 내용에는 반드시 【추측】라는 표시를 합니다.
예를 들면,
### Failure cases
- API가 타임아웃했을 경우 재시도한다
- 【추측】재시도 횟수는 최대 3회로 한다
...
기존 코드나 자료에서 확인된 내용에는 근거를 제시하고, 확인할 수 없었던 내용은 추측으로 남깁니다. 이로써 인간이 확인해야 할 부분이 명확해집니다.
더 나아가, AI가 조사해도 알 수 없는 것은 Open questions에 정리합니다.
다음으로, 독자적인 interview Skill을 실행합니다.
doc/specs/api-retry.md를 interview 해
그러면 AI가 하나씩 질문해 옵니다. 재시도 대상 오류는? A. 타임아웃과 HTTP 5xx만 (AI 권장)
B. 타임아웃과 모든 HTTP 에러
C. 기타 추천 이유: HTTP 4xx에는 재시도해도 개선되지 않는 오류가 포함되기 때문이다.
인간은 AI의 추천안을 채택할 수도 있고, 다른 안을 선택해도 무방합니다.
AI의 제안과 다른 판단을 내린 경우, 그 이유도 기록합니다.
답변은 Spec의 Decisions에 반영되고, 관련 사양도 업데이트됩니다.
즉, 인간이 AI에게 질문하여 사양을 작성하게 하는 것뿐만 아니라, AI에게 질문하게 함으로써 인간 스스로도 사양을 생각하고 결정해 나가는 것입니다.
이 상호작용은 단순히 사양서를 완성하기 위한 것만이 아닙니다. 인간이 시스템의 동작 방식에 대해 생각하고 이해를 심화하는 과정이기도 합니다.
AI와의 상호작용이 끝나면, 인간이 Spec 전체를 확인합니다. 여기서 특히 중요한 것은 남아 있는 【추측】을 하나씩 확인하는 것입니다.
- 추측이 맞다면, 확인하고 표시를 제거합니다.
- 틀렸다면, 사양을 수정하고 그 이유를 Decisions에 남깁니다.
- 판단할 수 없다면, 추가 조사나 질문으로 돌아갑니다.
이렇게 하여, AI가 추측으로 만든 초안을 인간이 책임을 질 수 있는 사양으로 변화시킵니다.
최소한 Goal과 Acceptance Criteria에는 【추측】이 남아있지 않은지, 중요한 Open question이 해결되었는지, 각 AC에 대응하는 테스트 방법이 결정되었는지를 확인한 후에 승인합니다.
여기까지 오면, 담당자는 "무엇을 만들 것인지", "왜 그 사양이어야 하는지"를 이해하고 있어야 합니다.
Spec이 승인되면, Claude Code의 Plan 모드에서 구현 계획을 작성합니다. AI는 AC별 테스트와 구현 Task를 생각하고, 인간이 계획을 승인합니다.
구현은 Task별로 새로운 세션에서 진행합니다. 테스트를 먼저 작성하여 실패를 확인하고, 구현한 후 테스트를 통과시키는 TDD(Test-Driven Development)를 기본으로 합니다.
# spec: api-retry AC1
async def test_retry_on_timeout():
...
테스트에는 대응하는 AC를 기록하여, 사양과 테스트의 관계를 추적할 수 있도록 합니다. 또한, 같은 실패가 3회 연속되거나 Task 범위를 벗어난 변경이 필요한 경우에는 인간에게 상담하도록 합니다.
그리고 또 하나의 중요한 과정은 구현의 이해입니다. AI가 코드를 작성하고 테스트가 통과되었다고 해서, 그것만으로는 Merge하지 않습니다.
다만, 인간이 모든 diff를 한 줄씩 읽는 것도 현실적이지 않습니다. 그래서 AI가 작성한 Change Brief를 사용하여 다음 5가지를 이해하도록 합니다.
- 어디에 무엇을 만들었는지
- 주요 처리는 어디를 거쳐 어떻게 흐르는지
Spec이나 Plan에 쓰여있지 않은, AI가 스스로 결정한 것은 무엇인지
- 실패했을 때 코드는 어떻게 작동하는지
- 테스트로 확인하지 못한 것은 무엇인지
특히 중요한 것은 3번입니다. AI는 사양에 쓰여있지 않은 것도 스스로 판단하여 구현합니다. 예를 들어, 예외를 어떻게 처리할지, 트랜잭션 경계를 어디에 둘지, 리트라이(Retry)를 어떻게 구현할지 등입니다. 이러한 판단은 반드시 인간이 지시한 것은 아닙니다.
그리고 인간에게 가장 놓치기 쉬운 것은, AI가 무언가를 멋대로 결정했다는 사실 자체를 알아차리지 못하는 것이라고 생각합니다. 그래서 AI에게 구현 내용을 설명하게 하고, 사양에 없는 판단을 명시하도록 합니다. 담당자는 각각의 판단을 수용할지, 수정하게 할지를 결정합니다.
설명을 듣기만 해서는 정말 이해했는지 알 수 없습니다. 그래서 Claude Code에게 다음과 같이 지시합니다.
AI는 코드 내용에 대해 구체적인 질문을 2~3개 합니다. 예를 들어, API가 타임아웃(Timeout)했을 경우, 어느 함수에서 예외가 처리되며 최종적으로 어떻게 되는지?
담당자가 자신의 말로 답할 수 없다면, 다시 코드를 조사하고 AI와 대화하며 이해를 재정비합니다. 이른바, AI에 의한 코드 이해 구술 시험입니다.
물론, 질문에 답할 수 있었다고 해서 완전히 이해했다고 보장되는 것은 아닙니다. 변경 위험도가 중~높은 경우에는 인간도 중요한 코드를 읽고, 다른 멤버의 리뷰도 진행합니다.
AI가 생성한 코드에 문제가 있을 경우, 그 자리에서 수정하고 끝내지 않습니다. 원인에 따라 Issue 템플릿, Spec, CLAUDE.md, 테스트 등에 개선 사항을 반영합니다.
같은 지적을 매번 인간이 반복하고만 있다면, AI를 사용할 의미가 없습니다. AI에 대한 지적을 그 자리의 대화로 끝내지 않고, 다음 개발에 피드백하는 것. 이것도 AI Loop의 중요한 사고방식입니다.
AI에 의한 코드 생성 속도가 빨라지는 반면, 인간이 코드를 이해하는 속도는 그다지 변하지 않았습니다.
앞으로 개발의 병목 지점(bottleneck)은 '코드를 작성하는 것'에서 '코드를 이해하고 판단하는 것'으로 이동할 것이 아닐까요?
저희의 AI Loop에서는 개발 시작 단계에서 AI와 인간이 함께 Spec을 만들고, 무엇을 만들 것인지 이해합니다. 그리고 종료 단계에서는, AI가 만든 구현(implementation)을 인간이 이해합니다.
그 사이의 작업은 가능한 한 AI에게 맡깁니다.
아직 시행착오(trial and error) 단계이며, 개발 속도나 품질에 미치는 효과는 앞으로 검증해 나갈 것입니다.
장기적으로는 AI에게 위임되는 판단의 범위 또한 더욱 넓어질 것입니다.
다만, 현시점에서 저희에게 중요한 것은 AI에게 무엇을 맡길지뿐만 아니라, 인간이 무엇을 계속 이해해야 하는지를 고민하는 것입니다.
그 경계를 조금씩 재검토하면서, AI를 통한 개발 효율화와 시스템의 신뢰성을 양립하고 싶습니다.