우리는 코드의 3분의 1을 AI가 작성하게 했습니다. 우리를 제정신으로 유지해 준 리뷰 프로세스를 소개합니다.
요약
AI 코딩 어시스턴트 사용 시 급증하는 코드 양과 품질 저하 문제를 해결하기 위한 리뷰 프로세스를 소개합니다. 코드 소유권 명확화, 자동화된 검증 게이트 구축, AI 특유의 실패 패턴 주시를 통해 안정적인 개발 환경을 유지하는 방법을 다룹니다.
핵심 포인트
- 머지(merge)하는 사람이 AI가 작성한 코드에 대해서도 전적인 책임을 진다.
- 인간 리뷰어의 부하를 줄이기 위해 타입 체크, 린터 등 자동화된 검증 단계를 선행한다.
- 엣지 케이스 미처리, 환각, 보안 안티 패턴 등 AI 코드의 특유의 실패 모드를 주시한다.
- 테스트 생성은 사람이 작성한 코드를 검증하는 용도로 활용할 때 가장 효과적이다.
AI 코딩 어시스턴트(AI coding assistants)가 실질적인 역할을 하기 시작할 때 유혹적인 순간이 찾아옵니다. 변경 사항(diffs)의 상당 부분이 기계에 의해 초안이 작성되고, 개발 속도(velocity)가 급증하며, 모두가 자신감이 넘치게 됩니다. 그러다 검토되지 않은 생성된 코드에서 발생한 첫 번째 미묘한 버그가 프로덕션(production) 환경에 도달하는 순간, 당신은 이 도구가 코드를 '작성하는' 속도는 바꾸었지만 코드를 '관리하는(own)' 비용은 바꾸지 못했다는 사실을 깨닫게 됩니다. 해당 코드를 리뷰하고, 테스트하고, 보안을 확보하고, 유지보수하는 비용은 예전과 정확히 동일합니다.
다음은 취약성을 물려받지 않으면서 생성 기능에 의존할 수 있게 해준 프로세스입니다.
규칙 제로: 머지(merge)하는 사람이 소유한다
가장 중요한 변화는 기술적인 것이 아니라 문화적인 것이었습니다. PR(Pull Request)을 여는 사람은 마치 자신이 직접 타이핑한 것처럼 모든 라인에 대해 책임을 집니다. 사후 분석(postmortem)에서 "모델이 작성했습니다"라는 말은 변명이 될 수 없습니다. 이 하나의 규범은 대충 훑어보고 승인하는(skim-and-approve) 반사적인 행동을 끝내게 했습니다. 이제 대충 훑어보는 행위는 장애(incident) 발생 시 당신의 이름이 걸리는 문제이기 때문입니다.
수도꼭지를 틀기 전에 자동화된 바닥(floor)을 구축하라
AI는 리뷰에 들어오는 코드의 '양'을 증가시킵니다. 만약 인간의 리뷰가 유일한 필터라면, 리뷰어들은 과도한 부하 속에서 형식적인 승인(rubber-stamping)을 하기 시작할 것입니다. 그래서 우리는 AI가 작성한 변경 사항이 사람에게 도달하기 전에 결정론적인 게이트(deterministic gate)를 배치했습니다:
[ ] 타입 체크(type-checks) / 컴파일(compiles)
[ ] 린터(linter) 클린
[ ] 정적 분석(SAST)에서 알려진 취약점 패턴 미발견
...
이 중 어느 것도 AI 전용이 아니며, 그것이 핵심입니다. 바닥(floor)은 더 많은 인간의 시간 투입 없이도 더 많은 코드를 흡수할 수 있을 만큼 견고해야 합니다.
어시스턴트가 과잉 생산하는 실패 모드(failure modes)를 주시하라
생성된 코드는 특징적인 방식으로 실패하며, 이를 알고 있으면 리뷰가 빨라집니다. 해피 패스(happy path)에서는 절대 실행되지 않는 잘못 처리된 엣지 케이스(edge cases, 빈 컬렉션, 시간대, 정수 절삭 등), 그럴듯하게 들리는 환각(hallucinated) 또는 오래된 API 호출, 그리고 모델이 학습 데이터로부터 재현하는 문자열 연결 방식의 SQL과 같은 보안 안티 패턴(security anti-patterns) 등이 있습니다. 우리는 정확히 이러한 항목들을 담은 짧은 리뷰어 체크리스트를 유지하고 있습니다.
어떤 어시스턴트(assistants)와 스캐너(scanners)를 표준화할지 결정하는 것 자체가 하나의 프로젝트였습니다. 만약 여러분이 이 단계의 초기 단계에 있다면, IDE에 기본적으로 포함된 도구를 그대로 사용하기보다는 현재의 AI 소프트웨어 개발 도구(AI software development tools)들을 조사해 볼 가치가 있습니다.
사람이 작성한 코드를 위한 테스트를 생성하세요, 그 반대가 아니라
테스트 생성은 우리의 가장 레버리지가 높은(highest-leverage) 활용 사례였지만, 신뢰의 방향에 관한 한 가지 주의사항이 있습니다. 기존에 사람이 작성한 코드를 위해 테스트를 생성하는 것은 매우 좋습니다. 이때 코드는 신뢰할 수 있는 산출물(artifact)이며 테스트는 이를 보조하는 스캐폴딩(scaffolding) 역할을 하기 때문입니다. 하지만 모델이 구현(implementation)과 테스트를 모두 작성하게 되면, 테스트가 구현 단계의 버그를 "예상되는 결과"로 인코딩하는 경향이 있습니다. 따라서 요구사항을 이해하고 있는 사람이 의도된 동작을 항상 단언(assert)해야 합니다:
def test_discount_never_exceeds_cap():
# 비즈니스 규칙: 입력값에 관계없이 할인은 30%로 제한됨.
assert apply_discount(price=100, pct=50) == 70 # 50이 아니라 제한된 값인 70
...
타이핑이 아니라 전달(delivery)을 측정하세요
함정은 "생성된 라인 수"나 "열린 PR(PRs opened) 수"를 축하하는 것입니다. 그것들은 투입량(inputs)일 뿐입니다. 우리는 변경 실패율(change-failure rate), 복구 시간(time-to-restore), 결함 유출률(defect-escape rate)을 모니터링합니다. 생성 속도는 빨라졌는데 변경 실패율이 상승한다면, 그것은 작업의 중심이 작성(writing)에서 디버깅(debugging)으로 옮겨졌다는 신호이며, 디버깅은 비용이 많이 드는 단계입니다.
시사점
리뷰 게이트(review gates), 테스트 규율(test discipline), 그리고 책임 소재(accountability)가 충분히 강력하여, 늘어난 작업량이 취약성을 초래하지 않고 속도를 높여줄 수 있다면 파이프라인에 더 많은 AI를 도입하는 것은 괜찮으며, 심지어 훌륭한 일입니다. 승리하는 팀은 코드를 가장 많이 생성하는 팀이 아닙니다. 생성은 저렴한 것으로 취급하고, 소유권(ownership)을 진정한 업무로 여기는 팀입니다. 만약 여러분의 팀이 이를 대규모로 공식화하려고 한다면, 그것은 본질적으로 모든 진지한 생성형 AI 소프트웨어 개발 기업(generative AI software development company)의 운영 모델과 같습니다. 즉, 생성에는 빠르게 움직이되, 검증(verification)에는 엄격함을 유지하는 것입니다.
여러분의 AI 코드 리뷰 프로세스는 어떤 모습인가요? 저는 댓글을 통해 다양한 패턴을 수집하고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기