Tenure — 시간이 흐를수록 신뢰를 쌓아가는 AI 코드 리뷰어 구축하기
요약
Tenure는 팀의 코드 리뷰 피드백을 학습하여 팀 고유의 컨벤션을 스스로 구축하는 AI 코드 리뷰어입니다. Hindsight 메모리 시스템을 통해 제안, 경고, 차단 단계로 규칙을 승격시키며, 팀의 실제 행동에 기반해 신뢰를 쌓아갑니다.
핵심 포인트
- 팀의 피드백(수락/거절)을 기반으로 컨벤션 자동 업데이트
- Hindsight 메모리를 통한 월드 팩트 및 경험 팩트 관리
- 제안에서 차단까지 3단계 신뢰 계층 시스템 적용
- 설정 파일 없이 관찰된 행동만으로 자기 억제 및 규칙 승격
문제점
모든 팀에는 명문화되지 않은 규칙이 있습니다.
"인라인 주석(inline comments)은 사용하지 않는다." "조기 반환(Early returns)만 사용한다." "프로덕션 환경에서 console.log를 사용하지 않는다."
이러한 규칙들은 시니어 개발자들의 머릿속에 존재합니다. 그들이 떠나면 — 규칙도 함께 떠납니다.
기존의 AI 리뷰어들은 도움이 되지 않습니다. 그들은 상태가 없는(stateless) 방식입니다. 모든 PR(Pull Request)은 제로(zero) 상태에서 시작됩니다. 그들은 팀이 이미 무시하기로 결정한 사항들을 지적합니다. 그들은 결코 학습하지 않습니다.
그 결과는 무엇일까요? 개발자들이 무시하는 법을 배우게 되는 소음 가득한 리뷰입니다. 양치기 소년처럼 행동하는 AI는 완전히 무시당하게 됩니다.
아이디어: Tenure
만약 코드 리뷰어가 팀이 자신의 제안에 어떻게 반응하는지를 관찰하고 — 그에 따라 자신의 표준을 업데이트할 수 있다면 어떨까요?
그것이 바로 Tenure입니다. Hindsight(지속성 메모리)와 NVIDIA Nemotron 3 Super(리뷰 엔진)를 기반으로 시간이 흐를수록 신뢰를 쌓아가는 AI 코드 리뷰어입니다.
Tenure는 제안하는 것부터 시작합니다. 팀이 코멘트를 수락하거나 거절함에 따라, Tenure는 증거를 구축합니다. 한 방향으로 충분한 증거가 쌓이면 — 하나의 컨벤션(convention)이 승격됩니다:
제안(Suggest) → 경고(Warn) → 차단(Block)
어떤 사항을 3번 거절당했나요? Tenure는 해당 카테고리에 대해 침묵합니다. 설정 파일도, 규칙 편집기도 필요 없습니다. 그저 관찰된 행동만 있을 뿐입니다.
다른 에이전트들은 기억하지만, Tenure는 신뢰를 얻습니다.
메모리 작동 방식
Tenure는 두 가지 유형의 메모리를 가진 하나의 Hindsight 뱅크를 사용합니다:
월드 팩트(World Facts) — 팀의 명시적인 선호도. 예: "우리는 조기 반환을 사용한다", "매직 넘버(magic numbers)는 사용하지 않는다".
경험 팩트(Experience Facts) — Tenure가 직접 학습한 결과. 예: "나의 console.log 제안은 계속 거절당한다", "나의 네이밍(naming) 제안은 일관되게 수락된다".
이러한 사실들은 관찰 결과(observations)로 추출됩니다 — 즉, 증거 횟수와 최신성을 추적하는 가중치가 부여된 컨벤션입니다. 각 컨벤션은 세 가지 신뢰 계층 중 하나에 속합니다:
제안(Suggest, 증거 횟수 12회): 부드러운 힌트로 표시됨4회): 강조 표시되어 무시하기 어려움
경고(Warn, 증거 횟수 3
차단(Block, 증거 횟수 5회 이상 안정적): 머지(merge)를 제한함
계층은 추세가 강화되면 승격되고, 반박되거나 약화되면 강등됩니다.
세 가지 핵심 순간 (The Three Hero Moments)
(A) 자기 억제 (Self-suppression)
특정 제안 카테고리가 3회 거절되면, Tenure는 해당 항목에 대한 플래깅(flagging)을 완전히 중단합니다. 팀이 이를 원하지 않는다는 것을 학습한 것입니다. 별도의 설정 변경은 필요하지 않습니다.
(B) 모순 처리 (Contradiction handling)
팀의 행동이 이전의 관찰 내용과 모순될 때, 메모리는 수정됩니다. 기존의 믿음과 평균을 내는 것이 아니라, 새로운 정보로 업데이트합니다.
(C) BLOCK 단계로의 승격 (Graduation to BLOCK)
부드러운 제안으로 시작된 컨벤션(convention)이 오직 증거 횟수(proof count)만으로 머지(merge)를 차단하는 상태를 획득합니다. 팀의 일관성이 곧 권한 부여의 근거가 됩니다.
아키텍처 및 설계 (Architecture and Design)
우리는 두 가지 모드를 구축했습니다. 이것이 우리의 비용 및 신뢰성 전략 (strategy) 의 전부였습니다.
- REPLAY 모드 (기본값, 공개용): 정적 JSON 피스처(fixtures)로부터 사전 녹화된 실제 세션을 재생합니다. API 호출이 전혀 없으며, 비용이 들지 않고, 완전히 결정론적(deterministic)입니다. 심사위원과 공개 트래픽에 안전합니다.
- LIVE 모드 (암호 기반 접근): 실제 NVIDIA Nemotron 3 Super 및 Hindsight 호출을 수행하며, Upstash Redis를 통해 속도 제한(rate-limited)을 적용합니다. 필요할 때 시스템이 실제임을 증명합니다.
해커톤 총 지출: 3달러 미만. 공개 트래픽 비용: 0달러.
UI는 2패널 레이아웃으로 구성됩니다. 왼쪽 패널은 인라인 주석(inline comments)이 포함된 디프(diff)를 보여줍니다. 각 주석에는 심각도 수준(severity level), 준수해야 할 컨벤션에 대한 참조, 그리고 색상으로 구분된 신뢰 계층(trust-tier) 배지가 포함되어 있습니다. 오른쪽 패널은 팀 메모리(Team Memory)를 보여줍니다. 여기에는 증거 횟수
사용된 기술 (Technologies Used)
Next.js (App Router, TypeScript) — 프론트엔드 및 백엔드, Vercel 배포 가능
NVIDIA Nemotron 3 Super via OpenRouter — 리뷰 엔진, OpenAI 호환 API, 구조화된 JSON 출력
Hindsight Cloud — World Facts, Experience Facts 및 관찰 통합(observation consolidation)을 포함한 영구 메모리
Upstash Redis — REST API를 통한 서버리스 안전 레이트 리미팅 (rate limiting)
Vercel — 배포
Tailwind CSS — 스타일링
직면한 과제 (Challenges Encountered)
Hindsight 통합은 비동기(async) 방식입니다. retain()을 호출한 후 관찰 내용이 즉시 업데이트되지 않습니다. 단계 사이의 통합에는 10초에서 30초가 소요됩니다. 따라서 저희의 시딩(seeding) 스크립트는 제한된 waitForProcessing() 호출을 통해 대기해야 했습니다. 이 과정에서 레이스 컨디션(Racing)이 발생하여 세 번의 핵심적인 순간(hero moments)이 피스처(fixtures)에 깔끔하게 담기지 않았고, 깨끗한 데모 데이터를 얻기 위해 여러 번 재실행해야 했습니다.
서버리스 레이트 리미팅 (Serverless rate limiting). Vercel은 매 호출(invocation)마다 인메모리(in-memory) 상태를 초기화합니다. 처음에는 인메모리 카운터를 시도했으나 항상 0으로 초기화되었습니다. Upstash Redis로 전환하여 문제를 해결했지만, 호출 전반에 걸쳐 레이트 리미트 상태를 저장하고 검색하는 방식을 재고해야 했습니다.
NVIDIA Nemotron 3 Super 출력 파싱 (output parsing). 때때로 마크다운 펜스(markdown fences)로 감싸진 JSON이나 추가적인 서문 텍스트가 포함된 JSON을 반환했습니다. 저희는 펜스를 제거하고 리뷰 파이프라인이 중단되는 대신 우아하게 폴백(fallback)할 수 있는 안전한 파싱 로직을 구축했습니다.
REPLAY와 LIVE 모드 간의 동기화 유지. UI는 데이터 소스만 바뀔 뿐 동일한 컴포넌트를 사용하여 두 모드 모두에서 동일하게 작동해야 했습니다. 기능을 추가하면서 이러한 추상화(abstraction)를 깔끔하게 유지하는 데는 엄격한 규율이 필요했습니다.
Claude Code와의 차이점 (How It Differs from Claude Code)
Claude Code는 상태가 없는(stateless) 코딩 에이전트입니다. 그 순간의 코드를 생성하고 편집하는 데는 탁월하지만, 세션 전반에 걸쳐 팀의 결정을 기억하지는 못합니다.
Tenure는 어떤 리뷰어 위에도 놓일 수 있는 영구적인 팀 메모리 계층(persistent team-memory layer)입니다. 팀이 무엇을 수락하고 거절했는지 알고 있으며, 시간이 흐름에 따라 그 지식을 강제합니다. 이 둘은 경쟁 관계가 아니라 상호 보완적인 관계입니다.
향후 범위 (Future Scope)
GitHub App 연동 — 기존 리뷰 워크플로우 내의 Pull Request (PR)에 직접 댓글 작성
저장소별 컨벤션 뱅크 (Per-repo convention banks) — 프론트엔드와 백엔드 팀이 독립적인 표준을 구축할 수 있도록 저장소별로 별도의 Hindsight 뱅크 운영
팀 온보딩 모드 (Team onboarding mode) — 기존에 머지된 PR 이력을 통해 Tenure의 메모리를 초기화하여, 백지 상태가 아닌 정보를 갖춘 상태로 시작
컨벤션 충돌 해결 (Convention conflict resolution) — 두 팀원이 특정 컨벤션에 대해 지속적으로 의견이 다를 경우, 증거 횟수가 서로 상쇄되게 두는 대신 충돌을 명시적으로 드러냄
분석 대시보드 (Analytics dashboard) — 어떤 컨벤션이 차단 (BLOCK) 단계로 향하고 있는지, 어떤 것이 억제 (suppressed) 되고 있는지, 그리고 어떤 것이 논쟁 중 (contested) 인지 표시
직접 체험하기 (Try It)
라이브 데모: https://tenure-4pioznjz4-vatsal-s-projects5.vercel.app
GitHub: https://github.com/InsaneCoder-69/tenure.git
HackBaroda에서 Vatsal Trivedi, Vraj Patel, Rutul Patel이 제작했습니다. 댓글을 남겨주세요 — 모든 의견을 읽고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기