저는 처음부터 AI를 믿지 않았습니다. 지금도 믿지 않아요. 그런데 제 코드는 대부분 AI가 씁니다. 지난 글에 적었듯 일주일에 267개의 PR이 머지되는 방식으로요. 믿지 않는 상대에게 일을 맡기는 사람은 무언가를 하고 있어야 합니다. 이 글은 그 무언가에 대한 이야기입니다. 믿지 않는 데서 출발해서, 맡길 수 있게 되기까지 무엇을 쌓아 왔는지에 대한 이야기예요.
지금의 코드 리뷰는 사람을 위해 만든 통로입니다
PR을 열고, 코멘트를 달고, Approve를 누릅니다. 이 통로는 사람이 사람의 코드를 보려고 만든 것입니다. 코멘트가 자연어인 것도, 승인이 버튼 하나인 것도, 리뷰어가 무엇을 얼마나 봤는지를 따로 적지 않는 것도 전부 상대가 사람이라는 전제 위에 서 있어요. 사람은 대충 봤으면 대충 봤다는 티가 나고, 그 티를 읽어 내는 것까지가 원래 리뷰였으니까요.
여기에 AI 리뷰어를 그대로 앉히면 어떻게 될까요. 겉으로는 아무 문제가 없어 보입니다. 코멘트가 달리고 승인이 찍히니까요. 하지만 이때 제가 AI의 코드를 검토하는 통로와, AI가 제 코드를 검토하는 통로가 완전히 같아집니다. 같은 문으로 들어와 같은 버튼을 누르는데, 한쪽은 사람이고 한쪽은 아닙니다. 그 버튼에서 나온 '승인'을 제가 무슨 근거로 믿을 수 있을까요. 사람의 승인에 담겨 있던 맥락, '이 사람이 어디까지 봤겠구나' 하는 감각이 AI의 승인에는 존재하지 않습니다. 그저 있는 것처럼 보일 뿐이죠.
quickstart.id는 사람과 AI를 다른 통로로 받습니다
사실 이 고민은 처음 해 본 게 아닙니다. AI가 막 퍼지기 시작하던 무렵 서비스를 여러 개 만들면서 한 가지 질문이 계속 걸렸거든요. 'AI가 더 발달하면 사람이 쓰던 서비스를 결국 AI가 쓰게 될 텐데, 지금까지 사람을 위해 만든 규격이 AI에게도 과연 맞는 틀일까?'
quickstart.id는 그 질문에서 시작한 서비스입니다. 로그인과 권한을 다루는데, 사람과 에이전트를 같은 문으로 받지 않아요. 사람은 세션으로, 에이전트는 별도의 토큰으로 들어옵니다. 누가 왔는지, 무엇을 할 수 있는지가 처음부터 다른 경로로 기록되죠. 인증(authn)과 인가(authz)에서는 그렇게 둘을 나눠 두고서, 정작 코드 리뷰에서는 둘을 같은 문(門)으로 받고 있었던 겁니다.
다만 이 비유에는 한계가 있습니다. quickstart.id는 RFC라는 정해진 규격 위에서 동작하는 서비스예요. 사람과 에이전트를 나누는 기준이 표준으로 정해져 있으니, 제가 구축한 방식이 남에게도 그대로 적용됩니다. 하지만 코드 리뷰에는 그런 표준이 없습니다. 리뷰의 규칙은 제가 정의한 스펙이고, 그 스펙은 제 일터의 환경에서 나오니까요. 'AI 전용 통로를 두어야 한다'는 생각까지는 같을지 몰라도, 그 통로가 무엇을 기준으로 판단할지는 오롯이 제가 정해야 합니다. 그리고 이 차이가 뒤에서 아주 중요해집니다.
AI 리뷰어가 맨 아래에 하나 있는 구조로는 신뢰가 쌓이지 않습니다
AI 리뷰어가 코드를 보고 코멘트를 남기면, 제가 그걸 다듬어 읽는 구조를 떠올려 보세요. 맨 아래에 AI 리뷰어가 있고 그 위에 제가 서 있는 모양새입니다. 이건 검증이 아니라 '검증자의 복제'에 불과합니다. 지난 Meat Proxy 글에서 했던 고민과 정확히 같은 지점이죠. 제가 리뷰어와 똑같은 자료를 똑같은 순서로 읽고 있다면, 저는 그저 리뷰어를 한 번 더 반복하는 사람일 뿐 검증하는 사람이 아닙니다.
그 사실을 뼈아프게 깨달은 날이 있었습니다. 에이전트 팀을 운용하던 어느 날, 리뷰 시스템이 하루에 네 번이나 뚫렸습니다. 그런데 네 건 모두 '모든 리뷰어가 동의한 승인'이었어요. 리뷰어가 게을러서가 아니었습니다. 리뷰어에게 원문과 커밋 SHA 대신 '요약본'을 건넸기 때문이었죠. 요약만 건네받은 리뷰어는 그 요약을 작성한 에이전트와 똑같은 결론을 낼 수밖에 없었던 겁니다. 합의는 검증이 아니었습니다. 파이프라인이 같으면 인원을 늘려 봐야 같은 오류가 재현될 뿐이었어요.
또 한 번은 파이프라인의 구조적 결함으로 뚫렸습니다. PR 본문을 수정했더니, 그 PR의 head 커밋에 붙어 있던 검증 결과가 날아갔는데도 PR 상태는 여전히 'CLEAN'으로 남아 있었습니다. 검증 기록은 사라졌는데 통과 표시는 그대로 남아 있던 것이죠. 리뷰어가 아무리 똑똑해도 그 결과가 실려 오는 통로가 이렇다면, 저는 무엇도 믿을 수가 없습니다.
이 두 사건이 가르쳐 준 핵심은, 리뷰어의 가치가 성실함에 있는 게 아니라 '위치'에 있다는 사실이었습니다. 어떤 자료를 어떤 순서로 받는지, 그 결과가 어디에 어떻게 기록되는지가 리뷰의 질을 결정합니다. 리뷰어가 얼마나 열심히 읽는가는 그다음 문제죠. 그렇다면 제가 점검해야 할 것도 리뷰어 개개인이 아니라 리뷰어가 서 있는 '위치'입니다. 리뷰어의 신뢰성을 검사하는 '층(Layer)'을 하나 위에 두고, 저는 그 층을 통해 리뷰어를 바라봅니다.
지금 제가 구축한 층은 두 가지 원칙으로 작동합니다.
판단의 기준을 스펙으로 단일화하는 것: 코드가 마음에 드는지, 잘 짜였는지가 아니라 사전에 정의된 '스펙에 들어맞는가'만 봅니다.
리뷰어의 결과가 전달되는 과정에서 '요약'을 전부 제거한 것: 요약은 타인의 주관이나 판단이 개입되는 자리이고, 과거의 오류 역시 모두 그 지점에서 발생했으니까요.
기준이 스펙으로 고정되어 있으니 리뷰어가 무엇을 검토했는지 투명하게 드러나고, 요약이 없으니 리뷰어의 판단과 제 판단 사이에 왜곡이 낄 여지가 없습니다. 리뷰어 열 명을 한 명씩 신뢰하는 게 아니라, 그 열 명이 지나가는 '문 하나'를 신뢰하는 것입니다. 신뢰는 리뷰어 개인에게 쌓이는 것이 아니라, 그 층에 쌓입니다.
그 층은 완벽하지 않고, 맞춰 나가는 것입니다
여기까지 읽으셨다면 당연히 이런 질문이 떠오르실 겁니다. "그렇다면 그 층은 누가 검증합니까?" 리뷰어를 검증하는 층 위에 또 다른 검증자가 필요하고, 그 위에 또 검증자가 붙어야 하는 것 아니냐는 무한 회귀의 질문이죠.
하지만 저는 이 질문이 '완벽한 검증자'라는 환상을 전제할 때만 성립한다고 봅니다. 세상에 완벽한 시스템은 없습니다. 제가 만든 층 역시 언제든 틀릴 수 있어요. 그래서 질문을 바꿔야 합니다. '누가 이 층을 검증하는가'가 아니라, '이 층이 뚫렸을 때 어떻게 인지하고 어떻게 보완할 것인가'로요.
앞서 언급한 두 사건이 바로 그 답이었습니다. 리뷰어가 뚫렸던 날, 저는 리뷰어 모델을 교체하지 않았습니다. 리뷰어가 스펙을 기준으로 판정하도록 만들고, 결과 전달 과정에서 요약본을 걷어내도록 '층'을 수정했죠. 검증 결과가 증발했던 날 역시 리뷰어를 탓하지 않고, 머지 직전에 초록불의 출처 커밋을 재검증하도록 '층'을 보완했습니다. 층은 그렇게 사건이 터질 때마다 한 칸씩 정교해집니다. 처음부터 완벽한 층이란 존재하지 않으며, 뚫리고 덧댄 흉터들이 모여 비로소 하나의 단단한 층이 되는 것입니다.
다시 정리해보자면
이 글은 제가 구축한 층의 명세를 자랑하거나 공유하려는 글이 아닙니다. 그대로 공개해 봐야 별 소용도 없을 테니까요.
보편적인 규격(Rule)이 존재하는 영역은 '제품'이 됩니다. quickstart.id가 사람과 에이전트를 분류한 방식은 RFC라는 표준 위에 있기에 다른 사람에게도 유효합니다. 하지만 나만의 규칙을 스스로 정의해야 하는 영역은 '과정'이 됩니다. 제가 만든 리뷰 층은 제 스펙 문서, 저희 팀의 구성, 그리고 그동안 시스템이 뚫렸던 수많은 경험에 맞춰진 사적인 시스템입니다. 누군가 이걸 그대로 복사해 간다면 그곳에서는 오류투성이가 될 겁니다.
여기서 가져갈 수 있는 것이 있다면, 구조 그 자체가 아니라 '태도'입니다. 믿지 않기 때문에, 믿고 맡길 수 있는 통로를 스스로 만들어 낸다는 태도 말입니다.
물론 이 방식에도 명확한 한계가 존재합니다.
첫째, 층을 개선해 나간다고는 하지만 아직 그것을 정량적인 수치로 측정하지 못한다는 점입니다. '뚫린 날 고친다'는 것은 역설적으로 뚫리기 전까지는 결함을 알지 못한다는 뜻입니다. 시스템이 감지하지 못한 채 조용히 통과한 오류가 얼마나 될지는 저 역시 측정하지 못했습니다.
둘째, 사람의 리뷰가 완벽하다고 말하는 것도 아닙니다. 사람 역시 요약본만 받으면 똑같이 편향된 결론을 내리고, 사람의 Approve 버튼에도 검토 범위가 명시되지 않기는 매한가지입니다. 다만 사람은 대충 보았을 때 어떻게든 '티'가 나지만, AI의 리뷰는 그 티가 나지 않는다는 결정적인 차이가 있을 뿐입니다.
저는 여전히 AI를 믿지 않습니다. 달라진 것이 있다면, 이제는 AI를 믿지 않는 채로도 안심하고 일을 맡길 수 있는 '층'을 하나 갖고 있다는 사실 하나뿐입니다.

quickstart.id로 로그인