본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 21. 22:06

리뷰 교훈 기록하기: 피드백 루프가 내 기억력에 의존하지 않도록 만든 방법

요약

AI 에이전트의 검증 과정에서 발생하는 피드백 루프의 단일 장애점인 '사람의 기억력' 문제를 해결하는 방법을 다룹니다. 리뷰에서 발견된 누락 사항을 기록하고 자동화하는 '간극 로그(gap log)' 시스템을 통해 지속적인 개선을 구현하는 과정을 설명합니다.

핵심 포인트

  • 피드백 루프의 단일 장애점인 인간의 기억력 의존성 문제 지적
  • 간극 로그(gap log)를 통한 리뷰 교훈의 체계적 기록 방식 제안
  • open, mechanized, resolved 상태를 통한 교훈의 생애주기 관리
  • 에이전트의 검증 과정을 디스크로 옮겨 신뢰성 확보

배경 설명: 이전 글에서, 저는 반복해서 나타나는 리뷰 코멘트들을 기계적인 스캔 (mechanical scans)으로 전환하여, 에이전트 (agent)가 수백 번째로 똑같은 수동태 실수를 잡아내라고 저에게 요청하는 일을 멈추게 했습니다. 그 글과 그 이전 글은 두 가지 관점에서 동일한 아이디어를 다루었습니다. 즉, 검증 (verification) 과정을 에이전트의 머릿속에서 꺼내 디스크 (disk)로 옮겨, 에이전트의 말을 무조건 믿지 않고도 직접 확인할 수 있게 만드는 것이었습니다.

하지만 저는 '체크박스 연극 (checkbox theater)'을 고백으로 끝맺었습니다. 시스템의 한 부분은 여전히 제가 그것을 실행하는 것을 기억해야만 작동하고 있었습니다. 이 글은 그 간극을 메우는 것에 관한 것입니다. 이는 게이팅 (gating)에 관한 세 편의 글 중 마지막 편이며, 다른 두 편과 달리 실제적인 결말이 있습니다.

내가 남겨둔 미결 과제

지난번에 제가 인정한 내용은 다음과 같습니다. 모든 리뷰 후에는 리뷰어들이 잡아냈지만 여러분의 게이트 (gates)가 잡아내지 못한 것을 살펴보고, 다음번에 게이트가 이를 잡아낼 수 있도록 교훈을 기록하는 단계가 있습니다. 저에게도 그 단계가 있었습니다. 기록이 저장될 로그 (log)도 구축했습니다. 그 교훈들을 다음 리뷰에 다시 반영하는 메커니즘 (mechanism)도 작동했습니다.

문제는 트리거 (trigger)였습니다. "이제 리뷰어의 코멘트를 살펴보고 우리가 놓친 것을 기록하세요"라는 부분은 저의 몫이었습니다. 제가 에이전트에게 이를 수행하도록 프롬프트 (prompt)를 주어야 했습니다. 만약 제가 잊어버린다면(실제로 그랬습니다), 루프 (loop)는 실행되지 않았고, 체크 항목으로 굳어져야 했을 교훈들은 그냥 증발해 버렸습니다.

결국 저는 단일 장애점 (single point of failure)을 가진 피드백 루프를 가지고 있었고, 그 단일 장애점은 바로 사람이었습니다. 바로 저였습니다. 제가 구축한 그 어떤 시스템에서도 가장 신뢰할 수 없는 구성 요소 말입니다.

간극 로그 (gap log)의 실체

수정하기 전의 메커니즘입니다. 간극 로그 (gap log)는 단일 파일이며, 추가만 가능 (append-only)하고, 간극 하나당 한 줄씩 기록됩니다:

2026-04-22 | PR-1247 | clarity | "this powerful feature" not caught | resolved
2026-05-12 | PR-1268 | completeness | nav entry missing for new section | mechanized
2026-05-18 | PR-1284 | technical | dependency claim not cross-checked vs source | open

