
AI 리뷰의 지적 사항을 자산화하기 — 추가 전용 로그와 예방 DoD로 만드는 자기 학습 루프
요약
AI 리뷰 과정에서 발생하는 반복적인 지적 사항을 데이터화하여 개발 플로우에 통합하는 자기 학습 루프 구축 방법을 소개합니다. 로그, 빈출 위반 랭킹, 예방 DoD(Definition of Done)를 활용해 에이전트가 과거의 실수를 반복하지 않도록 설계하는 구체적인 메커니즘을 다룹니다.
핵심 포인트
- AI 리뷰 지적 사항을 Append-only log로 자산화
- 빈출 위반 랭킹을 통해 리뷰 에이전트의 체크 성능 강화
- 예방 DoD를 구축하여 구현 에이전트의 셀프 체크 유도
- 회고(Retrospective)를 개발 플로우의 필수 단계로 정의
AI 리뷰를 개발 플로우에 도입한 직후, 필자의 팀은 어떤 허탈함을 느꼈습니다. 매번 똑같은 종류의 지적이 나옵니다. RORO 위반[1], 컬러 토큰(색상에 이름을 붙여 일원 관리하는 메커니즘)을 무시한 하드코딩된 hex, 전송 버튼의 중복 전송 방지 누락, 비동기 에러 무시……. 모델은 똑똑하지만, 팀의 과거 실수를 알지 못합니다. 그래서 구현을 담당하는 서브 에이전트(Sub-agent)는 같은 실수를 반복하고, 리뷰를 담당하는 서브 에이전트는 같은 지적을 반복합니다.
인간 팀이라면 이럴 때 회고(Retrospective)를 합니다. 그렇다면 AI 개발 플로우에도 회고를 포함시키면 됩니다 — 이것이 본 기사에서 소개하는 메커니즘의 출발점입니다. "AI에게도 회고를"이라는 착상 자체는 드문 것이 아니지만, 본 기사의 주제는 그 너머, 회고를 사람의 마음가짐이 아니라, 머지(Merge)해도 깨지지 않는 데이터 구조와 정해진 플로우로 구현하는 것에 있습니다.
하는 일은 간단합니다. 태스크가 끝날 때마다 리뷰 지적 사항 중 재발할 것 같은 것을 **추가 전용 로그(Append-only log)**에 쌓습니다. 로그를 집계하여 리뷰 에이전트의 **빈출 위반 랭킹(Frequent Violation Ranking)**을 업데이트합니다. 구현 전에 방지할 수 있었던 지적 사항은 **예방 DoD(Definition of Done, 제출 전 셀프 체크)**에 다시 씁니다. 그리고 효과가 있는지 장래에 판정할 수 있도록 **실측 메트릭스(Measured Metrics)**로 현재 위치를 기록합니다. 이 기사에서는 그 데이터 구조부터 실측값까지, 실제 사례를 곁들여 구현 레벨에서 보여드립니다.
1. 전체상 — 학습이 돌아가는 3가지 경로
먼저 그림 한 장입니다. 이전에 소개한 개발 플로우(Orchestrate)의 최종 페이즈에 「retrospective」라는 생략 불가능한 단계가 있으며, 거기서부터 배움이 3가지 경로로 환경에 다시 쓰여집니다.
(색상과 테두리로 역할 구분: 보라·점선 = 학습 메커니즘(retrospective·로그·랭킹·DoD·reference 반영) / 청록·실선 = 에이전트의 작업 / 노랑·점선 = 계측(테두리 및 계측 화살표 모두 점선) / 파랑·굵은 실선 = 개발 플로우. ①②③은 본문의 경로 번호)
경로 ① 「체크를 똑똑하게 만들기」: 지적 로그 → 빈출 위반 랭킹 → 리뷰 에이전트가 자주 발생하는 실수를 중점적으로 체크 (3장) -
경로 ② 「애초에 발생시키지 않기」: 예방 DoD → 구현 에이전트의 제출 전 셀프 체크 (4장) -
경로 ③ (보조) 「환경의 함정 제거하기」: 빌드 절차의 함정 등은 해당 스킬의 reference(스킬에 동봉하는 참조 문서)로 반영. 하네스 엔지니어링(Harness Engineering)의 기본 동작 그 자체이며, 본 기사에서는 상세히 다루지 않습니다.
retrospective를 실시하는 것은 플로우 전체를 지휘하는 메인 세션(지휘자)입니다. orchestrate의 종반(PR 전) 절차로서 「생략 불가능」하다고 정의되어 있습니다. 실제 플로우 정의에서 발췌하면 다음과 같습니다 (요약).
6. retrospective (학습 반영·생략 불가능. commit/PR 전에 수행하며, 학습 내용을 동일한 PR에 포함함):
이번 리뷰 지적 사항·어려웠던 점 중 「다음 태스크에서도 일어날 수 있는 것」을 선택하여,
worklog에 쓰는 것으로 끝내지 않고, 반영처를 판단하여 업데이트한다:
...
중요한 것은 retrospective가 「임의의 좋은 습관」이 아니라 플로우의 필수 단계라는 점입니다. 그리고 PR을 나누는 방식에는 대비가 있습니다: 학습 내용(로그에 추가·DoD 업데이트)은 기능 구현과 동일한 PR에 포함시키고, 반대로 랭킹의 재집계만은 기능 PR에 섞지 않고, main에서 따온 단독 유지보수(Maintenance) PR로 진행합니다. 이유는 재집계 측은 2장에서, 「동일한 PR」 측은 6장의 실패 패턴 5에서 설명합니다.
또한 전제로서, 에이전트 정의·로그·DoD는 모두 앱의 코드와 동일한 리포지토리(Repository)에서 Git으로 관리합니다. 따라서 「학습 차분이 PR에 올라간다」, 「병렬 브랜치의 머지로 인해 깨질 수 있다」는 이야기가 이후 계속 등장합니다.
2. 데이터 구조 설계 — 왜 「추가 전용 로그」인가
개인적으로 이 메커니즘 중에서 가장 이야기하고 싶은 부분이 이 장입니다. 학습 데이터의 보유 방식은 사실 AI라기보다 일반적인 데이터 설계의 문제이며, 병렬 개발과 Git의 머지까지 고려하여 결정해야 합니다.
단순한 구현은 병렬 브랜치에서 깨진다
처음에는 리뷰 에이전트의 정의 파일에 랭킹 표를 갖게 하고, 지적이 나올 때마다 횟수를 직접 「+1」 하면 된다고 생각했습니다. 이것이 병렬 개발 시 조용히 깨지게 됩니다.
브랜치 A와 브랜치 B가 동시에 실행 중이고, 양쪽 모두 「RORO 위반: 4회」를 「5회」로 업데이트했다고 가정해 봅시다. 3-way Merge (공통 조상과 양측의 변경 사항을 대조하는, Git 등이 사용하는 통합 방식)는 양쪽의 변경 사항 모두 「4→5」이므로, 통합 결과는 「5」가 됩니다. 2건이어야 할 증분이 1건으로 사라집니다. 충돌(Conflict)조차 발생하지 않기 때문에 아무도 알아차리지 못합니다 (증분 값이 서로 다르다면 충돌이 발생하겠지만, 이번에는 수동 머지(Manual Merge)를 할 때마다 오집계의 리스크를 안게 됩니다).
해결: 1지적 = 1행의 추가 전용 로그
그래서 카운터(Counter)가 아니라 **이벤트(Event)**를 기록합니다.
# Review Findings Log (리뷰 지적 사항 추가 전용 로그)
- **1지적 = 1행을 끝에 추가한다. 행의 편집 및 삭제는 금지**
(추가 전용. 병렬 브랜치 간의 3-way Merge에서 증분이 사라지지 않도록 설계됨)
...
- 2026-07-07 TICKET-123 be-review-security 인가·소유자 검증 누락 — 삭제 API에 소유자 체크 없음(IDOR)
- 2026-07-07 TICKET-123 fe-review-quality 실패 묵인/무한 스피너 — 비동기 status를 소비하지 않고 성공 화면을 무조건 그림
- 2026-07-07 TICKET-123 fe-review-ux 중복 전송 방지 결여 — 저장 버튼에 isMutating 미배선·연타 시 중복 전송
...
형식은 「날짜 티켓 번호 지적한 에이전트 이름 카테고리 — 한 줄 요약」의 1행 고정입니다. 실체는 .claude/skills/workspace-plan/reference/review-findings-log.md라는 파일 하나이며, 개발 플로우를 돌리는 스킬의 참조 문서로서 앱의 코드와 동일한 리포지토리(Repository)에 두고 있습니다.
첫 번째 줄의 IDOR[2]와 같이, 지적의 요점이 「1지적 = 1행」으로 압축되어 쌓여갑니다. 추가 전용이라 하더라도 병렬 브랜치가 동일한 끝부분에 행을 추가하면 충돌(Conflict) 자체는 발생합니다. 하지만 해결 방침은 「양쪽의 행을 모두 남긴다」는 한 가지뿐이므로, 머지(Merge)하는 사람(또는 에이전트)은 망설임 없이 기계적으로 처리할 수 있습니다. 카운터 업데이트처럼 조용히 증분이 사라지는 일은 없습니다 (이력을 새로 쓰지 않고, 발생한 일을 하나씩 추가해 나가는 「이벤트 소싱 (Event Sourcing)」이라는 데이터 설계 방식의 발상입니다).
랭킹 표는 로그로부터 만든 집계표로 위치를 정하고, 직접 편집하는 것을 금지합니다. 쌓인 기록으로부터 집계표를 다시 만든다는 일방통행 관계를 유지하는 것입니다.
재집계 절차와 트리거도 시스템화하기
「그렇다면 언제, 어떻게 다시 집계하는가". 이 부분 역시 인간의 기억에 의존하지 않습니다. 우선 절차서는 로그 파일 자체의 서두에 적혀 있습니다. 요약하자면 다음 3단계입니다.
- 로그의 모든 엔트리(Entry)를 에이전트별·카테고리별로 집계한다. 카테고리 이름은 원칙적으로 기존 랭킹 행의 이름에 맞춰 정규화하며 (예: 로그상의 「중복 전송 방지 결여」와 「중복 전송 방지 없음」은 동일 카테고리로 계산), 새로운 카테고리를 만드는 것은 기존 카테고리에 포함되지 않는 새로운 종류일 때만 수행한다.
- 각 리뷰 에이전트 정의의 「빈출 위반 랭킹」 표를 횟수 내림차순으로 다시 만든다.
- 로그 내의 마커인
last-aggregated-count를 현재의 총 엔트리 수로 업데이트한다.
집계를 자동화하는 스크립트는 아직 없으며, 유지보수 PR을 올린 사람(또는 요청을 받은 에이전트)이 이 절차서대로 실시하는 운영 방식입니다. 트리거 측은 기계화되어 있으며, 로그 안에 HTML 주석으로 마커를 심어 두었습니다.
<!-- regen-threshold: 20 -->
<!-- last-aggregated-count: 0 -->
집계 진행 상태를 로그 본체와 동일한 파일에서 관리하는 이유는, 추가 작업과 마커 업데이트가 항상 함께 운반되도록 하기 위해서입니다. 이 마커를 읽는 것은 스킬 그룹의 건전성을 체크하는 자체 제작 Lint 스크립트입니다 (필수 섹션 누락 등 스킬 정의의 손상을 검사하는 것으로, orchestrate 플로우에 「skill이나 agent 정의를 편집했다면 실행하여 green을 확인한다」라는 수동 단계로 포함되어 있습니다. 로그도 스킬 하위의 파일이므로, retrospective에서 추가할 때마다 실행 대상이 됩니다). Lint는 실행할 때마다 미집계 행 수를 표시하며, 임계값인 20행을 초과하면 「★재집계 유지보수 PR 권장」이라고 통지합니다. 참고로 20이라는 값은 경험적인 초기값이며, 근거가 있는 숫자는 아닙니다.
핵심은 알림만 보낼 뿐 lint를 fail 시키지는 않는 것(집계 지연은 사고가 아니기 때문)과, 재집계 작업을 기능 PR(Feature PR)에 섞지 않고, main 브랜치에서 분리한 단독 유지보수 PR로 수행하는 것입니다. 에이전트 정의(Agent definition)의 차이점을 기능 PR에 포함하면 리뷰의 노이즈가 될 뿐만 아니라, 진행 중인 다른 브랜치의 추가 사항과 충돌하게 됩니다.
참고로, 이 「미집계 행 수 카운트」를 담당하는 lint 측의 구현은 쉘 스크립트 십수 줄 정도입니다 (실제 코드에서 발췌. pass는 결과를 한 줄로 표시하는 자체 제작 함수입니다).
# review-findings-log.md 에서 2개의 마커를 읽음
threshold="$(sed -n 's/.*regen-threshold:[[:space:]]*\([0-9]\{1,\}\).*/\1/p' "$log" | head -1)"
last="$(sed -n 's/.*last-aggregated-count:[[:space:]]*\([0-9]\{1,\}\).*/\1/p' "$log" | head -1)"
...
거창한 기반은 필요하지 않습니다. 파일 내의 마커 2개와 grep만으로도 학습 루프의 트리거를 만들 수 있습니다.

