← 모든 글

AI가 PR을 만든다 — 코드 리뷰는 누구의 일인가

AI가 브랜치를 따고 PR을 올리는 시대, 결제·정산 현장에서 리뷰어의 역할은 줄지 않는다. 오히려 더 무거운 판단을 더 자주 요구받는다.

결제 코드에서 AI PR은 왜 다른 문제인가

팀에서 AI 코드 생성 도구를 본격적으로 쓰기 시작한 지 몇 달이 지났다. 자동완성 수준에서 시작해, 이제는 브랜치를 따고 커밋을 쌓고 PR까지 올리는 흐름이 일상이 됐다. 생산성은 체감상 올라갔다. 단순 CRUD, 유틸리티 함수, 보일러플레이트가 많은 영역에서는 코드 작성 시간이 2~3배 빨라졌다는 느낌이 있다. 그런데 연초에 팀원 한 명이 던진 질문이 계속 머릿속에 걸렸다. "AI가 만든 PR이면, 리뷰는 누구 기준으로 하는 거야?"

처음엔 "그냥 코드 보면 되지"라고 답했다. 틀린 말은 아니다. 그런데 결제·정산·자동화를 직접 운영하는 입장에서 이 대답은 핵심을 비껴간다. 일반 웹서비스에서 코드 한 줄이 틀리면 화면이 이상하게 뜨거나 기능이 안 되는 수준이지만, 결제 시스템에서 코드 한 줄이 틀리면 돈이 두 번 나가거나, 정산 금액이 어긋나거나, PG사 응답 코드가 잘못 매핑되어 성공 거래가 실패로 기록된다. 리뷰의 성격 자체가 다를 수밖에 없다.

결제·정산 코드에서 AI가 반복적으로 틀리는 패턴

몇 달을 써보면서 AI 생성 PR에서 우리가 반복적으로 발견한 문제는 세 가지로 수렴한다.

멱등성 처리가 허술하거나 빠진다. 결제 시스템에서 멱등성(idempotency)은 선택이 아니다. 네트워크 타임아웃으로 클라이언트가 재시도했을 때 결제가 두 번 일어나지 않도록 보장하는 것이 멱등 키의 역할인데, AI가 생성한 코드는 멱등 키를 파라미터로 받아 DB에 저장하는 흉내는 내지만 "이미 처리된 요청"을 감지하는 조건문을 종종 생략하거나 race condition이 발생하는 구조로 짠다. 실제로 우리가 리뷰 중 잡은 사례가 있다. AI가 생성한 웹훅 핸들러가 INSERT OR IGNORE 대신 단순 INSERT를 쓰고 있었다. 동시 재시도가 두 건 들어오면 중복 정산이 발생하는 구조였고, 기능 테스트만으로는 통과했을 타이밍 이슈였다.

PG사 에러 코드를 단순화해버린다. 카드사 응답 코드는 수십 가지이고, "재시도 가능 / 재시도 금지 / 카드사 문의"처럼 처리 방법이 코드마다 다르다. AI는 컨텍스트 윈도우 안에 보이는 코드를 기반으로 패턴을 추론하기 때문에, 팀이 수년에 걸쳐 누적한 에러 코드 매핑 테이블이나 과거 장애 대응에서 나온 예외 처리 로직을 제대로 반영하지 못한다. 실제로 PR에서 "5xx이면 전부 재시도"로 뭉뚱그린 코드를 발견한 적이 있다. 특정 에러 코드는 재시도할수록 카드사 측에서 해당 카드를 잠그는 케이스가 있어, 이 처리는 명시적으로 틀린 것이었다.

정산 집계에서 타임존·날짜 경계가 어긋난다. 정산은 보통 "어제 23:59:59까지의 거래"를 기준으로 끊는다. UTC와 KST가 혼재하는 환경에서 AI가 생성한 쿼리는 이 경계를 서버 타임존에 의존하는 방식으로 구현하거나, 날짜 조건을 임의로 설정한다. 스테이징에서 발견한 사례 중에는 특정 날의 23시~24시 거래가 이중 집계되는 쿼리가 PR에 포함되어 있던 것도 있었다.