세 가지 상태가 전체 과정을 담고 있습니다. open은 간극(gap)이 기록되었지만 아직 자동화된 것이 포착하지 못했음을 의미하므로, 다음 리뷰에서 이를 읽어 추가 검사 항목으로 주입합니다. mechanized는 스캔이나 훅(hook)이 이제 스스로 패턴을 포착한다는 것을 의미하며, 해당 라인은 조용해질 수 있습니다. resolved는 근본적인 문제가 사라졌음을 의미하는데, 종종 상위 스트림(upstream)의 무언가가 변경되었기 때문에 더 이상 검사가 필요하지 않습니다.

형식은 의도적으로 지루합니다. 가치는 이를 읽는 곳에 있습니다. 다음 리뷰가 시작되기 전에, 사전 비행 단계(pre-flight step)에서 이 파일을 열어 모든 open 라인을 해당 차원의 추가 검사 항목으로 변환합니다. 한 번 나타났던 간극은 스크립트가 되거나 관련성이 없어질 때까지 매번의 후속 리뷰에 계속 나타납니다.

이것이 제가 자랑스러워하는 부분입니다. 일회성 교훈을 인프라로 전환시킵니다. PR-1284를 검토하면서 배운 것은 목요일까지 사라질 Slack 메시지에 머무르지 않습니다. 로그에 남아있고, 그 로그가 읽힙니다.

여전히 나였던 부분

하지만. 포착 과정은 수동적이었습니다. 리뷰 후에는 제가

첫 번째는 저를 기다리게 하는 것을 멈추는 것이었습니다. 저는 그동안 간극 포착 (gap capture)을 에이전트가 수행한 뒤 잠시 멈추는 작업으로 취급해 왔습니다. 즉, 간극을 찾고, 이를 open 상태로 로그에 남기고, 저에게 보여준 뒤, 체크 항목을 만들지 결정하도록 저에게 맡기는 방식이었습니다. 이는 제가 병목 현상 (bottleneck)이 될 수 있는 지점이 두 곳이나 있다는 뜻입니다. 질문을 받는 것과 승인하는 것 말입니다. 저는 이 두 가지를 모두 제거했습니다. 이제 규칙은 모든 간극에 대해 에이전트가 동일한 세션 내에서 가능한 가장 작은 결정론적 체크 (deterministic check)를 구축하고, 나중에 이를 보고하는 것입니다. 에이전트는 간극을 로그에 남기고 기다리지 않습니다. 분석 내용을 제시하고 허가를 구하지도 않습니다. 작업을 수행한 뒤, 자신이 무엇을 했는지 저에게 알려줍니다.

모든 간극이 이 과정을 통과하는 것은 아닙니다. 어떤 것들은 정규 표현식 (regex)이 흉내 낼 수 없는 판단력, 버전 인지 추론 (version-aware reasoning), 문장 내에서 읽는 이와 행위자의 차이 등을 필요로 합니다. 그러한 것들은 여전히 open 상태로 로그에 남겨지며, 왜 단순한 스캐너가 득보다 실이 많을지에 대한 이유가 기록됩니다. 하지만 기본 설정이 뒤집혔습니다. 이전에는 "로그를 남기고 John을 기다려라"였다면, 이제는 "기계화하거나, 왜 할 수 없는지 정당화하라"입니다.

두 번째 조치는 제 기억력을 대체한 트리거 (trigger)였습니다. 이제 모든 리뷰는 매 패스 (pass)마다 그 발견 사항을 작은 장부 (ledger)에 기록합니다. 이후의 패스에서 이전 패스에서 기록되지 않은 발견 사항이 나타나면, 그것은 누출 (leak)이며, 이를 감지한 체크는 0이 아닌 값 (nonzero)으로 종료됩니다. 0이 아닌 종료 값은 전체 루틴을 실행하라는 신호입니다. 즉, 근본 원인을 파악하고, 아티팩트 (artifact)를 재감사하며, 게이트 (gate)를 강화하여 간극을 메우는 것입니다. 저는 더 이상 놓친 부분을 직접 알아차릴 필요가 없습니다. 첫 번째 패스에서 포착했어야 할 사항이 두 번째 패스에서 나타나는 것, 그것이 바로 "우리가 무언가를 놓쳤다"는 상황을 기계적이고 정확하게 보여주는 모습입니다. 따라서 스크립트가 이를 알아차리며, 스크립트는 지치거나 주의가 산만해지지도 않고 회의에 불려 가지도 않습니다.

