'고쳤습니다'를 믿지 않는 코딩 비평가, Opera

긴 코딩 작업에서 '고쳤다'와 '정말 사라졌다'를 갈라 문제가 닫힐 때까지 따라붙는 비평가 Opera. 세 벤치마크에서 비평가 없는 기본보다 최대 15퍼센트포인트 높았다.
English  ·  日本語  ·  한국어
← 목록으로
온
온틀 리서치
2026년 10월 10일 읽기 17분 조회 0

코딩 AI에게 "이거 틀렸어"라고 말해 주는 건 쉽다. 어려운 건 그다음이다. AI가 그 말을 듣고 진짜 고쳤는지, 아니면 고치는 시늉만 하고 넘어갔는지를 가려내는 일.

Opera는 바로 그 지점을 겨눈 코딩 비평가(critic, 에이전트가 일하는 걸 지켜보다 교정 피드백을 주는 역할)다. 한 번 지적하고 손 떼는 대신, 지적한 문제가 실제로 사라질 때까지 물고 늘어진다. 저장소 전체를 몇 시간씩 손보는 긴 코딩 작업에 붙여 보니, 비평가 없는 기본 설정보다 성공률이 뚜렷이 높았다. 가장 벌어진 경우는 15퍼센트포인트 차이였다.

지적은 쉽고, 추적은 어렵다

긴 작업을 맡은 코딩 에이전트는 코드를 뒤지고, 고치고, 돌려보며 과제를 끝낸다. 호흡이 길어질수록 사고가 늘어난다. 같은 실패한 명령을 몇 번이고 반복하고, 이미 본 파일을 또 뒤지고, 검증도 없이 "다 됐다"고 선언한다.

중간에 짚어 주는 비평가가 자연스러운 처방이다. 그런데 함정이 있다. 비평가는 아직 끝나지 않은 작업을, 증거가 반쯤만 쌓인 상태에서 판단해야 한다. 이 단계에선 "진짜 실수"와 "그럴 수 있는 중간 과정"의 경계가 흐릿하다. 잘못 짚으면, 그냥 뒀으면 성공했을 작업을 비평가가 오히려 탈선시킨다.

그래서 좋은 비평가의 조건은 똑똑한 지적이 아니다. 언제 끼어들지, 그 지적이 정당한지, 그리고 지적이 먹혔는지를 끝까지 보는 규율이다. 기존 비평가들은 앞의 둘까지는 한다. 진행 중인 작업을 평가하거나, 완성된 결과물을 채점하거나. 정작 피드백을 건넨 뒤 무슨 일이 벌어졌는지는 거의 보지 않는다. 지적은 해 놓고 그게 통했는지 확인하지 않는, 딱 그 공백이다.

Opera가 파고든 틈이 여기다. 피드백을 건넨 뒤를 두 질문으로 쪼갠다. 시킨 걸 하긴 했나. 그리고 원래 문제가 사라졌나. 이 둘을 뭉뚱그리지 않는 게 Opera의 전부라고 해도 지나치지 않다.

가드 하나가 닫히기까지

말로는 추상적이니 한 장면을 따라가 보자.

에이전트가 테스트를 통과시키려다 실패한다. Opera가 끼어들어 진단한다. "특정 입력을 걸러 줄 가드(잘못된 값이 들어오지 못하게 막는 방어용 조건문)가 빠졌다." 그리고 이 문제를 쪽지 한 장에 적는다. 쪽지에는 진단만 적히는 게 아니다. "이 문제가 해결됐다고 치려면 무엇이 보여야 하는지"까지 함께 못 박힌다. 이번엔 "원래 요구된 테스트가 통과할 것".

쪽지가 에이전트에게 전달되고, 에이전트는 가드를 코드에 추가한다. 여기서 순진한 비평가라면 "시켰더니 했네" 하고 쪽지를 덮는다. Opera는 두 단계로 나눠 본다. 먼저 지시를 따르기는 했는지 — 가드를 넣었으니 일단 통과다. 하지만 더 중요한 걸 묻는다. 그래서 원래 테스트가 통과하는가 — 아니다, 여전히 빨간불이다. 처음에 못 박아 둔 기준을 못 넘었으니 쪽지는 덮이지 않는다. 열린 채로 다음 리뷰까지 따라간다.