세 패턴의 공통점이 있다. 기능 자체는 작동한다는 것이다. 단위 테스트를 돌려봐도, happy path에서는 아무 문제가 없다. 문제는 경계 조건, 외부 시스템의 예외 응답, 동시 요청처럼 실제 프로덕션 환경에서만 나타나는 상황에서 터진다.

리뷰의 무게중심이 이동한다

전통적인 코드 리뷰에서 리뷰어의 부담 중 상당 부분은 문법, 스타일, 변수명, 불필요한 중복 수준의 이슈였다. AI가 코드를 생성하면 이 층위의 이슈는 눈에 띄게 줄어든다. 코드는 깔끔하고, 함수 이름도 나쁘지 않으며, 타입 어노테이션도 달려 있다. 그래서 리뷰가 쉬워진 것처럼 느껴진다.

그런데 그 착각이 문제다. 줄 단위 검토가 줄어든 자리에서, 설계 수준의 판단이 더 자주 요구된다. 이 코드가 우리 시스템의 설계 원칙과 일관성이 있는가? 이미 팀 내에 같은 역할을 하는 모듈이 있지 않은가? 미래의 요구사항 변화를 감당할 수 있는 구조인가? 이 판단은 모델이 내릴 수 없다. 컨텍스트 윈도우 안에서 볼 수 있는 코드는 전체 시스템의 일부이고, 팀이 암묵적으로 쌓아온 결정들은 코드 어딘가에 흩어져 있거나 아예 문서화되지 않은 채다.

HEDVION의 정산 파이프라인이 전형적인 예다. 우리 정산 로직은 단계별로 상태를 명시적으로 관리하는 스테이트 머신 구조를 따르기로 팀이 결정한 게 있는데, 이 결정은 어느 파일에도 명시적으로 기록되어 있지 않았다. AI가 생성한 정산 관련 PR에 단계를 건너뛰거나 상태 전이를 직접 DB에서 업데이트하는 구현이 들어와 있었다. 기능적으로는 맞았다. 하지만 설계 방향과 달랐고, 이걸 잡으려면 그 결정의 맥락을 아는 사람이 봐야 했다.

속도 이득의 착시: 실제 트레이드오프

AI 도구가 코드 작성 속도를 높이는 건 사실이다. 문제는 이 속도 이득이 전체 사이클 단축으로 이어지지 않는다는 점이다. 우리가 내부적으로 추적한 결과, AI가 생성한 PR의 리뷰 사이클은 인간이 작성한 PR보다 평균 1 라운드 더 걸렸다. 이유는 명확했다. PR description이 요구사항을 재진술하는 수준에 머물러서 리뷰어가 구현 의도를 파악하기 위해 코드를 처음부터 더 꼼꼼히 읽어야 했고, "왜 이 방식인가"를 설명하는 주체가 사라졌기 때문이다. 어떤 PR에서는 팀원이 "이게 왜 이렇게 된 거야?"를 슬랙에서 먼저 묻고, 그 답을 확인한 뒤에야 리뷰가 시작됐다. 그 답도 AI한테 다시 물어봐야 했다.

외부 시스템과 붙어 있는 코드에서는 역전 현상이 더 두드러진다. 정산 자동화처럼 PG사 API, 세금계산서 발행 API, 은행 이체 API가 얽힌 코드는 테스트 환경 구성 자체가 복잡하고, AI가 만든 예외 처리가 실제 외부 응답 패턴과 다를 가능성이 높다. 이런 영역에서는 AI가 PR을 빠르게 만들어도, 리뷰와 테스트 단계에서 시간이 역으로 늘어났다. 자동 환불 처리 로직을 AI로 초안을 짰던 경험이 있다. 생성된 코드는 PG사 환불 API 호출 → DB 상태 업데이트 순서로 되어 있었다. "PG사 API는 성공했는데 DB 업데이트가 실패하면?" 이 케이스 처리가 없었다. 결과적으로 보상 트랜잭션 설계를 새로 추가하면서 리뷰 사이클이 두 배로 늘었다.

HEDVION이라면 어떻게 적용하는가

우리 팀이 AI 생성 PR을 다루는 방식은 구조화된 규칙 세 가지로 정리된다.