스크립트는 비교하기 전에 발견 사항을 정규화 (normalize)하므로, 줄 번호가 바뀌더라도 속지 않습니다. 동일한 문제라면 줄 번호가 다르더라도 여전히 일치하는 것으로 간만큼입니다.

A review pass runs and records its findings to a ledger. If a later pass finds something an earlier pass missed, that leak triggers a root-cause check and a re-audit; otherwise the review's gaps are collected directly. Each gap is then tested for whether it is cheap to mechanize. If yes, the check is built in the same session and the gate becomes permanently stronger. If no, the gap is logged as open with a reason, and the next pre-flight injects it into the following review.

제대로 작동할 때의 모습

추상적인 설명은 와닿지 않으므로, 세 가지 실제 사례를 들어보겠습니다.

영국식 철자 하나가 새어 나갔습니다. 자동 검토기(automated reviewers)는 통과했고, 제 스타일 게이트(style gate)의 9가지 스캔도 통과했으며, 이를 발견한 인간 검토자들은 게이트가 스스로 이를 잡아내는지 확인하기 위해 의도적으로 통과시켰습니다. 하지만 잡아내지 못했습니다. 철자 스캔 기능이 없었기에 "honour"는 9가지 스캔을 모두 통과했고, 며칠 후 제가 명시적인 미국식 영어(American-English) 패스를 실행할 때까지 이 실수는 조치되지 않은 채 남았습니다. 이 격차는 로그에 기록되었고, 동일한 세션 내에서 실제 위반 사항에는 작동하고 영국식으로 보일 뿐인 단어들에는 침묵하도록 조정된, 큐레이션된 영국식 철자 스캔(curated British-spelling scan)이 되었습니다. 이제는 다음 실수가 인간에게 도달하기도 전에 잡아냅니다.

동일한 페이지가 여러 개의 병렬 버전으로 존재했습니다. 문구 수정 사항이 일부 복사본에는 적용되었지만 다른 곳에는 적용되지 않아, 두 버전이 잘못된 용어를 유지한 채 서로 달라졌음에도 아무도 알아차리지 못했습니다. 여기서 얻은 교훈은 패리티 스캔(parity scan)이 되었습니다. 공유 페이지의 한 복사본이 변경되면, 변경된 라인을 형제 버전들과 비교(diff)하여 더 이상 일치하지 않는 부분을 표시하는 방식입니다. 이 문제를 일으켰던 정확한 사례를 통해 검증한 결과, 오탐(false positives)은 제로였습니다.

소스 코드 어디에도 존재하지 않는 설정 키(config key)가 문서화되었습니다. 그럴듯해 보이고 형식도 잘 갖춰져 있었지만, 완전히 지어낸 것이었습니다. 해결책은 '제로 히트 검색(zero-hit search)'이었습니다. 문서가 실제라고 주장하는 모든 식별자(identifier)를 가져와 실제 소스에서 검색하고, 결과가 없는 것들을 표시하는 방식입니다. 이제 에이전트는 키를 마음대로 지어내어 통과할 수 없습니다. 게이트가 문장을 믿기 전에 소스 코드에 해당 키가 존재하는지 먼저 확인하기 때문입니다.

이 각각의 사례는 단 한 번의 당혹스러운 실수로 시작되었지만, 영구적으로 실행되는 체크(check)로 끝났습니다. 이것이 로그(log)의 핵심 목적입니다. 실수는 일회성이지만, 체크는 영구적입니다.

원칙

드디어 세 가지 글의 뼈대가 하나로 연결되었습니다. '체크박스 연극 (Checkbox theater)'은 에이전트의 주장을 믿지 말고, 그것이 생성한 결과물 (artifact)을 확인하라고 말했습니다. '기계적 패턴 게이트 (Mechanical pattern gates)'는 반복해서 적는 노트를 스캔 (scan) 프로세스로 전환하라고 말했습니다. 두 가지 모두 검증 (verification)의 통제권을 에이전트로부터 분리합니다. 그리고 이 글은 개선 (improvement)의 통제권을 나로부터 분리합니다.