"고치는 시늉"과 "진짜 해결"이 갈리는 곳이 정확히 여기다. 보고서만 보면 둘은 똑같이 "처리 완료"다.

작동 원리: 쪽지 한 장, 세 가지 규율

이 쪽지가 Opera의 심장이다. 논문은 이걸 지속 메모라고 부른다. 진단된 문제 하나, 지금 줄 지침, 그리고 처음 정하면 바뀌지 않는 해결 기준을 한데 묶은 것이다. 코드 리뷰에서 누군가 단 코멘트가 "고쳤음" 체크가 찍히기 전까지 닫히지 않고 남아 있는 것과 똑같다. 코멘트가 사라지지 않으니 비평가는 여러 번의 리뷰에 걸쳐 같은 문제를 좇을 수 있고, 기준이 고정돼 있으니 "방금 뭘 시켰나"가 아니라 "원래 문제가 사라졌나"로 판정한다. 열린 쪽지는 한 번에 하나만 둔다. 이 쪽지를 세 가지 규율이 움직인다.

언제 볼 것인가. 고정 간격으로만 리뷰하면 반응이 느리고(다음 리뷰 전까지 실패를 되풀이한다), 사건이 터질 때만 보면 조용한 실패(확신에 차서 엉뚱한 파일을 고치는 경우)를 놓친다. Opera는 둘을 섞는다. 일정 턴마다 돌면서, 멈춤·반복·오류·완료 선언·최종 제출 다섯 신호 중 하나라도 뜨면 즉시 본다. 중요한 건, 본다고 꼭 끼어드는 게 아니라는 점이다. 잘 가고 있으면 비평가는 아무 말 없이 지나간다. 불필요한 참견이 성공할 작업을 망치니, 침묵을 떳떳한 선택지로 설계해 둔 것이다.

무엇을 지적할 것인가. 자유롭게 쓰게 두면 "엣지 케이스를 고려하라" 같은 두루뭉술한 말이 되기 쉽다. 에이전트로선 당장 손댈 거리가 없다. 그래서 Opera는 모든 진단을 미리 정해 둔 꼬리표 하나에 반드시 담게 한다. 꼬리표는 코드를 고치는 다섯 단계—탐색·검토·수정·테스트·제출—에 묶여 있다. 핵심은 꼬리표마다 규칙이 딸려 온다는 점이다. 이런 증거가 보일 때만 이 지적을 꺼낼 수 있고 해결됐는지는 이런 기준으로 판정한다, 그런 약속이 처음부터 붙어 다닌다. 덕분에 지적끼리 겹치지 않고, 나중에 "해결됐나"를 따질 잣대도 흔들리지 않는다. 게다가 한 번 볼 때 근거가 분명한 이슈 딱 하나, 그에 대한 가장 작은 교정만 고른다. 지시를 쏟아붓지 않아야 서로 부딪치지 않고, 뭐가 효과를 냈는지도 되짚을 수 있어서다. (꼬리표는 모두 아홉 개로, 전체 목록은 글 끝에 정리해 뒀다.)

틀린 지적을 어떻게 거를 것인가. 비평가도 결국 언어모델이라 그럴듯하지만 틀린 진단을 내놓는다. 그래서 쪽지의 일생에 두 번의 확인을 둔다. 내보내기 전 한 번 — 근거가 진단을 받치는가, 꼭 고쳐야 하는가, 제안한 확인 방법으로 정말 해결을 증명할 수 있는가. 과제와 무관한 청소나, 새 증거도 없이 하는 잔소리가 여기서 걸러진다. 닫기 전 또 한 번 — 해결됐다는 증거가 실제로 있는가. 동작을 요구했으면 실행 결과를, 코드 상태를 요구했으면 실제 편집을 확인하고서야 닫는다. 이 두 번의 확인이 Opera의 필터다.

