Skip to content
게으른 엔지니어의 기술 블로그
Go back

여덟 번의 AI 코드 리뷰 중 여섯 번에서 버그가 나왔다

다 확인했다고 생각한 순간마다, 확인이 하나씩 빠졌다 · 1/3편

여러 국가 앱스토어를 가로질러 특정 조건에 맞는 앱과 회사를 찾아내는 파이프라인을 만드는 중이었다. 스키마, 수집기, 룰 기반 판정 로직까지 합쳐서 8개 태스크짜리 구현 계획을 세웠다. 방식은 이랬다 — 태스크 하나마다 전담 구현 에이전트를 붙이고, 구현이 끝나면 별도의 리뷰 에이전트가 그 diff만 떼어서 검토한다. 스펙에 맞는지, 코드 품질은 괜찮은지 둘 다 본다. 문제가 나오면 고치고 다시 검토한다. 통과해야 다음 태스크로 넘어간다.

이 정도 절차면 어지간한 실수는 걸러질 거라고 생각했다. 실제로는 여덟 개 태스크 중 여섯 개에서 리뷰가 뭔가를 잡아냈다.

내가 계획서에 직접 심어둔 모순

가장 인상 깊었던 건 첫 번째 태스크였다. 기존에 있던 함수 두 개를 다른 모듈로 옮기기만 하는, 말 그대로 “순수 리팩토링” 작업이었다. 계획서에는 “동작 변화 없음”이라고 못 박아뒀고, 옮길 코드도 있는 그대로 복사해서 넣으라고 적어놨다.

그런데 같은 계획서의 테스트 케이스 하나가, 서로 다른 두 개의 원본 문자열이 같은 회사로 정규화될 때 완전히 다른 두 개의 레코드가 생겨야 한다고 요구하고 있었다. 문제는 내가 “그대로 복사하라”고 지시한 원본 코드는 정규화된 값 하나당 레코드 하나만 만드는 로직이었다는 것이다. 계획서 안에서 “동작을 바꾸지 마라”는 지시와 “이 동작이 나와야 한다”는 테스트가 서로 모순되고 있었다.

구현을 맡은 에이전트가 이 모순을 알아서 풀어버렸다 — 원본 로직을 살짝 바꿔서 테스트를 통과시켰다. 그 자체는 정답이었다. 하지만 “동작 변화 없음” 이라고 스스로 적어놓은 문서와 실제로 나간 변화가 어긋나 있다는 걸, 리뷰가 붙기 전까지는 아무도 짚지 않았다. 리뷰어가 이걸 발견하고 왜 이런 판단을 내렸는지 되짚어보니, 원인은 명확했다. 나는 옛날 코드를 “그대로만” 옮기라고 쓰면서, 그 옛날 코드가 애초에 지금 요구사항을 만족 못 한다는 걸 계획을 쓰는 시점에 확인하지 않았다.

픽스처 자체가 틀렸던 경우

다른 태스크에서는 정반대 문제가 나왔다. 이번엔 계획이 아니라 테스트 데이터가 틀렸다. 특정 조건(“최근 릴리스가 여러 번 있었지만 간격이 넓다”)을 검증하는 테스트를 하나 만들어뒀는데, 리뷰어가 그 조건을 판정하는 코드에서 일부러 조건 하나를 지워보는 실험을 했다. 지워도 같은 테스트가 그대로 통과했다. 즉 그 테스트는 애초에 그 코드가 있어야만 통과하는 게 아니었다 — 테스트 데이터의 날짜 범위가 실제로는 다른 분기를 타고 있었다. 겉으로는 초록불이었지만, 검증하려던 조건은 한 번도 실행된 적이 없었다.

이 두 건 다 실제로 돌려서 확인하지 않았으면 못 잡았을 문제다. 코드만 읽어서는 “논리적으로 맞아 보인다”는 인상만 남는다. 리뷰어가 픽스처 숫자를 손으로 계산해보거나, 조건문 하나를 일부러 지워서 테스트가 정말 그 조건 때문에 통과하는지 확인하는 과정을 거치고 나서야 발견됐다.

태스크 단위 리뷰가 못 잡은 것도 있었다

여섯 번 잡아낸 건 나쁘지 않은 결과처럼 보이지만, 이 절차가 완벽하다는 뜻은 아니었다. 태스크 단위 리뷰는 그 태스크의 diff만 본다 — 다른 태스크와 어떻게 얽히는지는 애초에 시야 밖이다. 전체 브랜치를 통째로 다시 보는 마지막 리뷰 한 번을 따로 붙였는데, 거기서 또 새로운 문제가 네 개 나왔다. 그중 하나는 한쪽 수집 경로에서만 특정 집계 함수를 부르고, 먼저 만들어둔 다른 수집 경로에는 그 호출을 넣는 걸 깜빡한 것이었다. 각 태스크는 자기 파일만 봤으니 이 구멍을 볼 수가 없었다.

그리고 이 마지막 리뷰까지 다 끝내고 나서, 실제로 코드를 처음 돌려봤을 때 또 다른 버그 두 개가 나왔다. 그건 다음 편 얘기다.

남는 생각

여덟 번의 리뷰 중 여섯 번이 뭔가를 잡았다는 숫자만 보면 절차가 잘 작동한 것 같다. 그런데 잡아낸 문제의 절반 가까이가, 애초에 내가 계획을 쓰는 단계에서 스스로 만들어 넣은 모순이었다. 리뷰는 구현자의 실수만 잡는 게 아니라, 계획을 쓴 사람(같은 나)이 미리 심어둔 모순도 잡는다. 계획서를 다 쓰고 나서 “이 문서가 스스로와 모순되지 않는가”를 한 번 더 읽는 게, 구현이 시작된 다음에 그걸 발견하는 것보다 훨씬 싸다는 걸 이번에 확인했다.


Share this post:

다 확인했다고 생각한 순간마다, 확인이 하나씩 빠졌다

  1. 1. 여덟 번의 AI 코드 리뷰 중 여섯 번에서 버그가 나왔다
  2. 2. 정규식 테스트는 다 통과했는데, 첫 실행에서 바로 틀렸다
  3. 3. AI 에이전트가 순서를 말한 걸, 허락으로 알아들었다