왜냐하면 그것이 제가 오랫동안 보지 못했던 간극이었기 때문입니다. 저는 에이전트의 검증은 기계적으로 만들었지만, 시스템의 자기 개선 (self-improvement)은 인간의 프롬프트 (prompt)에 의존하도록 남겨두었습니다. 그리고 그 인간은 바로 저였습니다. 제가 실행하는 것을 기억할 때만 작동하는 피드백 루프 (feedback loop)는, 한 단계 높은 수준의 체크박스 연극 (checkbox theater)입니다. "교훈 기록 완료"라고 적힌 박스는, 제가 기록했다고 스스로 결정함으로써 체크되고 있었으며, 디스크 상에는 제가 수행했다는 것을 증명할 아무것도 없었습니다. 동일한 실패 모드 (failure mode)가 한 층 더 높은 곳에서 발생하고 있었으며, 제대로 작동하는 프로세스의 탈을 쓰고 있었기에 더 알아차리기 어려웠습니다.

기록 (capture)은 그것이 만들어내는 체크 (check)만큼이나 기계적이어야 합니다. 그렇지 않으면 전체 시스템에서 가장 취약한 게이트 (gate)는, 다른 게이트들을 더 강하게 만드는 것이 유일한 임무인 바로 그 게이트가 될 것입니다.

현재 실제 상태

이제 루프 (loop)는 저 없이도 돌아갑니다. 간극 (gaps)은 포착되고, 기계화 가능한 것들은 동일한 세션 내에서 체크 (check)가 되며, 나머지는 이유와 함께 로그 (log)에 남습니다. 그리고 무언가가 검사 과정 사이로 빠져나갈 때 누출 탐지기 (leak detector)가 작동합니다. 저는 여전히 이 시스템 안에 있지만, 무언가를 기억해야 하는 의존 대상으로서가 아니라, 시스템이 수행한 내용을 읽는 사람으로서 존재합니다.

여전히 해결되지 않은 부분들이 많지만, 저는 그것을 괜찮다고 생각합니다. 로그에는 제가 아직 해결하지 못한 열린 라인들이 있습니다. 그것들은 저렴한 비용으로 인코딩 (encode)할 수 없는 판단력을 필요로 하기 때문입니다: 버전 인식 체크 (version-aware checks), 독자와 행위자를 구분하는 것, 그리고 단순한 스캐너 (scanner)가 나쁜 것보다 좋은 것을 더 많이 플래그 (flag)하게 되는 사례들 같은 것 말입니다. "이유와 함께 열어두기 (Open with a reason)"는 무언가를 남겨두기에 정직한 상태입니다. 목표는 결코 열린 간극을 제로(0)로 만드는 것이 아니었습니다. 목표는 제가 교훈을 배운 순간과 그것을 잊어버리는 순간 사이에서 교훈을 잃어버리는 것을 막는 것이었습니다.

그것이 바로 게이팅 아크(gating arc)입니다. 세 가지 요소, 하나의 아이디어: 에이전트(agent)가 작업을 수행하지만, 그 수행한 작업과 작업을 더 잘 수행하기 위한 과정 모두 제가 보증해야 하는 곳이 아닌, 제가 명확히 지칭할 수 있는 어딘가에 존재하게 만드는 것입니다. 만약 동일한 시스템이 작업을 수행하고, 작업을 감사(audit)하며, 작업을 개선하는 그 어떤 것이라도 구축하고 있다면, 제가 스스로 답을 얻기 위해 세 편의 글을 쓰는 데 걸렸던 이 질문을 여러분께 던지고 싶습니다. 그 세 가지 중 무엇이 여전히 당신의 기억력에 의존하고 있습니까? 그것이 바로 다음에 기계화(mechanize)해야 할 대상입니다. 여러분이 직접 찾아보았을 때 무엇을 발견하게 될지 듣고 싶습니다.

저는 AI 지원 문서화 워크플로우(documentation workflows), 개발자 경험(developer experience), 그리고 기술 작가(technical writer)의 진화하는 역할에 대해 글을 씁니다. 이 내용 중 공감되는 부분이 있다면, LinkedIn에서 연결해 주세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0