Opera는 에이전트와 실행 기록·말로 된 피드백만 주고받고 모델 가중치는 건드리지 않는다. 그래서 기존 하네스(에이전트를 과제 환경에 연결해 돌리는 실행 틀)에 그대로 꽂힌다.

숫자는 무엇을 말하나

성격이 다른 세 벤치마크(성능을 재는 표준 시험)에서 쟀다. 터미널에서 명령을 다루는 Terminal-Bench, 실제 소프트웨어 저장소를 고치는 SWE-Bench Pro, 그리고 기본 성공률이 셋 중 가장 낮은 어려운 과제들의 DeepSWE. 일부러 결이 다른 셋을 골랐다. 한 환경에서만 통하는 요령이 아니라 두루 통하는 틀인지 보려는 것이다.

같은 에이전트(코드를 짜는 주체 모델은 고정)에 비평가만 바꿔 붙인 비교가 핵심이다. 올림폭은 퍼센트포인트(pp)로 적는다.

방법 Terminal-Bench SWE-Bench Pro DeepSWE
비평가 없음 65.9 75.3 32.4
SWE-PRM 68.9 77.7 36.6
SWE-Search 70.0 77.3 38.6
LLM-as-verifier 71.2 78.7 38.9
Agentic Rubrics 71.9 78.3 39.5
Opera 73.8 79.3 41.3

세 군데 모두 Opera가 1등이다. 다만 2등과의 거리는 제각각이다. 터미널과 DeepSWE에선 1.9pp, 1.8pp 앞섰지만 SWE-Bench Pro에선 0.6pp에 그친다. 이유는 같은 표의 맨 윗줄에 있다. SWE-Bench Pro는 비평가 없는 기본이 이미 75.3으로 강하다. 잘하는 판에선 어떤 비평가를 붙여도 올릴 구석이 얼마 없다.

이 "올릴 구석"이 결과 전체를 꿰는 열쇠다. 이득의 크기는 모델의 절대 실력보다 교정할 여지가 얼마나 남았나에 따라 갈렸다. 이미 만점에 가까운 학생보다, 아슬아슬하게 틀리는 학생에게 족집게 과외가 가장 값진 것과 같은 이치다. 네 모델에 걸친 최대 상승폭은 12.4·15.0·8.9pp였고, 터미널과 SWE-Bench Pro에선 가장 약한 모델이 가장 크게 올랐다. 반대로 기초가 아예 없어 문제 자체를 못 푸는 학생에겐 과외도 소용없다. 그 약한 모델은 DeepSWE를 비평가가 있든 없든 한 문제도 못 풀었고, 그래서 DeepSWE의 최대 상승은 오히려 더 센 모델 몫이었다. 바닥에서 출발해 성공률이 거의 세 배가 된 모델도 있었지만, 절대 이득 자체는 크지 않았다.

여기까진 "비평가를 붙이니 올랐다"는 이야기다. 더 들여다볼 대목은 무엇이 그 상승을 만드느냐다.

첫 번째 답은 필터다. 앞서 말한 두 번의 확인을 모두 떼어 내 모든 지적이 그대로 전달되고 모든 닫기 요청이 받아들여지게 하면, 이득이 주저앉는다. 터미널에서 +7.9pp가 +2.6pp로(3분의 2가 증발), DeepSWE에서 +8.9pp가 +4.5pp로(절반) 떨어졌다. 지적을 많이 하는 것보다, 정확한 지적만 골라 해결될 때까지 붙드는 장치가 이득의 절반 이상을 책임진다는 뜻이다. 잘못 고쳤을 때 대가가 큰 판일수록 필터의 몫이 컸다.

두 번째 답이 더 뜻밖이다. 비평가를 에이전트 자기 자신으로 써도 올랐다. 새 지식을 보태 줄 수 없는데도 말이다. DeepSWE에서 두 모델이 자기 자신을 비평가로 삼아 각각 6.2pp 올랐고, 이는 더 센 외부 비평가를 붙인 것과 맞먹거나 넘었다. 비평가를 바꿔 끼운 33개 조합 중 기본보다 못한 건 딱 하나뿐이었다. 이쯤 되면 이득의 큰 몫은 비평가가 얼마나 똑똑하냐가 아니라, 제때 보고 유형을 정해 진단하고 닫힐 때까지 좇는 틀 자체에서 나온다는 쪽으로 읽힌다.

