내가 코딩하고, AI에게는 계속 의심하게 했다

이번 작업은 AI에게 구현을 맡겨보는 실험이 아니다. 회사 업무에서 요구사항 정리와 설계 수정, 실제 구현은 내가 직접 진행하고, AI에게 맡긴 영역은 범위를 명확히 지정한 일부 라이브러리 문제 분석, 구현이 끝난 뒤의 코드 리뷰, 그리고 릴리즈 노트 초안 정리였다.

 

처음부터 AI 리뷰를 계획했던 것도 아니다. 기획에서 UX 변경 요청이 들어왔고, 그 변경을 반영하는 과정에서 여러 곳에 흩어져 있던 상태 관리까지 하나의 기준으로 정리하게 됐다. 수정 범위가 점점 넓어졌고, 작업이 끝났을 때 변경 파일은 43개까지 늘어 있었다. 기능은 내가 의도한 방향으로 구현했지만, 이 정도 범위를 한 번에 수정하면 사소한 실수가 섞일 가능성이 있다. 그래서 구현을 다시 AI에게 맡기는 대신, 반대로 완성된 변경분을 최대한 의심하게 해보기로 했다.

변경되거나 추가된 파일 43개,  리뷰를 따로 돌려보기로 했다

이번 변경은 단순히 화면 하나를 추가하는 작업으로 끝나지 않았다. UX 변경을 반영하면서 기존에 여러 모듈에서 제각각 관리하던 상태를 공통 기준으로 통일했고, 프로토콜과 화면 상태, 서버 전송 조건처럼 서로 연결된 부분도 함께 손봤다. 각각의 변경 이유에 대해 나는 정확히 알고 있어 “여기는 원래 이렇게 동작해야 한다”는 전제가 머릿속에 있으니, 오타나 빠진 조건처럼 작은 문제는 오히려 지나치기 쉽다.

 

신규 화면이 추가되었기 때문에 어느정도 변경을 생각하였으나, 동일 의미의 상태 관리가 중복 정의되어 있어, 이번 기회에 함께 정리하게 되어 생각보다 변경 사항이 많아 이 부분을  대상으로 AI 코드 리뷰를 진행했다. 그래서 AI에게 릴리즈 노트를 바탕으로 현재 변경 코드가 의도대로 구현됐는지 검토하게 했다. 특히 상태 전이, 프로토콜 분기, 타임아웃, 화면 객체 관리처럼 변경 범위가 넓을 때 실수하기 쉬운 부분을 중심으로 보게 했다.

첫 리뷰는 생각보다 심각했다

첫 리뷰에서는 꽤 많은 문제가 지적됐다. 사용자 동의가 실제로 무시될 수 있다는 판단도 있었고, 특정 프로토콜 기능이 항상 활성화되는 것이 문제라는 지적도 있었다. 화면 객체를 잘못 공유하거나 정리하지 않아 문제가 생길 수 있다는 의견도 나왔다.

 

코드만 놓고 보면 충분히 의심할 만한 부분들이었다. 하지만 내용을 하나씩 확인해보니 일부는 버그가 아니라 제품 정책과 실행 순서를 모르면 오해하기 쉬운 설계였다. 예를 들어 차량과 충전기 사이에서 정보를 교환하는 것과, 그 정보를 실제 서버로 전송하는 것은 같은 의미가 아니었다. 프로토콜 초기 단계에서는 통신을 먼저 진행하고, 이후 사용자 선택과 제품 정책에 따라 실제 활용 여부를 결정하는 구조였다. AI는 코드에 드러난 조건만 보고 두 단계를 하나의 동의 흐름으로 해석했다.

AI의 지적을 그대로 수정하지 않았다

여기서 AI가 지적했다는 이유만으로 코드를 고치지는 않았다. 왜 현재 구조가 필요한지 제품 정책과 실제 동작 순서를 다시 설명하고 재검토를 요청했다. 설명을 반영한 두 번째 리뷰에서는 처음의 주요 지적 중 상당수가 철회됐다. 초기 단계에서 특정 기능을 먼저 활성화하는 것도 의도된 동작이었고, 사용자 입력이 없는 제품에서 자동으로 처리하는 부분 역시 제품 정책이었다. 화면 전환 역시 일반적인 객체 생성·삭제 방식이 아니라 임베디드 UI 환경에서 사용 중인 Show/Hide 구조를 전제로 하고 있었다.

 

이 과정에서 AI 리뷰의 역할도 명확해졌다. AI가 버그 여부를 최종 판정하는 것이 아니라, 코드만 봤을 때 이상해 보이는 부분을 넓게 찾아내고 개발자가 제품 맥락을 대입해 실제 문제인지 판단하는 방식이 더 적절했다.