lint-skill.sh의 실행 결과. check7이 미집계 로그의 행 수를 세고, 임계값을 초과하면 「★재집계 유지보수 PR 권장」을 출력한다 (알림만 보낼 뿐 fail은 시키지 않음)
스크린샷의 「미집계 142행」이 보여주듯, 로그에는 배움이 꾸준히 쌓이고 있습니다 (집필 시점 기준 146행). 이 저축분은 다음 재집계 유지보수 PR에서 한꺼번에 랭킹에 반영됩니다. 로그가 쌓일수록 재집계 1회당 리뷰로 흘러 들어오는 학습량은 늘어납니다 — 이 메커니즘은 루프가 진행됨에 따라 리뷰가 점점 똑똑해지는 성장형 설계입니다. 다음 단계로는 집계 자체를 에이전트에게 맡기고 인간은 승인만 하는 자동화를 고려하고 있으며, 그렇게 되면 재집계 빈도 자체도 높일 수 있습니다.
3. 경로 ① — 빈출 위반 랭킹으로 주의 배분을 변경하기
집계 결과는 각 리뷰 에이전트의 정의 파일 서두에 다음과 같은 표 형태로 삽입합니다. 초기 버전은 이 메커니즘을 도입할 때, 그때까지의 리뷰 지적 기록을 바탕으로 작성했습니다 (2장의 추가 전용 로그는 이 시점부터 비어 있는 상태로 시작하므로, 마커의 last-aggregated-count: 0은 초기값 그대로입니다). 이후의 업데이트는 2장의 재집계 유지보수를 통해 수행하며, 표 바로 아래에는 「이것은 집계 뷰입니다. 횟수를 직접 편집하지 마세요」라는 주석을 달아 두었습니다.
## 빈출 위반 랭킹 (과거 지적 사항. 횟수가 많은 관점부터 우선적으로·상세하게 확인)
| 카테고리 | 횟수 |
|---|---|
...
(표는 실제 코드에서 발췌한 것입니다. 실제로는 8개의 카테고리가 있습니다)
그리고 에이전트에 대한 지시는 다음과 같습니다.
먼저 위 빈출 위반 랭킹의 상위 카테고리부터 우선적으로·상세하게 검사하고, 그 후에 나머지 관점들을 망라한다.
이는 체크의 수고(주의력) 배분을 변경하는 것입니다. 체크리스트가 길어질수록 항목당 주의력이 분산된다는 것이 필자들의 체감이며 (인간의 훑어읽기와 같습니다), 모든 항목을 균등하게 보는 것이 아니라 「실제로 일어나기 쉬운 실수」부터 순서대로 주의를 기울이게 하려는 목적입니다. 랭킹은 그 우선순위를 팀의 실적 데이터로 결정하기 위한 메커니즘입니다.
이 표는 이제 막 성장하기 시작한 단계입니다. 횟수는 아직 최대 4회로 적고, 현시점의 순위는 「실제로 발생한 적이 있는 항목을 위에 배치한다」 정도의 의미를 갖지만, 2장의 로그에는 다음 반영을 기다리는 배움이 백여 줄 넘게 쌓여 있습니다. 재집계가 돌아갈 때마다 이 표는 팀의 실적을 반영한 우선순위로 성장해 나갑니다. 배분 변경으로 인해 검출률이 어떻게 변하는지에 대한 전후 비교는 앞으로의 측정 테마입니다.
4. 경로 ② — 예방 DoD로 지적되기 전에 제거하기
리뷰에서 검출할 수 있더라도, 검출에서 수정까지의 왕복에는 한 사이클의 비용이 듭니다. 더 좋은 방법은 처음부터 나오지 않게 하는 것입니다. 회고(retrospective)에서는 「이 지적 사항은 구현 전 셀프 체크로 방지할 수 있었는가?」를 분류하고, 방지할 수 있었던 것은 **예방 DoD (Definition of Done)**에 추가합니다.
예방 DoD는 구현 에이전트가 제출 전에 항목별로 자신에게 적용하는 채점표입니다. 모두 YES/NO로 판정할 수 있는 형태로 통일되어 있습니다. 실제 파일은 백엔드용과 프론트엔드용 2개 파일(.claude/skills/backend/reference/ 및 .claude/skills/frontend/reference/)로 구성됩니다.
([IMG:N]에 배치)하며, 구현 에이전트(Implementation Agent) 정의의 「자기 검증 (반환 전 필수)」 섹션에서 경로로 참조하도록 하고 있습니다. 몇 가지 항목을 발췌하면 다음과 같습니다.
- [ ] 비동기 처리 후크(Asynchronous processing hook)가 반환하는 status (loading/success/failed)를 UI에서 반드시 소비하고, 성공 화면을 무조건 그리지 않는다 (무한 스피너/실패 무시를 만들지 않는다). 출처: TICKET-123
- [ ] 전송 버튼의 disabled/loading에 mutation의 isMutating/isPending을 연결한다
...
체크 결과는 구현 에이전트가 지휘자(Conductor)에게 반환하는 요약(Summary)의 고정 필드로 보고하게 합니다 ("예방 DoD 자기 체크: NO였던 항목과 대처법만 열거. 모든 항목이 YES라면 그 내용을 한 줄로 작성"). 별도의 전용 기록 파일을 만들지 않고, 요약(Summary)과 워크로그(worklog)에 남는 형태입니다.
추가되는 항목에는 「출처」가 붙는다
회고(Retrospective)에서 추가되는 항목에는 1, 2번 항목처럼 출처인 티켓 번호를 붙입니다. 이는 규칙이 「누군가의 취향」이 아니라 「실제로 발생한 사고」임을 보장하기 위함입니다. 나중에 「이 규칙 정말 필요한가?」라는 의문이 생겨도, 출처까지 거슬러 올라가 판단할 수 있습니다. 규칙의 근거를 언제든 추적할 수 있도록 해두는 것은 규칙이 계속 늘어나는 메커니즘에서는 특히 중요합니다 (3번 항목과 같은 초기 정비분에는 출처가 없는 것도 있으며, 실제 사례에서 출처가 붙은 것은 약 3분의 2 정도입니다).
자기 신고의 함정
운영해 보며 알게 된 중요한 교훈이 있습니다. 자기 체크(Self-check)를 자기 신고(Self-declaration) 방식으로 두면 제대로 작동하지 않습니다. 실제로 있었던 사고 중에는, 「비동기 에러를 catch 하고 있는가」라는 항목에 구현 에이전트가 「YES」라고 신고했음에도 불구하고, grep으로 확인해 보니 catch가 없는 곳이 2군데 남아 있어 리뷰에서 P0로 검출된 사례가 있었습니다.
대책은 체크 항목 자체에 검증 방법을 적는 것입니다.
- ⚠️ 이 체크는 「grep을 실행하여 실제로 catch가 있는지」로 확인할 것.
(「YES」라는 자기 신고만으로 통과시키지 말 것)
지난 리뷰 수렴 규칙에서 「'대체로 대응 완료'로 말을 바꾸는 것 금지」를 소개했지만, 사상은 같습니다. LLM을 상대로 하는 규칙은 성선설에 기반해 작성하지 마십시오. 판정을 선언이 아니라 검증(grep, lint, 실행)에 연결해야 합니다.
물론 「grep을 실행했는가」 자체도 또한 자기 신고입니다. 이 부분을 완전히 통제할 수는 없으므로, 경로 ②를 단독으로 신뢰하지 않고, 예방 DoD에서 누락되더라도 경로 ①의 리뷰(다른 컨텍스트의 에이전트)가 동일한 관점을 독립적으로 검사하도록 다층 방어 체계를 구축하고 있습니다. 예방은 왕복 비용을 줄이기 위한 제1층이지, 최후의 보루는 아닙니다.
5. 효과 측정 — metrics 행으로 「예방이 효과가 있었는지」를 계산하기
시스템을 만들면 그것만으로 만족해버리기 쉽습니다. 하지만 효과가 있는지 없는지는 별개의 문제입니다. 그래서 orchestrate 실행 시에는 worklog에 grep 가능한 정형화된 행을 반드시 기록하도록 규칙을 정했습니다 (서식은 worklog 템플릿에 「단일 진실 공급원 (Single Source of Truth)」으로 정의되어 있습니다).
- metrics: 최초 리뷰 BE P0=n P1=n / FE P0=n P1=n (변경 파일 m건)
- metrics: 반복 횟수 BE=n FE=n 중단=none|상한|정체|진동
- metrics: 최종 게이트 fail n건 (typecheck=n unit 테스트=n e2e=n)
...
(3행의 e2e는 컨트롤러 변경 시에만 추가되는 체크이며, 일반적인 최종 게이트는 typecheck와 유닛 테스트입니다. 2행의 중단 조건 「상한·정체·진동」은 이전에 정의한 강제 중단 조건입니다 — 상한=3회 반복, 정체=이전 회차보다 P0/P1 잔여 수가 줄어들지 않음, 진동=동일한 지적 사항이 2회 연속 남거나 수정이 반복됨)
설계 의도를 몇 가지 나열하겠습니다.
- 반드시 분모를 붙인다. 「P1이 16건」이라고만 하면 많은 것인지 적은 것인지 알 수 없습니다. 변경 파일 수를 분모로 곁들여, 태스크 규모를 동일하게 맞추어 비교할 수 있도록 합니다.
- 「예방 가능한 위반 (Preventable Violation)」을 가장 중요한 지표로 삼는다. 첫 번째 P0/P1 지적 사항 중, 기존의 예방 DoD (Definition of Done)나 랭킹 게재 항목에 해당하는 건수입니다. 즉, "기존 실수의 재발"입니다. 새로운 종류의 지적 사항은 나와도 괜찮습니다 (기존 지식에 얽매이지 않고 체크가 작동하고 있다는 증거라고 생각합니다). 줄이고 싶은 것은 기존의 실수뿐이며, 이 숫자의 감소가 예방 메커니즘의 직접적인 효과입니다.
- 판정 근거를 남긴다. "기존 항목에 해당하는가"에 대한 판정은 지휘자(메인 세션)가 첫 번째 지적 사항 리스트를 기존 예방 DoD 및 랭킹 항목과 대조하여 수행하며, 어떤 항목에 해당했는지를 worklog에 열거하여 남깁니다. 판정자가 LLM인 이상 이 분류에도 편차가 발생할 수 있지만, 근거가 남아 있다면 나중에 사람이 검산할 수 있습니다.
- 그 자리에서 기록한다. 첫 번째 리뷰 통합 직후에 기록하며, 나중에 몰아서 쓰는 것은 금지합니다. 기억에 의존한 기록은 누락되거나 왜곡되기 마련입니다.
- metrics:
접두사(Prefix)를 고정해 두었으므로, 집계는 원라이너(One-liner)로 끝납니다.
grep -rh "- metrics:" .claude/workspace/*/worklog.md
실측값
실제 태스크에서 몇 가지를 발췌합니다 (티켓 번호는 마스킹 처리했습니다).
| 태스크 | 변경 규모 | 첫 번째 리뷰 지적 (P0 / P1) | 그 중 예방 가능한 위반 | 수정 회차 | 중단 |
|---|---|---|---|---|---|
| A (BE+FE 중규모) | 16파일 (BE8+FE8) | BE: 0 / 3, FE: 0 / 4 | 7건 중 4건 | BE=1, FE=1 | 없음 |
| ... | |||||
| ※ 표는 5행이지만, D와 E는 동일한 태스크를 FE / BE 트랙별로 기록한 것이므로 독립된 태스크로서는 4건입니다. E는 P0/P1이 0이고 P2만 6건 있으며, 수정 회차 1은 해당 P2 지적에 대한 대응 결과입니다. |
데이터는 아직 적으며, 이는 효과 측정을 위한 출발점입니다. 이 표의 값이 기준선(Baseline)이 되며, 이로부터의 추이를 통해 "예방이 효과를 발휘하고 있는가"를 숫자로 판정해 나갈 것입니다. 출발점의 측정만으로도 이미 알 수 있는 사실이 있습니다.
- 첫 번째 P0/P1 지적의 약 4할(합계 22/53건)이 "기존 실수의 재발"이었다. 태스크 단위로는 약 28%(C: 18건 중 5건)에서 약 83%(D+E 합계: 6건 중 5건)까지 편차가 크며, 합계 값이 최대 태스크 B(22건)에 의해 강하게 끌려가고 있다는 점에는 주의가 필요합니다. 이 4할은 예방 메커니즘으로 깎아낼 여지가 그만큼 크다는 것을 의미합니다. 기존의 실수는 리뷰와 수정의 루프가 검출하여 고칠 수 있지만, 제출 전에 없앨 수 있다면 그 왕복 비용 자체를 없앨 수 있습니다. 루프가 돌아가며 로그와 DoD가 성장할수록 이 숫자는 내려갈 것이며, 그것을 확인할 수 있는 상태를 만든 것이 이번 측정의 가치입니다.
- 수정 루프는 1~2회 내에 수렴하고 있다. P0/P1이 발생한 태스크는 모두 1~2회 내에 해소되었으며, 상한 3회·정체·진동에 의한 중단은 측정 시작 이후 제로입니다. 정확히 말하면, 이는 "안전장치가 작동할 상황이 아직 오지 않았다"는 뜻이기도 하며, 중단 규칙이 실전에서 올바르게 작동할지는 향후 검증 사항입니다.
- 측정하지 않았다면, 둘 다 "감각"에 머물러 있었을 것이다. 메커니즘의 효과를 말할 때 "체감상 좋아졌다"라고밖에 말할 수 없는 것은, 검증 메커니즘 (Verifier)을 만드는 측으로서 설득력이 없습니다.
숫자의 겉모습보다, 숫자를 뽑아낼 수 있는 상태를 먼저 만드는 것. 이것이 이 장에서 가장 하고 싶은 말입니다.
루프를 스마트하게 만들기 위한 다음 단계
이 메커니즘은 여기서 완성되는 것이 아니라, 돌리면서 키워나간다는 전제하에 움직입니다. 성장 가능성으로서 생각하고 있는 다음 단계를 몇 가지 적어둡니다.
- 리뷰 지적 사항의 타당률 측정. 「망설여지면 지적한다」는 방침 때문에 지적 사항에는 일정 수준의 노이즈가 섞입니다. 타당률을 측정할 수 있다면 「지적이 줄었다 = 좋아졌다」를 더욱 강력하게 말할 수 있게 됩니다. -
- 운영 비용 측정. 회고 (retrospective)와 메트릭 (metrics) 기록이 태스크당 몇 분·몇 토큰을 증가시키는지 정량화하여, 리턴(return)과 대조할 수 있도록 합니다. -
- 플로우 실시의 기계화. 회고 (retrospective) 및 기록 실시는 현재 기술 기술 규범으로 담보하고 있지만, 메트릭 (metrics) 행의 존재를 린트 (lint)로 검사하는 등의 기계화를 통해 「성선설에 의존하여 작성하지 않는다」를 시스템 자체에도 적용해 나갑니다. -
- 예방 DoD의 신진대사. 추가적인 운영 (항목별·이진적 (binary) 표현)은 이미 확립되었으므로, 다음으로는 효과가 없어진 항목을 퇴역시키는 기준을 마련하여 리스트를 탄탄하게(muscular) 유지합니다.
6. 실패 패턴·안티 패턴 모음
실제 운영에서 겪은 것, 설계 단계에서 회피한 것을 정리합니다 (본문의 요점 재게시를 포함합니다).
- 랭킹 표의 직접 편집— 병행 브랜치의 머지 (merge) 과정에서 증분 데이터가 사라집니다 (2장 참조). 대책: 카운터가 아니라 이벤트를 기록하고, 표는 재생성한다. -
- 「나중에 한꺼번에 기록」— 기억에 의존하는 워크로그 (worklog)는 현실과 괴리됩니다. 대책: 「작업 완료 = 문서 업데이트까지」를 플로우의 정의에 포함한다. -
- 체크리스트의 무한 비대화— 실수할 때마다 항목을 추가하면 리스트가 길어져 모든 항목을 대충 훑어보게 되고, 항목당 주의력이 분산됩니다. 대책: 기존 카테고리에 계상하는 것을 우선하며 (로그 행 추가와 명칭 통일로 계산. 표의 직접 +1이 아님), 신규 항목은 기존 카테고리에 담기지 않는 새로운 종류로만 한정한다. 빈도순으로 정렬하여 주의력을 상위로 집중시킨다. -
- 자기 체크의 자기 신고— 단순히 「YES」라고 말하게 하는 것만으로는 기능하지 않습니다. 대책: 검증 커맨드 (grep·lint)까지 항목에 작성한다 (4장 참조). -
- 학습 반영을 「임의」로 두기— 임의적인 회고는 반드시 스킵됩니다. 대책: 회고 (retrospective)를 플로우의 필수 단계 (PR 전·생략 불가)로 편입시키고, 학습 내용을 동일한 PR에 포함한다. 이렇게 하면 기능이 main에 도달할 때 학습 내용도 함께 도달합니다. -
- 중요도의 임의 강등— P1에서 P2로의 강등을 AI의 독단으로 허용하면, 지적 사항을 묵살하는 데 악용됩니다. 대책: 강등은 이유와 함께 대장 (worklog 내에 생성하는 연번 ID·관점·중요도·상태의 지적 목록표. 이전의 수렴 규칙 참조)에 기록하고, 사용자 승인 사항으로 만든다.
요약 — 「환경이 학습하기」 위한 최소 구성
지금까지 작성한 메커니즘은 한 번에 완성된 것이 아니라, 운영하면서 조금씩 더해온 것입니다. 오늘부터 시작한다면 최소 세트는 이 정도라고 생각합니다.
- 지적·실패를 기록하는 추가 전용 장소를 파일 1개로 만든다 (1지적=1행이라면 형식은 무엇이든 상관없음) - 리뷰용 프롬프트 (에이전트 (agent) 정의)에 「과거 빈출 실수」 섹션을 마련하고, 처음에는 수동이라도 좋으니 로그로부터 반영한다.
- 지적 사항을 「구현 전에 막을 수 있었는가?」로 분류하고, 막을 수 있었던 것은 제출 전 체크리스트 (예방 DoD)로 보낸다. 반드시 출처를 기재한다.
- 반영 타이밍을 플로우에 고정한다 (PR 전 등. 「마음 내킬 때」로 두지 않는다).
- 효과를 하나의 숫자로 측정한다 (추천하는 방식은 「기존 실수의 재발 횟수」).
제1회에서 소개했듯이, 하네스 엔지니어링 (harness engineering)이라는 용어를 정착시킨 Mitchell Hashimoto[3]는 이를 「에이전트가 실수할 때마다, 같은 실수가 일어나지 않도록 환경 측에 영구적인 수정을 넣는」 사고방식이라고 정의했습니다. 본 기사의 메커니즘은 그것을 사람의 마음가짐에 의존하는 것에서 데이터 구조와 정해진 플로우로 재설계한 것입니다. 목표는 모델의 진화를 기다리지 않고도, 현재 모델 그대로 환경의 학습을 통해 성적이 올라가는 상태를 만드는 데 있습니다.
실측이 보여주는 현재 위치는 「기존 실수의 재발이 약 4할」입니다. 여기서부터 루프가 돌 때마다 로그가 쌓이고, 랭킹과 DoD가 업데이트되며, 환경은 조금씩 똑똑해져 갑니다. 시리즈 타이틀인 「같은 실수를 두 번 다시 하지 않는다」를 숫자로 향해 다가가는 것을 확인할 수 있는 상태 — 그곳까지의 토대(foundation)가 마련되었습니다.
다음은 최종회입니다. 이 「닫고·측정하고·학습을 다시 쓰는」 형식을 외관 체크로 확장한, Figma to Code의 측정 우선(measurement-first) 구현을 소개합니다.
참고 링크
-
엔지니어의 Agent Loop를 정비하는 기술 ─피드백 루프(Feedback Loop) is All You Need─ (karamage)
-
Scoped Meta-Harness: 기업 AI 에이전트에서의 자기 개선 루프(Self-improvement Loop) 설계 이론 (shark_same_same)
-
Claude Code로 하네스 엔지니어링(Harness Engineering)을 실천하기 — 5개 층의 설계 패턴 (sasadango28)
-
Loop Engineering 입문 (suwash)
RORO = Receive an Object, Return an Object. 함수의 인자(Argument)와 반환값(Return value)을 객체(Object)로 통일하는 설계 규약. ↩︎
IDOR = Insecure Direct Object Reference. ID를 변경하는 것만으로 타인의 데이터에 접근할 수 있는 인가 누락 취약성. ↩︎
Mitchell Hashimoto 「My AI Adoption Journey」 (2026년 2월, https://mitchellh.com/writing/my-ai-adoption-journey). 본인은 「업계에 정착된 용어가 있는지는 모르겠지만」이라는 단서를 달고 명명했습니다 (경위는 제1회 참조). ↩︎
Discussion

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