다만 여기서 한 번 멈춰 서야 한다. 자기 비평도 추론을 더 쓰는데 이 비교는 그 연산량을 맞추지 않았다. 그러니 향상분을 전부 틀의 공으로 돌리는 건 이르다. 게다가 에이전트가 과제를 풀 밑천 자체가 없으면 자기 비평은 힘을 못 쓴다. 가장 약한 모델은 터미널에서 외부 비평가를 붙였을 때 최소 12.4pp 올랐지만, 자기 비평으론 많아야 2.7pp였다.

비평가가 남긴 기록이 교재가 된다

Opera가 돌며 남긴 작업 기록에는 쓸모가 하나 더 있다. 나중에 비평가 없이도 쓸 수 있는 학습 데이터가 된다는 것이다. 연구진은 작은 모델을 두 가지 기록으로 각각 가르쳐 봤다. 하나는 Opera의 코치를 받으며 그 작은 모델이 직접 푼 기록, 다른 하나는 더 센 모델이 푼 모범 답안.

한 벤치마크에선 둘 다 비슷하게 올랐다. 승부가 갈린 건 다른 벤치마크였다. 더 센 모델의 모범 답안을 그대로 베끼게 했더니 터미널 성공률이 23.6%에서 7.9%로 오히려 추락했다. 반면 Opera의 코치를 받은 자기 기록으로 배운 쪽은 25.8%로 버텼다. 모든 행동이 학생 자신에게서 나왔고 비평가의 손길은 곁의 쪽지로만 들어간 데이터라, 자기 페이스를 잃지 않은 것이다. 학생이 직접 푼 문제집에 선생님이 빨간펜으로 첨삭만 해 준 것과, 선생님이 푼 답안을 통째로 외운 것의 차이다. 전자가 덜 흔들린다.

그래도 남는 한계

연구진 스스로 못을 박는다. 비평가는 없는 능력을 만들어 주지 못한다. 앞서 본 "한 문제도 못 푼" 경우가 그 증거다.

더 미묘한 함정도 있다. 강한 모델은 피드백을 잘 받아들여 구제되는 경우가 늘지만, 동시에 원래 풀었을 과제를 되레 망치는 경우도 함께 는다. 회복과 교란이 한 몸인 셈이다. 불필요한 참견의 대가가 강한 모델일수록 크다는 뜻이기도 하다.

근본적인 한계도 짚어 둘 만하다. 비평가가 언어모델인 이상 틀린 진단은 완전히 사라지지 않고, 그걸 걸러 주는 두 번의 확인 역시 또 다른 언어모델의 판단에 기댄다. 필터가 필터를 완전히 보증하진 못한다. 그리고 SWE-Bench Pro에서 봤듯, 기본기가 이미 탄탄한 판에서는 비평가 설계의 차이가 잘 드러나지 않는다.

온틀에 대입하면

온틀에서는 AI PM이 고객 요청 하나를 받아, 내부 워커가 몇 시간에 걸쳐 처리하는 과정을 관리한다. 고객이 "주문 취소 시 환불 금액 계산을 바꿔 달라"고 했다고 하자.

PM이 워커에게 작업을 넘긴다. 잠시 뒤 워커가 "처리했습니다"라고 보고한다. 여기서 끝내면 온틀이 오래 앓던 병이 도진다. 바로 가짜 완료다. 워커는 환불 계산 코드를 손대긴 했지만, 고객이 말한 그 조건에서 금액이 맞게 나오는지는 아무도 안 봤다.

Opera식으로 하면 이 보고는 "순응"일 뿐이다. PM은 고객 요청을 받은 순간 "환불 금액이 이 조건에서 이렇게 나와야 한다"는 해결 기준을 쪽지에 못 박아 둔다. 워커가 "했다"고 해도 쪽지는 그 기준을 실제 실행 결과로 넘기 전까지 닫히지 않는다. 완료 선언과 산출물 제출을 리뷰 신호로 삼으면, 가짜 완료가 고객에게 "완료"로 건너가기 직전에 기준을 들이댈 수 있다.