오탐을 걷어내자 실제 실수가 남았다

그렇다고 리뷰가 헛돈 것은 아니었다. 제품 정책을 설명하며 오탐을 걷어내는 동안 실제로 수정할 부분도 발견됐다. 빌드 조건에 사용되는 매크로 이름의 오타가 있었고, 상태 enum을 도입한 뒤에도 일부 코드에는 예전 숫자 비교 방식이 남아 있었다. 사용되지 않는 지역 변수와 enum 명칭의 오타도 정리 대상이 됐다. 코드 동작 전체를 뒤집을 만한 설계 오류는 아니었지만, 변경 파일이 많아진 상황에서 사람이 놓치기 쉬운 종류의 문제였다.

 

특히 상태 비교는 단순히 숫자 하나를 비교하는 것과 “동의 이전의 모든 상태”를 의미하는 조건이 서로 달랐다. AI가 그 차이를 지적했고, 의도를 다시 확인한 뒤 상태 enum의 의미에 맞도록 비교 기준을 통일했다. 수정은 직접 했다. 수정할 때마다 다시 리뷰를 요청했고, 남은 지적을 하나씩 확인했다.

AI도 현재 코드를 항상 제대로 보고 있는 것은 아니었다

재검토 과정에서는 반대 방향의 실수도 있었다. 이미 화면 객체의 부모 관계를 수정했는데 AI는 작업공간에서 이전 상태를 읽고 여전히 수정되지 않았다고 판단했다. 에디터에서 보이는 코드와 AI가 확인한 저장 상태가 달랐고, 화면을 다시 확인시킨 뒤 저장된 작업 트리를 기준으로 재검토하게 했다. 그 결과 해당 지적은 철회됐다.

 

이 경험은 AI 리뷰 결과 자체도 검증 대상이라는 점을 다시 보여줬다. AI가 자신 있게 문제라고 말해도 현재 파일을 제대로 읽었는지, 제품의 실행 조건을 알고 있는지, 개발자가 의도한 정책과 같은 전제를 가지고 있는지 확인해야 했다.

릴리즈 노트도 AI 결과를 그대로 쓰지 않았다

코드 리뷰가 끝난 뒤에는 변경분을 다시 읽혀 상세 릴리즈 노트를 만들었다. AI가 정리한 문서는 변경 내용을 빠짐없이 펼쳐보는 데는 유용했지만, 실제 회사에서 사용하는 릴리즈 노트 내용으로 사용하기에는 코드 레벨에서 세세히 작성된 부분은 과감히 버리고, 사내 양식에 맞춰 다시 압축했다. 기능 개선과 버그 수정이라는 기존 구조를 유지하고, 세부 구현 설명보다는 기획 변경, 상태 관리 통일, 프로토콜 처리 개선처럼 실제 릴리즈에서 의미 있는 항목만 남겼다.

 

결국 문서화에서도 역할은 같았다. AI가 변경사항을 넓게 펼쳐주고, 어떤 내용이 제품 관점에서 중요한지는 개발자가 결정해야 했다.

회사 업무에서의 AI 협업은 개인 프로젝트와 달랐다

사이드 프로젝트에서는 구현 자체를 AI에게 맡기는 실험도 해왔다. 하지만 회사 코드에서는 접근 방식이 달랐다. 요구사항을 해석하고 설계를 바꾸고 실제 코드를 작성하는 것은 내가 담당했다. AI에게는 내가 지정한 범위의 분석과 사후 검증을 맡겼다.

 

이번 작업을 통해 변경 범위가 넓은 작업에서는 이 방식이 꽤 유용하다는 생각이 들었다. AI가 제품을 대신 이해해주는 것은 아니었고, 실제로 제품 맥락을 몰라 잘못 지적한 부분도 있었다. 반대로 개발자가 너무 익숙해서 지나친 작은 실수는 AI가 집요하게 찾아냈다. 중요했던 것은 AI의 답을 정답으로 받아들이는 것이 아니라 계속 근거를 확인하는 것이었다. 잘못된 지적에는 설계 이유를 설명했고, 실제 문제는 직접 수정한 뒤 다시 의심하게 했다. 반복 검토가 끝났을 때 코드 리뷰 기준으로 남은 지적사항은 없었다.

 

코드는 내가 작성했고, AI에게는 계속 의심하게 했다.

이번 작업에서 가장 정확한 AI 활용 방식의 설명은 아마 이 문장일 것 같다.