River Review의 핵심 설계: AI 리뷰가 아닌, 팀의 판단을 재현하기 쉬운 형태로 남기기
요약
본 글은 AI 에이전트 개발 과정에서 코드를 생성하는 것보다, 그 결과를 어떻게 판단하고 검증할지가 더 중요해졌음을 지적합니다. OSS River Review는 'Review Judgment as Code'를 핵심으로 삼아, 팀의 판단 기준을 리포지토리 자산으로 관리하며, 판단 과정을 Artifact, Evidence, Memory 등으로 구조화하여 제시합니다.
핵심 포인트
- 판단 기준(Judgment)을 모델 내부가 아닌 리포지토리에 버전 관리하는 Skill로 정의해야 합니다.
- 대화를 연속적인 흐름이 아닌, 재사용 가능한 Artifact와 Evidence의 경계로 다루어야 합니다.
- 검증과 생성 과정을 분리하고, 판단 결과를 Memory에 기록하여 다음 단계에 활용할 수 있도록 해야 합니다.
- 문맥(Context) 관리의 핵심은 양적 문제가 아니라 '책임 경계'를 설정하는 문제입니다.
AI 에이전트를 사용한 개발을 계속하다 보면, 문제는 점차 '코드를 작성할 수 있느냐'가 아니라 됩니다.
코드 생성은 빨라졌습니다. 반면에 어려워지는 것은 그 결과를 어떻게 판단할 것인가입니다.
- 이 구현으로 정말 괜찮은지
- 계획에서 벗어나지 않았는지
- 필요한 테스트가 실행되었는지
- AI의 지적을 신뢰해도 되는지
- 여러 리뷰 결과들을 어떻게 정리할지
- 과거의 판단을 다음 리뷰로 어떻게 계승할지
필자가 개발하고 있는 OSS River Review는 이 문제를 'AI에게 더 잘 리뷰하게 한다'는 것만으로는 해결하려고 하지 않습니다.
핵심으로 삼고 있는 것은 Review Judgment as Code입니다.
팀이 '무엇을 확인하고, 무엇을 증거(Evidence)로, 어떻게 판단할지'를 모델 안에 두는 것이 아니라 리포지토리 측의 자산으로 갖는 것입니다.
본 기사에서는 현재의 River Review를 기능 목록이 아닌, **판단을 Artifact・Evidence・Verification・Memory・Human Judgment로 나누는 책임 경계(責務境界)**로서 정리합니다. 문맥을 선택하는 방식은 그 주변의 책임으로 다룹니다. 이하 §1~§7은 판단 기준(§1) → Artifact・Evidence(§2) → 문맥(§3) → 검증(§4) → Memory(§5) → 인간의 판단(§6) → 실행 제어(§7) 순서로 배열되어 있습니다.
참고로, 본문에서 '현재의 구현'이라고 쓰인 부분은 s977043/river-review의 main 브랜치 2026-10 시점의 상태를 가리킵니다.
TL;DR
River Review의 핵심을 압축하면 다음 6가지입니다. 1~6은 §1・§2・§4・§5・§6・§7에 대응합니다. §3(문맥 선택 방식)는 주변 책임으로 다루기 때문에 여기에는 포함하지 않았습니다.
- 판단을 모델 안에 가두지 않는다. 리뷰 기준을 리포지토리 측에서 버전 관리하는 Skill로 갖는다.
- 대화가 아닌 Artifact와 Evidence를 경계로 한다. 다른 에이전트나 CI, 다른 세션에서도 재사용할 수 있는 형태로 만든다.
- 생성과 검증을 분리한다. 리뷰어의 지적을 결정론적인 검증과 Review Coverage로 확인한다.
- 대화 전체가 아닌 판단을 기억한다. Riverbed Memory(River Review에서 리뷰 판단을 기억하는 계층)에 다음 판단을 바꿀 정보(결정, 수용된 위험, 억제)를 남긴다.
- 사람에게는 모든 것을 보여주고, 판단이 필요한 부분에 주의를 집중시킨다. Finding을 숨기지 않고, 표시로 주의를 좁힌다.
- 실행 제어를 떠맡지 않는다. River Review는 Review Judgment를 반환하고, 세션/재시도/정지는 호출하는 측에 남긴다.
계기가 된 '긴 세션일수록 문맥을 다시 읽는다'는 실측
TOKIUM의 hanafusay 님의 기사 「Claude Code / Codex로 『제 한계, 너무 줄어든 건가…?』라고 생각했을 때 보는 글」은 Codex의 실제 로그 111세션・8,096요청을 집계했습니다.
여기서 보여준 것은 Prompt Cache가 높은 비율로 히트하더라도, 문맥이 커지면 1요청으로 재전송하는 양 자체가 늘어난다는 것이었습니다.
특히 눈에 띄었던 것은 대책 중 하나로 소개된 테스트나 로그 분석 같은 큰 출력을 서브 에이전트 측으로 격리하는 운영 방식이었습니다. 서브 에이전트는 병렬 처리뿐만 아니라, 방대한 문맥을 메인 에이전트에 넣지 않기 위한 경계 역할도 합니다.
River Review에 적용하면, Context Budget을 작게 하는 것만으로는 부족합니다. 무엇을 읽을지, 어떤 책임에 읽게 할지, 무엇을 근거로 남길지, 다음 판단으로 무엇을 전달할지. 문맥의 '양' 문제가 문맥을 언제 끊고 무엇을 계승할지에 대한 '책임 경계' 문제로 확장됩니다.
다만, 이 기사의 중심은 판단 기준의 배치입니다. 문맥 이야기는 그 주변에 있는 책임 중 하나로 다룹니다.
1. Review Judgment as Code: 판단 기준을 모델에서 분리하기
River Review의 출발점은 리뷰의 판단 기준을 모델이나 프롬프트 안에 두는 것이 아니라, 리포지토리 측의 자산으로 갖는 것입니다.
판단 기준이 모델이나 프롬프트 안에 있으면, 모델을 바꿀 때마다 지적이 바뀌고, 어떤 사람의 컴퓨터에서 통하던 지식도 CI나 다른 에이전트에게 전달되지 않습니다. 그래서 무엇을 볼지, 무엇을 Evidence로 삼을지, 어떤 조건에서는 지적하지 않을지를 Skill로 팀이 소유하고, fixture(Skill의 회귀를 확인할 수 있는 테스트용 입력 예시)로 회귀를 확인할 수 있도록 하고 있습니다.
예를 들어, River Review 리포지토리에 있는 AI 생성 코드용 Skill인 hallucinated-reference를 보겠습니다. 이는 생성된 코드에 섞여 있는 존재하지 않는 함수나 메서드 호출을 찾아내는 것입니다.
- 무엇을 볼 것인가: 차이점(diff)으로 새로 추가된 import나, 함수/메서드 호출 -
- 무엇을 Evidence로 삼을 것인가: 차이점의 해당 줄과, 리포지토리를 검색하여 정의가 발견된 위치(또는 발견되지 않았다는 사실) -
- 어떤 조건에서는 지적하지 않을 것인가: 같은 차이점 내에서 정의도 추가된 참조. 정의를 찾지 못했더라도, 코드 생성 등으로 만들어질 가능성을 배제할 수 없을 때는 지적이 아니라 질문으로 반환합니다.
- 회귀를 어떻게 확인할 것인가: '존재하지 않는 헬퍼를 호출하는' fixture와 '같은 변경점 내에서 정의하고 있는' 오탐지 예시를 Skill과 함께 배치해 놓았습니다.
보는 대상, 근거, 지적하지 않을 조건이 하나의 파일에 모여 있습니다.
팀이 자신만의 기준을 추가할 때도, Skill이나 프로젝트 고유의 리뷰 규칙(.river/rules.md)을 자신의 리포지토리에 두고 코드와 함께 관리할 수 있습니다. 모델은 교체되어도 괜찮습니다. 무엇을 중요하다고 생각하는지는 팀 측에 남기는 것입니다.
이것이 Review Judgment as Code이며, River Review의 컨셉 페이지(pages/explanation/concept.md)도 핵심적인 사고방식으로 삼고 있습니다. '판단 인프라(Engineering Judgment Infrastructure)'라는 용어는 같은 문서에서 현재 기능이 아니라 장기적인 방향을 가리키는 것으로 되어 있습니다.
판단 기준의 내용이나, 판단을 결정론적 체크부터 AI 리뷰, 사람의 판단까지 4단계로 나누는 생각은 'AI 코드 리뷰를 4단계로 분할. River Review의 Judgment Placement 설계'에서 자세히 다루었습니다. 이 글에서는 이 판단 기준을 중심으로 놓았을 때, 그 주변의 책임을 어떻게 나눌 것인지를 다룹니다.
2. 대화가 아닌 Artifact를 경계로 삼기
다음은 무엇을 리뷰 대상의 정본(正本)으로 할 것인가입니다.
장시간의 AI 개발 과정에서는, 대화 기록에 요구사항, 계획, 구현 이유, diff, 테스트 결과, 리뷰 결과, 수정 이유 등이 쌓이게 됩니다. 이 모든 것을 대화 안에만 두면, 그 세션 중에는 편리하지만, 다른 세션이나 CI(지속적 통합)나 다른 에이전트로부터는 재활용하기 어렵습니다.
River Review에서는 입력과 출력을 Artifact로 취급합니다. 대표적으로 다음과 같은 것들이 있습니다.
plan
diff
tests
...
채팅을 정본으로 삼지 않고, Artifact로 만들어 놓으면,
- 동일한 입력으로 재실행할 수 있고
- CI에서 이용할 수 있으며
- Claude Code와 Codex에서 공유할 수 있고
- 사람이 나중에 확인할 수 있으며
- 다음 세션으로 전달할 수 있다
라는 속성을 갖게 됩니다.
River Review를 특정 코딩 에이전트 전용으로 만들고 싶지 않은 이유도 여기에 있습니다. 실행 환경이 바뀌어도, Artifact와 Review Judgment의 계약은 유지할 수 있기 때문입니다.
3. Context Engineering: '모두 읽기'가 아닌 '판단에 필요한 것만 읽기'
Artifact화하면, 모든 Artifact를 매번 LLM(거대 언어 모델)에게 넣어야 하는 문제가 생깁니다. 이것은 하지 않습니다.
River Review에는 Context Budget이 있습니다.
현재 설정에서는 리뷰 모드별로 다음과 같은 상한선을 가지고 있습니다.
| Mode | maxTokens |
|---|---|
| tiny | 1,024 |
| ... | |
| (값의 근거: src/lib/context-presets.mjs) |
명시적인 budget을 지정할 수도 있습니다.
더 나아가, 리포지토리 전체에서 문맥을 모을 때는 후보들을 재정렬하는 메커니즘(ranking)을 설정으로 활성화할 수 있습니다. 기본적으로는 비활성화되어 있습니다.
현재 구현에서 실제로 계산하고 있는 신호는 변경 파일 간의 경로 근접성(pathProximity)
)에 불과합니다. 설정상으로는 symbolUsage
・siblingTest
・commitRecency
의 가중치도 지정할 수 있지만, 현재 구현에서는 이러한 시그널을 계산하지 않으므로 정렬에는 영향을 미치지 않습니다 (src/lib/repo-context.mjs).
생각은 간단합니다.
모두 읽는 것이 아니라, 그 판단에 필요한 Evidence에 가까운 문맥을 선택하는 것입니다.
Skill에도 Progressive Disclosure를 사용합니다.
처음부터 모든 Skill 본문이나 Reference를 prompt에 넣는 것이 아니라, 먼저 metadata에서 대상을 좁힌 후, 선택된 Skill의 상세 내용만 로드합니다.
Intent / Change
↓
Skill metadata
...
이것은 토큰 감소만의 문제가 아닙니다. 무관한 정보를 대량으로 넣으면 중요한 Evidence가 상대적으로 묻히게 됩니다. 즉, Context Budget은 비용의 예산인 동시에 주의력의 예산이라고 생각합니다.
Review Team도 '에이전트를 늘리는 것'이 목적이 아니다
River Review에는 bug-hunter / security-scanner / test-gap / dependency-reviewer 등 관점별 리뷰 역할이 있습니다.
하지만 현재 Review Team은 완전히 자율적인 독립 에이전트 그룹이 아닙니다. 하나의 orchestrator가 역할을 병렬로 실행하고, 그 findings를 merge하는 구조입니다.
Review Orchestrator
├─ bug-hunter
├─ security-scanner
...
목적은 '에이전트를 많이 움직이는 것'이 아니라, 리뷰 관점과 입력할 문맥의 책임을 분리하는 것입니다.
4. 생성(Generation)과 검증(Verification)을 분리하기
AI 리뷰에서는 지적을 내는 것과 그 지적이 옳은 것은 별개입니다.
River Review에서는 리뷰어가 제시한 지적 후보를 다른 LLM이 아닌 결정론적인 Verifier에 통과시킵니다. 확인하는 것은 근거의 참조처가 diff에 실재하는지, Skill이 선언한 심각도를 초과하지 않는지, 수정안이 있는지 등 기계로 확인할 수 있는 조건들입니다. 의미 판단까지는 결정론적일 수 없지만, 기계로 확인할 수 있는 조건까지 매번 모델에게 판단을 시킬 필요도 없습니다.
이 생각은 앞서 언급된 Judgment Placement 글에서도 다루었기 때문에, 여기서는 또 다른 분리인 Review Coverage를 중심으로 작성하겠습니다.
'Finding가 0건'과 '리뷰가 완료되었다'는 다르다
예를 들어 Security Reviewer가 timeout하여,
{
"findings": []
}
이 되었다고 가정해 봅시다. 이것은 security issue = none이 아니라, security review = not completed일 수 있습니다.
그래서 Review Coverage에서는 전체 상태를 complete / partial / not_executed 세 가지로 나누고 있습니다. '문제가 없었다'와 '확인할 수 없었다'를 같은 값으로 취급하지 않기 위해서입니다.
참고로, Review Coverage는 현재 실험적인(Experimental) 처리입니다. 기본적으로 Gate(Merge 가능 여부를 반환하는 판정)의 판단을 바꾸지 않고, JSON 결과물이나 저장된 실행 기록에 상태를 남깁니다.
반면, 리뷰를 반복하는 루프의 수렴 판정에서는 Coverage가 불완전(partial / not_executed)한 실행을 '수렴했다'고 간주하지 않습니다. 타임아웃으로 지적이 0건이 된 실행을 근거로 루프를 멈추지 않기 위해서입니다.
5. Memory는 Transcript가 아닌 Judgment를 남긴다
리뷰를 반복하다 보면, 이번에는 다른 문제가 발생합니다.
같은 지적을 매번 한다.
예를 들어,
- 이 설계 판단은 ADR(Architecture Decision Record, 설계 판단의 기록)로 결정되어 있다
- 이 의존성은 수용된 상태이다
- 이 Finding는 WontFix로 판단했다
- 이 패턴은 과거에도 확인한 적이 있다
와 같은 상황입니다.
River Review의 Riverbed Memory는 이러한 리뷰 판단을 미래의 리뷰에 재사용하기 위한 레이어입니다.
현재 저장 형식에서는 예를 들어 다음 type을 다룹니다.
adr
review
wontfix
...
여기서 남기고 싶은 것은 과거 대화 전체가 아니라, 다음 판단을 바꿀 정보입니다. type이 아닌, 남기고 싶은 정보의 분류로 나열하면 다음과 같습니다.
Decision
Constraint
Evidence
...
장시간 세션 논의와 연결하면,
대화 전체를 보존하는 Transcript Memory
과 판단을 보존하는 Judgment Memory는 별개의 것입니다. 대화 전체를 계속 가지고 있지 않아도, 판단에 필요한 상태가 Artifact와 Memory에 남아 있다면, 세션 자체는 사용하기 쉽게 만듭니다.
6. 사람에게 '전부'가 아닌 '판단이 필요한 면'을 보여주기
AI 측의 리뷰 역할이나 검증을 늘리면, 사람이 읽어야 할 정보도 증가하게 됩니다. 다음으로 문제가 되는 것은, 사람의 주의를 어디에 집중시킬 것인가입니다.
River Review에서는 이를 다음과 같은 분리로 설계했습니다.
machine-side complexity
↓
review / validation
...
전제적으로, 보여줄 양을 줄이기 위해 Finding 자체를 숨기지는 않습니다. 모든 것을 볼 수 있는 상태는 유지하되, 주의를 집중시킬 면만 좁힙니다.
사람에게 보여주는 출력은 개념적으로 다음의 3개 계층으로 나뉩니다.
L1 Decision Surface
현재 사람이 판단하는 것
L2 Resolution Summary
...
이 3개 계층을 구성하는 부품(설계상의 이름은 Organizer)은 새로운 판정 역할을 하지 않습니다. 이미 존재하는 Finding, Coverage, 검증 결과로부터, 사람이 봐야 할 표시의 구분을 결정론적으로 투영할 역할에 머뭅니다. 중요도를 재평가하거나, 지적의 진위 여부를 재판단하거나, GO / NO-GO를 결정하지는 않습니다.
Canonical Review State
↓
Organizer
...
다만, Organizer는 설계 단계에 있어 아직 구현되지 않았습니다. 지금 있는 것은 기존 판단 결과를 바꾸지 않고 표시만 하는 판단면(Decision Surface)입니다.
AI의 출력이 늘었다고 해서, 그 위에 '더 똑똑한 AI 판정 역할'을 필수 계층으로 쌓아야 한다고 생각하지 않습니다.
7. Context Lifecycle은 River Review의 코어에 넣지 않기
현재 River Review는 한 번의 리뷰에서 무엇을 문맥(Context)에 넣을지를, Context Budget, ranking, Skill의 단계적인 로딩으로 제어할 수 있게 되었습니다. 그러나 하나의 개발 세션을 언제 끝낼지는 별도의 책임입니다.
장시간 에이전트 실행에서는 구현・테스트・리뷰・수정 등이 여러 번 반복되며, 도중에 구분을 기록하고 문맥을 압축하거나 세션을 전환하여 Artifact로부터 재개하게 됩니다. 이러한 Context Lifecycle은 필요하다고 생각하지만, River Review의 코어에 세션 정책을 넣을 생각은 없습니다. 예를 들어 다음과 같은 설정입니다 (실제 존재하는 설정이 아니며, 설명을 위한 가상의 예시입니다).
soft_context_limit: 70%
rotate_after_review: true
예시의 70%는 서두의 TOKIUM 기사에서 운영상의 기준으로 언급된 값일 뿐, 기술적인 임계값은 아닙니다. 언제 세션을 끊어야 하는지에 대한 판단 기준 그 자체도 이 기사의 범위를 벗어납니다.
세션 전환, 압축, 재시도, 타임아웃, 중지는 Claude Code나 Codex, 독자 에이전트 등, 호출 측(Agent Host)의 실행 정책입니다.
River Review가 제공하는 것은, 그 전후에 필요하게 되는 판단 자료입니다.
Agent Host / Caller
├─ Session
├─ Context Lifecycle
...
River Review의 문서에서도 반복・정지・에스컬레이션은 호출 측의 책임으로 하고 있습니다. 루프 자체는 소유하지 않고, 판단 자료를 반환합니다. 이 경계를 유지한 채로, 다음 세션이 필요한 판단을 복원할 수 있는 Artifact나 Memory를 강화하는 것이 설계적으로 더 쉽다고 생각합니다.
River Review의 코어를 한 장으로 정리하면
현재 구조를 상당히 압축하면 다음과 같습니다. 사람 대상 출력은 현시점에서는 표시 전용의 Decision Surface입니다 (§6의 Organizer는 설계 단계이므로, 다이어그램에는 넣지 않았습니다).
또한, 기억에 등록하는 것은 억제(suppression) 추가나 평가 결과 저장과 같은 명시적인 조작으로 이루어집니다.
Engineering Artifacts
│
▼
...
이 바깥쪽에 세션이나 재시도, 중단을 가진 호출 측면(§7)이 있습니다. 이 분리가 현재 River Review의 핵심 설계입니다.
AI 리뷰에서 팀이 소유하는 판단으로
River Review를 만들기 시작했을 때는 'AI 리뷰를 더 좋게 하고 싶다'는 문제에서 출발했습니다. 지금은, AI에게 리뷰를 시키는 것 자체보다, 팀의 판단을 책임별로 나누고 재현 가능한 형태로 남기는 것이 중심에 있다고 생각합니다.
모델도, 에이전트도, 호출 측면도 바뀝니다. 그중에서도,
- 무엇을 중요하다고 생각하는지
- 무엇을 Evidence로 삼는지
- 어디까지 확인할 수 있었는지
- 무엇을 기억할지
- 어디서 사람의 판단으로 되돌릴지
는 팀 스스로가 소유할 수 있도록 하고 싶습니다.
River Review의 핵심은, 이를 위한 Review Judgment as Code입니다. 판단을 Artifact・Evidence・Verification・Memory・Human Judgment로 나누고, 문맥 선택 방식은 그 주변의 책임(責務)으로 다룹니다. 이렇게 함으로써 모델이나 호출 측면이 바뀌어도 동일한 기준과 동일한 Evidence로 판단을 재현하기 쉽게 하고 있습니다.
참고
- River Review (GitHub)
- River Review README
- River Review의 컨셉트
- River Review의 아키텍처
- 설정 스키마 (Context Budget / ranking)
- Review Coverage Contract
- Loop Convergence Contract
- Riverbed Storage
- ADR-012: Human Attention Architecture
- Claude Code / Codex로 '나의 한계, 너무 줄어드는가…?'라고 느꼈을 때 보는 글
관련 기사
토론

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