쪽지를 워커에게 내보내기 전에는 확인을 하나 둔다. 동료 PM이 "이 지적이 근거가 있나, 꼭 필요한 수정인가"를 교차로 본다. 그럴듯하지만 근거가 약한 참견이 멀쩡히 굴러가던 작업을 탈선시키는 사고를, 고객에게 영향이 가기 전에 막는다. Opera 실험에서 이 확인을 뺐을 때 이득의 절반 이상이 날아갔다는 건, 외부 고객이 걸린 온틀 같은 환경에선 이 절차가 선택이 아니라 필수라는 근거로 읽힌다.

자원 배분의 힌트도 있다. 자기 비평이 유능한 모델에서 잘 먹혔다는 결과는, 밑천이 받쳐지는 작업엔 무거운 외부 검증을 덜 붙여도 되고 밑천이 부족한 작업에 힘을 몰아주면 된다는 뜻으로 읽힌다. PM 운영에 그대로 옮길 수 있는 교훈이다.

자주 묻는 질문

리뷰를 자주 돌리면 그만큼 비용이 드나요?

네. Opera는 모델을 더 학습시키지 않고, 실행할 때 진단·교정에 연산을 더 들여 성능을 끌어올리는 방식입니다. 그래서 성공률이 오른 만큼 추가 연산 비용이 따라붙습니다. 이 글의 성공률 숫자 자체는 그 비용을 보여주지 않으니, 도입을 저울질할 때는 두 가지를 함께 봐야 합니다.

열린 쪽지를 한 번에 하나만 둔다면, 문제가 여러 개일 때 느려지지 않나요?

그래서 닫기를 열기보다 먼저 처리합니다. 한 번의 리뷰가 다 끝난 이슈 하나를 닫고, 바로 다음 이슈 하나를 여는 식입니다. 열린 건 늘 하나지만 흐름이 막히지는 않습니다.

벤치마크마다 실행 환경까지 달랐다는데, 치팅이 끼어들 여지는 없나요?

세 벤치마크를 각기 다른 실행 틀로 돌리되, 과제는 공통 도구로 관리하고 네트워크를 격리해 외부에서 정답을 끌어오는 치팅을 막았습니다. 환경이 서로 달라도 Opera가 일관되게 앞섰다는 점이, 특정 설정에 기댄 결과가 아님을 뒷받침합니다.

참고: 실험 구성

  • 벤치마크·실행 틀: Terminal-Bench 2.1(89과제, Terminus-2) · SWE-Bench Pro 100과제 부분집합(OpenHands) · DeepSWE v1.1(113과제, mini-swe-agent). 과제 관리는 Harbor, 네트워크 격리는 Pier. 타임아웃은 공식 데이터셋 카드 설정.
  • 코드를 짜는 모델: Qwen3.5-9B, Muse-glimmer-30B, Qwen3.8-27B, Deepseek-V4-Flash-0731. 표의 기본 비교는 Qwen3.8-27B.
  • 비평가 기본값: GPT-5.6-Sol (민감도 분석에선 자기 자신·다른 모델로도 교체).
  • 지표: 해결률(과제를 실제로 통과시킨 비율) 하나.
  • 아홉 개 꼬리표:
단계 꼬리표 무엇을 잡나
탐색 repo_localization_search 고칠 대상을 아직 못 찾음
탐색 implementation_target_shift 엉뚱한 대상을 고치고 있음
검토 implementation_readiness_review 고칠 지점이 분명한데 코드를 또 들여다봄
검토 failure_signature_triage 도구 출력을 오독함
수정 requirement_contract_review 요구사항 위반
수정 diff_scope_review 빠졌거나 무관한 변경
수정 state_transition_review 실행 로직 결함
테스트 minimal_repro_or_focused_verifier 다음 결정을 내릴 증거가 없음
제출 submission_readiness_review 증거 없이 완료를 주장함

참고자료