리뷰 체크리스트를 두 층위로 분리했다. 기존 체크리스트가 "이 코드가 올바른가"에 집중했다면, AI PR 전용 항목은 "이 코드가 우리 시스템에 맞는가"다. 구체적으로는 ① 멱등성 보장 여부, ② 에러 코드별 분기 처리 완결성, ③ 기존 유틸리티·헬퍼 중복 여부, ④ 정산 상태 전이 규칙 준수 여부, ⑤ 타임존·날짜 경계 처리 명시 여부가 별도 항목으로 들어갔다. 이 항목들은 AI가 생성한 코드에서 반복적으로 문제가 나왔던 지점에서 직접 추출한 것이다.

PR description 보완을 의무화했다. AI가 올린 PR description은 "무엇을 했는가"는 있지만 "왜 이 방식인가"와 "고려했지만 선택하지 않은 대안"이 없다. 우리는 그 PR을 트리거한 사람이 두 항목을 반드시 채우도록 팀 내 규칙을 만들었다. 한 줄이라도 좋다. 미래의 유지보수자가 코드가 아니라 맥락을 이해할 수 있어야 하기 때문이다.

결제·정산 관련 PR은 단독 승인을 금지했다. 도메인 지식이 집중된 영역은 1인 승인으로 머지하지 않는다. AI가 만든 PR이든 사람이 만든 PR이든 동일하게 적용된다. 작은 팀이라 이 규칙이 병목이 될 때도 있다. 하지만 정산 오류 한 번의 수습 비용을 생각하면 감수할 수 있는 병목이다.

바로 쓸 수 있는 실행 시사점

AI가 PR을 만드는 게 일상인 팀이라면, 아래를 지금 당장 적용할 수 있다.

1. 리뷰 체크리스트에 "도메인 일관성" 항목을 따로 추가하라. 로직 정확성 점검과 분리해서 운영해야 한다. "이 코드가 우리 설계 결정과 충돌하지 않는가"는 AI가 판단할 수 없는 영역이고, 명시적 항목이 없으면 리뷰어도 놓친다.

2. 결제·정산 코드에서 세 가지 시나리오를 필수 체크 항목으로 고정하라. 외부 API 호출이 포함된 코드는 반드시 ① API 성공 + DB 실패, ② API 타임아웃 + 재시도, ③ 이미 처리된 요청의 중복 수신 케이스를 명시적으로 확인하는 습관을 만들어야 한다.

3. AI PR의 description은 사람이 보완해야 한다. "무엇을 했는가"는 diff를 보면 알 수 있다. "왜 이 방식인가"와 "선택하지 않은 대안"을 PR에 기록하는 것은 다음 사람을 위한 투자다. AI는 이 맥락을 남기지 못한다.

4. 속도를 재는 기준을 바꿔라. AI 도구의 효과를 "코드 작성 시간"으로만 재면 착시가 생긴다. 리뷰 사이클 횟수와 프로덕션 배포 후 핫픽스 빈도까지 포함해서 봐야 실제 생산성이 나온다. 도구가 빠르게 코드를 만들어도, 리뷰와 테스트에서 더 많은 시간을 잡아먹는다면 전체 속도는 늘어나지 않는다.

5. 승인 권한과 도메인 지식을 매핑하라. 결제·정산처럼 실수 비용이 높은 영역은 해당 도메인을 아는 사람이 승인 체인에 반드시 포함되도록 구조화하라. AI 도구를 쓰기 시작하면 이 원칙이 더 쉽게 흐트러진다. 도구가 자신있게 코드를 만들어 올리면, 리뷰어도 자신있게 승인 버튼을 누르게 된다.

책임은 승인 버튼을 누른 사람에게 있다. 코드를 어떤 도구로 썼는지는 변명이 되지 않는다.

— by HEDVION Engineering

* 위 링크는 인프런 affiliate 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

📚 추천 강의
한 입 크기로 잘라먹는 바이브코딩 (with Claude Code)
Claude Code로 바이브코딩, 개발자라면 꼭 들어야 할 필수 강의
강의 보러가기 →

* 위 추천 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.