코드 에이전트 — SWE-RL과 테스트라는 reward
SWE-RL: Advancing LLM Reasoning via Reinforcement Learning on Open Software Evolution (Wei et al., Meta AI, NeurIPS 2025)
Introduction
이 시리즈 #9에서 “환경이 곧 reward”라는 명제를 다뤘다. 게임처럼 승패가 명확한 환경, 컴파일러처럼 통과/실패가 분명한 환경일수록 reward hacking의 여지가 줄어든다는 이야기였다. 코드 에이전트는 이 명제가 가장 강력하게 적용될 것 같은 도메인이다. 소프트웨어 이슈를 고치는 문제에는 테스트라는, 사람이 이미 만들어둔 자동화된 판정자가 딸려 있기 때문이다. 사람의 취향을 학습해야 하는 judge도, 애매한 rubric도 필요 없다. 코드를 고치고, 테스트를 돌리고, 초록 불이 켜지면 끝이다.
그런데 실제로 이 편을 조사하면서 나온 논문 네 편을 읽다 보면 이상한 패턴이 반복된다. 테스트가 있는데도 그 논문들 중 어느 것도 “테스트 통과를 reward로 삼아 policy gradient를 직접 돌린다”는 가장 단순한 방식을 쓰지 않는다.
- SWE-RL(Meta)은 GRPO로 진짜 RL을 돌리긴 하는데, reward가 테스트 통과가 아니라 정답 patch와의 텍스트 유사도다.
- SWE-Gym(UC Berkeley 등)은 진짜 실행 가능한 환경 2,438개를 만들었지만, 그 reward로 하는 학습은 policy gradient가 아니라 성공한 궤적만 골라 SFT하는 rejection sampling이다.
- R2E-Gym(UC Berkeley)도 마찬가지로 policy는 SFT로 학습하고, 테스트 실행은 추론 시점에 여러 patch 후보 중 하나를 고르는 재채점기로만 쓴다.
- 그리고 최근 나온 감사 논문 Rajan (2026)은 애초에 SWE-bench류 테스트의 28.5%가 오답 patch도 통과시킬 만큼 허술하다는 것을 직접 재서, “테스트가 있다”는 전제 자체를 흔든다.
이 편의 논점은 이거다. 테스트라는 조달처는 이 도메인을 “가장 축복받은 경우”로 만들어주지만, 그 축복은 공짜가 아니다. ① 테스트 통과는 이진값이고 100턴짜리 궤적 끝에야 나온다는 희소성, ② 테스트 커버리지가 부실하면 그 자체가 판정 정의의 구멍이 된다는 취약성, ③ 그래서 이 도메인의 대표 논문들이 실제로는 테스트를 reward로 직접 쓰기를 주저한다는 사실 — 이 세 가지를 논문 네 편의 구체적 설계와 숫자로 따라가 본다.
Background
이 도메인에서 세 조달처가 섞이는 방식
RLHF Reward 설계 시리즈와 이 시리즈(#9, #10, #11)에서 reward의 조달처를 셋으로 나눴다 — 환경 검증, 도구 신호, judge 채점. 코드 에이전트는 이 셋이 특히 뚜렷하게 분리되어 나타나는 도메인이다.
- 환경: 코드를 실제로 실행해서 테스트가 통과하는지 보는 것. 가장 신뢰도가 높지만 비용이 크고(Docker 컨테이너를 띄우고, 의존성을 설치하고, 테스트 스위트를 돌려야 한다) 판정의 질이 테스트 자체의 질에 종속된다.
- 도구: 파일 편집, bash 명령 실행, 검색 같은 개별 행동이 형식적으로 성공했는지. “diff가 문법적으로 유효한 patch인가”, “명령어가 에러 없이 끝났는가” 같은 낮은 수준의 신호다.
- judge: LLM이 patch나 궤적 전체를 보고 “이게 이슈를 해결했을 것 같다”고 점수를 매기는 것. 실행 없이도 채점할 수 있어 빠르지만, 텍스트의 그럴듯함에 속기 쉽다.
이 편에서 다루는 네 논문은 이 셋을 서로 다르게 조합한다. SWE-RL은 환경을 아예 포기하고 규칙 기반 유사도로 대체했고, SWE-Gym은 환경 신호를 얻긴 하지만 policy gradient가 아니라 궤적 필터로만 쓴다. R2E-Gym은 환경(execution-based verifier)과 judge(execution-free verifier)를 나란히 학습시킨 뒤 둘을 섞는다. 이 조합 방식의 차이가 이 편의 실질적인 내용이다.
도구 신호는 이 편에서 상대적으로 조용하지만 완전히 없지는 않다. SWE-RL의 reward 정의에서 “포맷을 어기면 무조건 \(-1\)“이라는 항이 바로 도구 수준 신호다 — patch가 애초에 diff로 파싱 가능한 형태인지는 이슈를 실제로 고쳤는지와 무관하게 판단할 수 있는, 가장 값싼 검사다. SWE-RL 논문이 SFT(96.2%)와 RL(95.6%)의 “correct format” 비율을 수정 점수와 별도로 보고하는 것도 같은 이유다 — 형식이라는 값싼 신호와 실제 해결이라는 비싼 신호를 분리해서 보고해야, 어느 쪽이 좋아졌는지가 뒤섞이지 않는다.
SWE-bench의 판정 프로토콜은 이미 다른 시리즈에서
SWE-bench 자체 — 12개 레포지토리에서 뽑은 2,294개의 실제 GitHub 이슈, 리더보드 구성 — 는 이 블로그의 다른 시리즈에서 벤치마크 자체의 각도로 다뤘다(Jimenez et al., Princeton, ICLR 2024). 자세한 내용은 LLM 평가 체계 시리즈의 수학·코드 벤치마크 편을 참고하고, 이 글에서는 그중 RL의 reward 원천으로서 중요한 사실 두 가지만 가져온다.
첫째, 판정은 두 종류 테스트의 조합이다. FAIL_TO_PASS는 이슈가 고쳐지기 전에는 실패하다가 정답 patch를 적용하면 통과하는 테스트 — “이 버그가 실제로 고쳐졌는가”를 직접 확인한다. PASS_TO_PASS는 원래도 통과하던 테스트인데 patch를 적용한 뒤에도 여전히 통과해야 하는 것 — “고치는 김에 다른 걸 망가뜨리지 않았는가”를 확인한다. 모델의 patch가 통과로 인정되려면 이 둘을 동시에 만족해야 한다. 이 이중 조건이 뒤에 나올 “회귀 테스트 필터” 같은 방어 장치의 원형이다.
둘째, 모델이 만든 patch는 코드베이스에 적용되고, 그 위에 정답 test_patch(새/수정된 테스트)가 별도로 적용된 뒤 테스트가 돌아간다. 즉 모델은 애초에 테스트 파일 자체를 생성 대상으로 보지 않는다 — 이슈를 고치는 patch만 낸다. 이 분리 구조가 “테스트 파일을 고쳐서 통과시키는” 가장 노골적인 해킹을 원천 차단한다(단, SWE-RL·SWE-Gym·R2E-Gym처럼 자체 환경을 만드는 경우는 이 보장이 논문마다 다시 설계해야 하는 문제로 돌아온다 — 뒤에서 다룬다).
왜 테스트 통과는 희소한 신호인가
#4에서 결과 reward의 근본 문제를 다뤘다. 코드 에이전트에 대입하면 이렇다. 궤적 하나가 파일 탐색, 버그 위치 특정, 코드 편집, (있다면) 재현 테스트 작성과 실행까지 수십 턴을 거친다. 그런데 “진짜” 판정 — SWE-bench의 FAIL_TO_PASS/PASS_TO_PASS 테스트 — 은 이 모든 턴이 끝나고 최종 patch가 나온 뒤에야 실행된다. 궤적 전체가 하나의 이진값 하나로 붕괴한다는 뜻이다.
\[R(\tau) = \mathbb{1}[\text{모든 FAIL\_TO\_PASS 테스트 통과} \wedge \text{모든 PASS\_TO\_PASS 테스트 유지}]\]\(\tau\)는 궤적, \(\mathbb{1}[\cdot]\)은 지시함수다. 30번째 턴에서 엉뚱한 파일을 열어본 실수도, 55번째 턴의 결정적인 버그 발견도 이 하나의 스칼라 안에서 구별되지 않는다. 이 문제를 여러 입도(턴·스텝·토큰)로 쪼개 credit을 나누는 것이 이 시리즈 2부(#5~#8)의 주제였다. 이 편의 네 논문은 사실 이 문제를 정면으로 풀기보다, 애초에 이 이진 신호를 얼마나 자주, 어떻게 우회하는가로 답한다는 점이 흥미롭다.
긴 궤적이 credit에 미치는 영향 — 수십 턴, 2만 토큰
코드 에이전트 궤적이 실제로 얼마나 긴지 감을 잡아보자. SWE-Gym이 rejection sampling으로 모은 성공 궤적 491건은 평균 약 19턴, 약 19,000토큰이었다. 파일을 열어보고, grep으로 관련 코드를 찾고, 수정하고, 다시 확인하는 과정을 19번 반복한 끝에야 patch 하나가 나온다는 뜻이다. 책 한 권을 처음부터 끝까지 다 읽게 시켜놓고 마지막 페이지 한 줄만 보고 “이 책 재미있었는지”를 채점하는 것과 비슷하다 — 중간에 어디서 흥미를 잃었는지, 어디서 결정적인 복선을 놓쳤는지는 그 한 줄에 전혀 드러나지 않는다.
이 길이는 학습 설계에 직접 영향을 준다. SWE-RL은 정책을 16k 컨텍스트로 학습시켰는데, 굳이 파일 전체 내용을 프롬프트에 통째로 넣는 방식을 택한 이유도 여기 있다 — Agentless의 원래 방식대로 위치 특정을 여러 단계로 나누면 그 자체가 또 하나의 긴 궤적이 되어 credit이 흩어진다. 파일 전체를 한 번에 주고 “이 안에서 어디를 고칠지 스스로 추론하라”고 맡기면, 최소한 위치 특정과 수정을 하나의 reasoning 블록 안에 욱여넣어 궤적 길이 자체를 줄일 수 있다. 컨텍스트 관리가 credit assignment 문제를 우회하는 한 가지 실전적인 수단인 셈이다 — 이 트레이드오프는 #3에서 다룬 멀티턴 RL 실무의 핵심 고민과 정확히 같은 결이다.
반대로 궤적을 줄이지 않고 그대로 감당하려는 방향도 있다. 최근 나온 SkyRL-Agent(Cao et al., 2025)는 비동기 롤아웃 디스패처로 긴 궤적을 병렬로 굴리는 인프라를 만들어, 순수 RL만으로 학습한 32B 모델(SA-SWE-32B)이 SWE-bench Verified pass@1 39.4%를 내면서도 비슷한 성능의 기존 모델보다 학습 비용을 2배 넘게 줄였다고 보고한다. 궤적을 짧게 자르는 대신 “긴 궤적을 저렴하게 많이 굴리는” 쪽으로 문제를 우회한 사례다. 두 접근(컨텍스트를 압축해 궤적을 줄이는 SWE-RL과, 인프라를 최적화해 긴 궤적의 비용을 낮추는 SkyRL-Agent) 모두 “궤적 끝의 이진 신호 하나로는 부족하다”는 같은 진단에서 출발한 서로 다른 처방이다.
Method
SWE-RL — reward는 테스트가 아니라 patch 유사도다
SWE-RL(Wei et al., Meta AI, NeurIPS 2025)은 이름과 달리 테스트를 reward로 쓰지 않는다. 저자들이 명시적으로 밝히는 이유는 실행 비용이다. 학습에 쓴 시드 데이터셋은 GitHub PR 273,000건에서 뽑은 이슈-패치 쌍인데, 이 규모에서 매 rollout마다 Docker 환경을 띄워 테스트를 실행하는 것은 감당하기 어렵다. 코드 자체가 실행 가능한 자기완결적 환경(경쟁 프로그래밍 문제처럼)이 아니라 임의의 레포지토리라는 점도 문제를 키운다.
그래서 SWE-RL은 규칙 기반이되 실행이 필요 없는 reward를 골랐다. Policy LLM이 이슈와 코드 컨텍스트를 보고 검색/치환(search/replace) 형태의 코드 수정을 추론해 생성하면, 이를 patch 포맷으로 변환한 뒤 정답 patch와 비교한다.
\[\mathcal{R}(o) = \begin{cases} -1 & \text{if } o \text{ 가 포맷을 어겼을 때} \\ \mathrm{sim}(p_{pred}, p_{gt}) & \text{그 외} \end{cases}\]여기서 \(o\)는 policy가 생성한 응답, \(p_{pred}\)는 거기서 뽑아낸 predicted patch, \(p_{gt}\)는 PR에 실제로 merge된 oracle patch다. \(\mathrm{sim}\)은 파이썬 표준 라이브러리 difflib.SequenceMatcher — Gestalt 패턴 매칭 기반의 시퀀스 유사도로, 0에서 1 사이 연속값을 낸다. 두 문자열에서 겹치는 블록의 길이 비율이라고 생각하면 된다. 포맷을 어기면 무조건 \(-1\)이고, 그 외에는 테스트 실행 없이 텍스트 비교만으로 점수가 나온다.
비유하자면 이렇다. 첨삭 선생님이 학생 답안을 채점할 때, 문제를 실제로 다시 풀어보는 대신 모범답안과 학생 답안을 나란히 놓고 글자가 얼마나 겹치는지만 세는 것과 같다. 손이 훨씬 덜 가고(코드를 실행할 필요가 없으니 273,000건 규모로도 확장된다), 부분 점수도 자연스럽게 나온다(한 줄만 틀렸으면 그만큼만 감점). 다만 학생이 모범답안과 다른 방식으로 정답을 냈을 때 낮은 점수를 줄 위험, 반대로 모범답안과 글자는 비슷한데 틀린 답에 후한 점수를 줄 위험을 함께 안고 간다.
Policy는 Llama-3.3-70B-Instruct에서 시작해 GRPO로 1,600 스텝, 16k 컨텍스트, 글로벌 배치 512(문제 32개 × rollout 16개)로 512장의 H100에서 약 32시간 학습했다. 평가는 Agentless를 단순화한 Agentless Mini 파이프라인 위에서 하는데, 원래 Agentless의 다단계 위치 특정 대신 파일 전체 내용을 프롬프트에 넣어 위치 특정 부담을 줄이고 policy가 수정 자체에 더 집중하게 만들었다.
결과. Llama3-SWE-RL-70B는 SWE-bench Verified에서 pass@1 41.0%를 냈다. 100B 미만 모델 중 최고 기록이고, GPT-4o + Agentless(38.8%)와 비슷한 수준이다.
| 모델 | 스캐폴드 | SWE-bench Verified |
|---|---|---|
| SWE-Gym-32B | OpenHands | 32.0 |
| SWE-Fixer-72B | SWE-Fixer | 32.8 |
| Llama3-SWE-SFT-70B (같은 논문의 SFT 베이스라인) | Agentless Mini | 36.2 |
| GPT-4o | Agentless | 38.8 |
| Llama3-SWE-RL-70B | Agentless Mini | 41.0 |
| o1-preview | Agentless | 41.3 |
| DeepSeek-V3 | Agentless | 42.0 |
| Claude-3.5-Sonnet | Agentless | 50.8 |
오라클 위치(정답 파일이 어딘지 이미 알려준 상태)에서 순수 수정 능력만 비교한 실험(Table 2)이 더 흥미롭다. 베이스 Llama-3.3은 greedy decoding에서 포맷을 12.2%만 맞추고 수정 점수(0~100 스케일 서술형)는 5.4에 불과했다. SFT는 포맷 정확도를 96.2%까지 끌어올리고 점수도 29.6까지 올렸다. 그런데 SWE-RL은 포맷 정확도가 95.6%로 SFT보다 살짝 낮은데도 점수는 34.8로 더 높다. 형식을 더 잘 지키는 것과 실제로 더 잘 고치는 것이 다르다는 걸 보여주는 대목이다.
reward를 이진으로 바꾸면 어떻게 되나 — 논문 자체의 ablation. SWE-RL 저자들은 §3.6에서 정확히 이 편의 질문을 스스로 실험했다. 연속값 유사도 대신 “정답과 완전히 일치하면 1, 아니면 0”인 이산(discrete) reward로 똑같은 GRPO를 돌린 것이다. 결과는 이산 reward 쪽이 전반적으로 더 나빴다(포맷 94.2% vs 95.6%, 수정 점수 29.0 vs 34.8). 더 결정적인 관찰은 학습이 끝날 때까지 이산 reward의 평균값이 거의 0에 머문다는 것이다 — 실제 patch는 워낙 다양해서 정답과 완전히 같은 문자열을 만드는 rollout이 거의 없기 때문이다. 이건 이 시리즈가 반복해서 말하는 “결과 reward의 스파스함”(#4)이 코드 도메인 안에서, 심지어 테스트 실행조차 없는 순수 텍스트 비교에서도 그대로 재현된다는 뜻이다. 이진 판정이 문제의 본질이지, 실행 여부가 문제의 본질이 아니라는 얘기다.
샘플 수를 늘리면 어디까지 오르나. Agentless Mini는 여러 patch 후보와 재현 테스트를 함께 늘려 재순위화할 수 있게 설계됐다. Repair 샘플을 20개에서 160개로 늘리면 33.6%에서 40.0%로 크게 뛰지만, 그 이상(320~500개)은 41.0%까지 완만하게만 오른다. 재현 테스트도 1개에서 20개까지 늘리면 38.8%에서 41.0%로 오르고 20~30개 구간에서는 차이가 없다 — 두 축 모두 이른 구간에서 이득이 크고 이후 saturate하는, RL 분야에서 익숙한 수확체감 곡선이다.
도메인 밖에서도 통한다 — OOD 일반화. SWE-RL은 이슈 해결이라는 단일 과제로만 학습했는데도, 학습에 전혀 없던 다섯 개 벤치마크에서 흥미로운 패턴을 보인다.
| 벤치마크 | 베이스(Llama-3.3-70B) | SFT | SWE-RL |
|---|---|---|---|
| HumanEval+(함수 코딩) | 76.2 | 73.2 | 79.9 |
| CRUXEval-I(코드 추론) | 60.5 | 68.4 | 71.6 |
| CRUXEval-O(코드 추론) | 61.9 | 75.1 | 75.5 |
| MATH(엄격 채점) | 63.2 | 54.0 | 73.7 |
| MMLU(일반 지식) | 86.49 | 85.26 | 86.82 |
SFT는 이슈 해결 데이터에 맞춰 미세조정된 만큼 정작 MATH·MMLU 같은 도메인 밖 과제에서는 베이스 모델보다 떨어진다(MATH 63.2→54.0). 반면 RL로 학습한 SWE-RL은 같은 데이터로 학습했는데도 모든 항목에서 베이스를 웃돈다. 이슈 하나를 풀기 위해 근본 원인을 추론하는 훈련이, 좁은 패턴을 암기하는 게 아니라 일반적인 추론 능력 자체를 끌어올렸다는 저자들의 해석이다. 이 시리즈의 문맥에서 보면, 결과 reward라도 그 reward가 요구하는 추론이 충분히 깊으면 일반화가 따라온다는 사례로 읽을 수 있다.
한계 — 저자들이 직접 밝힌 것. 이 reward는 두 patch의 텍스트 유사도이지 기능적 동치성이 아니다. 논문 스스로 이 점을 한계로 명시한다 — 정답과 기능은 같지만 표현이 다른 대안 해법을 탐색할 유인이 없다는 것이다. 뒤집어 말하면, 표현은 정답과 비슷한데 기능은 다른 patch에 부분 점수를 줄 위험도 구조적으로 안고 있다는 뜻이다(이 문제는 뒤의 Experiments에서 숫자로 다시 짚는다).
SWE-Gym — 진짜 실행 환경을 만들고, 그 reward로는 아직 RL을 안 한다
SWE-Gym(Pan et al., UC Berkeley 등, ICML 2025)은 SWE-RL과 정반대 선택을 한다. 텍스트 유사도 대신 진짜 실행 가능한 환경을 만들었다. 11개 오픈소스 Python 레포지토리(SWE-bench와 겹치지 않는 레포를 골라 오염을 피했다)에서 2,438개의 과제를 큐레이션했는데, 각 과제는 의존성이 설치된 실행 환경, 전문가가 검증한 단위 테스트, 자연어 이슈 설명을 모두 갖춘다. 더 쉬운 부분집합인 SWE-Gym Lite(230개)와, 실행 환경 없이 이슈-패치 쌍만 있는 대규모 SWE-Gym Raw(64,689개, 358개 레포)도 함께 공개했다.
이 환경이 왜 필요했는지는 저자들이 정리한 기존 자원 비교표를 보면 분명해진다.
| 자원 | 레포지토리 수준 | 실행 환경 | 실제 사람 과제 |
|---|---|---|---|
| APPS | 아니오 | 있음 | 있음 |
| HumanEval | 아니오 | 있음 | 있음 |
| R2E(2024년 판) | 있음 | 있음 | 아니오(합성) |
| SWE-bench(train split) | 있음 | 없음 | 있음 |
| SWE-Gym | 있음 | 있음 | 있음 |
기존 자원들은 셋 중 하나씩은 포기하고 있었다 — APPS·HumanEval은 레포지토리 수준의 복잡성이 없는 독립된 함수 문제고, R2E는 실행 환경은 있지만 합성 과제라 사람이 실제로 겪은 문제가 아니고, SWE-bench의 학습용 분할(train split)은 실제 이슈-패치 쌍은 있지만 실행 환경이 없어 지도학습 이상으로는 쓸 수 없었다. SWE-Gym은 이 세 조건을 동시에 만족시킨 첫 자원이라는 게 논문의 핵심 기여다.
그런데 이 환경으로 policy를 개선하는 방법은 policy gradient가 아니라 rejection sampling fine-tuning(filtered behavior cloning이라고도 부른다)이다. GPT-4o와 Claude-3.5-Sonnet으로 SWE-Gym 위에서 rollout을 여러 번 굴려 테스트를 통과한 궤적만 골라내고(491건), 그 성공 궤적으로 Qwen2.5-Coder를 지도학습한다. 저자들 스스로 이렇게 적는다 — “PPO 같은 더 발전된 policy optimization 방법을 쓰면 더 나은 결과를 얻을 수 있을 것으로 가정한다. 이는 향후 연구 과제로 남긴다.” 즉 SWE-Gym이라는 논문 자체는 실행 결과를 reward로 삼아 policy gradient를 돌리는 실험을 하지 않았다.
결과. OpenHands 스캐폴드에서 32B 모델은 zero-shot 7.0% → fine-tuned 20.6%(SWE-bench Verified, +13.6%p)로 뛴다. 성공한 궤적으로만 학습했는데도 loop에 갇히는 비율(같은 행동을 3번 이상 반복)이 29.4%에서 크게 줄어드는 부수 효과도 있었다.
| 모델 크기 | zero-shot | fine-tuned | 증가폭 |
|---|---|---|---|
| 7B | 1.8% | 10.6% | +8.8%p |
| 14B | 4.0% | 16.4% | +12.4%p |
| 32B | 7.0% | 20.6% | +13.6%p |
자기개선은 아직 안 통한다. 흥미로운 실패 사례가 하나 있다. Teacher 모델(GPT-4o/Claude) 대신 방금 fine-tuning된 32B 모델 자신으로 rollout을 새로 뽑아(온폴리시 868건) 기존 491건과 섞어 다시 학습시켰더니, SWE-Bench Lite 점수가 15.3%에서 8.7%로 떨어졌다. 저자들은 이를 policy optimization 방법의 한계(역시 PPO 부재)나 베이스 모델의 역량 부족 탓으로 돌린다. 테스트라는 검증 가능한 reward가 있어도, 그 reward로 자기 자신의 출력을 다시 학습하는 루프는 저절로 좋아지지 않는다는 실증 사례다.
행동 반경이 좁은 스캐폴드에서는 자기개선이 아주 조금은 통하기도 한다. 위치 특정·수정·재랭킹처럼 정해진 단계만 밟는 MoatlessTools 스캐폴드로, 30개의 고온도(temperature 1.0) rollout을 굴려 성공 궤적만 학습에 추가하는 과정을 반복했더니 7B 모델은 7.0% → 9.0% → 10.0%(2회 반복), 32B 모델은 19.0% → 19.7%로 오르고 그 뒤로는 개선이 없었다(SWE-Bench Lite 기준). OpenHands처럼 자유도가 높은 스캐폴드에서는 자기개선이 오히려 역효과였는데, 행동 공간을 좁혀 놓은 스캐폴드에서는 최소한 나빠지지는 않는다 — 다만 그 이득도 두 번째 반복부터는 사실상 없다.
부분 통과의 함정 — 쉬운 문제 편향. SWE-Gym이 직접 부딪힌 또 다른 문제가 이 편의 핵심 논점과 정확히 겹친다. 반복 샘플링을 하면 과제별 성공 확률이 롱테일 분포를 그린다 — 쉬운 과제는 여러 번 성공하고 어려운 과제는 거의 성공하지 못한다. 성공한 궤적을 전부 학습에 쓰면 데이터가 쉬운 과제 쪽으로 심하게 쏠린다. 이를 완화하려고 과제당 채택하는 성공 궤적 수에 상한(cap)을 두는 per-instance capping을 도입했는데, 실험적으로 상한 2가 가장 균형이 좋았다. 낮은 상한은 데이터가 너무 줄고, 높은 상한은 쉬운 과제로 분포가 기운다.
검증기(verifier)로 추론 시점을 채점한다. SWE-Gym은 정책 학습과 별개로, 궤적이 성공했는지를 스스로 판단하는 outcome-supervised reward model(ORM)도 학습시킨다. 문제 설명·궤적·현재 git diff를 입력받아 <YES>/<NO> 토큰의 로그확률로 스칼라 점수를 낸다.
\(l_y\), \(l_n\)은 각각 <YES>, <NO> 토큰의 로그확률이다. 이 verifier로 여러 rollout 중 가장 점수가 높은 것을 고르는 Best@k를 하면 32.0%(k=16)까지 오른다. Pass@k(k개 중 하나라도 맞으면 성공, 상한선 역할)는 37.8%까지 오르는데, Best@k가 이보다 낮다는 것은 verifier 자체의 정확도가 완벽하지 않다는 뜻이다 — verifier도 결국 학습된 근사치라는 한계가 그대로 드러난다.
verifier를 무엇으로 학습시키는지도 성능을 좌우한다. off-policy(teacher 모델) 궤적과 on-policy(방금 fine-tuning된 모델 자신) 궤적을 섞어 학습한 verifier가 27@8을 냈는데, on-policy 데이터만 쓰면 개선폭이 뚜렷이 줄고, off-policy 데이터만 쓰면 22% 부근에서 일찍 saturate했다. 정책 학습에서는 on-policy 데이터를 섞는 자기개선이 오히려 해가 됐는데(15.3%→8.7%), verifier 학습에서는 정반대로 온-오프폴리시를 섞는 쪽이 최선이었다는 대비가 흥미롭다 — “무엇을 옳은 것으로 규정할지 배우는 문제(verifier)”와 “그 규정에 맞춰 행동을 바꾸는 문제(policy)”가 자기참조 데이터에 반응하는 방식이 다르다는 뜻으로 읽을 수 있다.
R2E-Gym — 하이브리드 verifier로 테스트의 약점을 실측하다
R2E-Gym(Jain et al., UC Berkeley·ANU, 2025년 4월 preprint — 논문 자체 페이지에 “Preprint. Under review.”라고 명시되어 있어 확정된 학회 venue는 없다)은 SWE-Gym과 같은 방향이지만 두 가지를 더 밀어붙인다. 하나는 실행 환경을 사람 손 없이 더 크게 만드는 것(SWEGen), 다른 하나는 그렇게 만든 실행 신호와 LLM 판단을 섞어서 쓰는 것이다.
환경 생성. SWEGen은 커밋에서 직접 테스트 생성과 back-translation을 해서 사람이 쓴 이슈나 테스트에 기대지 않고 실행 가능한 과제를 만든다. 이렇게 8.1천 개 이상의 과제(본문 기준. 초록에는 8.7K로 표기되어 있어 소폭 불일치가 있다)를 확보했다. Policy 학습 자체는 R2E-Gym도 SWE-Gym과 마찬가지로 수집된 궤적에 대한 지도학습(SFT)이다 — 이 SFT만으로 R2E-Gym-32B는 pass@1 34.4%를 낸다.
하이브리드 verifier — 이 논문의 핵심. R2E-Gym이 새로 보여주는 것은 추론 시점에 patch 후보를 재채점하는 두 방식의 강점과 약점을 정량적으로 비교했다는 점이다.
Execution-based(EB) verifier. 테스트 생성 전용 에이전트가 재현 테스트 10개를 만들고, 회귀 테스트로 기존 기능을 깨는 patch를 걸러낸다.
\[s_k^{EB} = \begin{cases} \text{TestScore}_k & \text{if } RS_k = \max_j RS_j \\ 0 & \text{그 외} \end{cases}, \quad \text{TestScore}_k = \sum_i \mathrm{Pass}(P_k, T_i)\]\(RS_k\)는 \(k\)번째 patch의 회귀 테스트 점수이고, 회귀 점수가 최고인 patch들 중에서만 생성 테스트 통과 개수로 순위를 매긴다.
Execution-free(EF) verifier. SWE-Gym의 ORM과 같은 방식으로 궤적 전체를 보고 YES/NO 확률로 점수를 낸다: \(s^{EF} = P(\text{YES}) / (P(\text{YES}) + P(\text{NO}))\).
두 verifier 모두 개별적으로는 Best@K가 42~43%에서 saturate한다. 여기서 두 가지 결정적 실측이 나온다.
- 실행 기반 verifier의 변별력 한계. 생성된 재현 테스트 중 정답과 오답 patch를 실제로 구별해내는 테스트는 대부분의 문제에서 20% 미만이다. 즉 재현 테스트 10개를 만들어도 8개 이상은 정답이든 오답이든 똑같이 통과하거나 똑같이 실패해서 순위를 가르는 데 아무 도움이 안 된다.
- 독성 테스트(toxic test). 일부 문제(소수지만 무시할 수 없는 비율)에서는 생성된 테스트가 오히려 오답 patch는 통과시키고 정답 patch는 실패시킨다 — 최대 전체 테스트의 10%까지. 이런 테스트가 하나만 섞여도 verifier의 순위가 뒤집힐 수 있다.
- execution-free verifier는 patch가 아니라 “자신감”을 본다. 궤적에서 patch만 남기고 나머지(에이전트의 사고 과정)를 지우면 Best@26이 42.8%에서 37.6%로 떨어진다. Attention을 시각화해보면 verifier가 YES를 예측할 때 가장 크게 주목하는 부분이 실제 코드 diff가 아니라 에이전트가 스스로 남긴 마무리 문장 — 예컨대 “좋아, 이 수정으로 해결됐다”류의 자평 — 이었다. 실제로 sympy 저장소의 한 오답 궤적에서, 에이전트가 스스로 확신에 찬 어조로 요약하자 verifier가 그 문체에 이끌려 틀린 patch를 YES로 잘못 예측한 사례가 보고된다. 텍스트만 보고 채점하는 judge가 논리적 정합성보다 어조의 자신감에 반응할 수 있다는 것은 #11에서 다룬 judge 일반의 약점이 이 도메인에서도 그대로 나타난 것이다.
이 두 관찰은 이 편의 논점을 정확히 실증한다. 테스트 커버리지가 부실하면 판정 정의 자체에 구멍이 난다는 #9의 명제가, 사람이 짠 SWE-bench 테스트가 아니라 에이전트가 스스로 생성한 재현 테스트에서 재현된 것이다.
그래서 나온 게 hybrid. Execution-free 점수로 먼저 상위 \(n\)개만 추리고, 그 안에서 execution-based 점수로 최종 순위를 매긴다.
\[s_k^{H} = \mathrm{Top}_n(s_k^{EF}) + s_k^{EB}, \quad \mathrm{Top}_n(s_k^{EF}) = \begin{cases} s_k^{EF} & \text{if } s_k^{EF} \text{가 상위 } n\text{개 안에 들 때} \\ -\infty & \text{그 외} \end{cases}\]즉 execution-free가 “그럴듯한 후보”를 먼저 좁혀주고, execution-based가 그 안에서 “실제로 실행해보니 어떤가”로 최종 결정을 한다. 서류 전형으로 후보를 추린 뒤 실기 시험으로 최종 합격자를 가리는 채용 과정과 비슷하다 — 서류(execution-free)만으로는 실무 능력을 확신할 수 없고, 실기(execution-based)만 전원에게 보게 하면 비용도 크고 변별력 있는 문제를 낼 재간도 없다. 판정력이 약한 execution-based 신호를, 변별력은 있지만 편향될 수 있는 execution-free 신호로 보완하는 구조다. 이 조합으로 Best@26 51.0%까지 올라간다.
이 51.0%가 어느 위치인지도 짚어두자. 논문이 함께 보고한 비교표(Table 4)에서 프론티어 독점 모델 쪽 상한은 훨씬 높다 — Claude-3.7-Sonnet + Tools가 62.3%(단일 시도), 여러 시도 중 하나라도 맞으면 인정하는 Best@Any 기준으로는 70.3%까지 간다. 즉 R2E-Gym의 51.0%는 “그 시점 오픈소스/오픈웨이트 중 최고”였다는 뜻이지, 이 도메인의 상한에 도달했다는 뜻은 아니다. 격차를 좁히는 힘은 policy 자체의 추론 능력에서도 오지만, 이 절만 놓고 보면 상당 부분이 “후보를 몇 개나, 얼마나 잘 골라내는가”라는 재채점 설계에서 나온다.
보강 실험 두 가지. 저자들은 이 설계가 최선인지도 따로 확인했다. 먼저 execution-based verifier에서 회귀 테스트만 쓰고 새로 생성한 재현 테스트를 빼면 성능이 뚜렷이 떨어진다 — 기존 기능을 안 깨는 것만으로는 부족하고, 애초에 버그를 재현해서 고쳐졌는지 직접 확인하는 테스트가 있어야 한다는 뜻이다. 다음으로 테스트 생성 에이전트에게 Django에서 가져온 예시 하나를 in-context로 보여줬더니, 형식을 지키지 못하거나 도메인 지식이 없어 실패하던 문제의 약 2%가 추가로 풀렸다. 작은 개선처럼 보이지만, “테스트를 생성하는 에이전트” 자체도 결국 프롬프트에 민감한 LLM이라는 걸 보여주는 대목이다 — 판정자를 하나 더 세워도 그 판정자 역시 완벽하지 않다.
Reward Hackability Audit — 테스트가 몇 % 뚫리는지 직접 잰다
앞의 세 논문이 테스트 신호의 약점을 우회하거나 보완하는 쪽이었다면, Rajan (2026)의 “Auditing Reward Hackability in Code RL Training Environments”는 아예 그 약점의 크기를 직접 측정한다(단독 저자, 소속 정보 없음. 2026년 6월 공개된 preprint이며 확정된 학회 venue는 없다).
방법은 단순하고 직접적이다. SWE-bench Verified에서 49개 과제를 뽑아, 각 과제마다 “정답이 아닌데 그 과제의 테스트는 통과하는” patch(exploit)를 프론티어 LLM(Claude Sonnet 4)으로 생성하도록 시도한다. 1라운드는 한 번에 만들고, 2~3라운드는 직전 실패 로그를 보여줘 “아직 이 테스트 스위트가 막지 못한 방식”을 노리도록 유도하는 반복 공격을 쓴다. Docker 컨테이너에서 실제로 실행해 통과하면 그 과제는 “hackable”로 표시한다. 1라운드 단발 시도만으로도 18.4%(9/49)가 뚫렸고, 2~3라운드 반복 공격이 5개 과제를 추가로 뚫어 최종 49개 중 14개, 28.5%에 도달했다. 같은 파이프라인을 R2E-Gym 과제 20개(6개 레포지토리)에도 단발 시도만으로 적용했더니 25.0%가 뚫렸다 — 저자 자체 도구로 만든 R2E-Gym의 실행 기반 테스트도 예외가 아니라는 뜻이고, 반복 공격까지 허용하면 이 수치는 더 올라갈 여지가 있다.
이 감사가 과제를 KEEP(그대로 유지)/FIX(보강 필요)/DROP(폐기) 세 등급으로 나누는 데 쓰는 종합 점수도 눈여겨볼 만하다.
\[\mathrm{EQS}(t) = 0.35\,V(t) + 0.30\,(1 - H(t)) + 0.20\,F_1(t) + 0.15\,D(t)\]\(t\)는 과제, \(V(t)\)는 후보 patch들 사이에서 verifier가 정답과 오답을 얼마나 잘 갈라내는지, \(H(t)\)는 앞서 설명한 exploit 파이프라인으로 측정한 경험적 해킹률, \(F_1(t)\)은 LLM judge와 실행 결과의 일치도, \(D(t)\)는 여러 모델의 실제 제출 성적에서 뽑은 학습 가능성 신호다. 가중치는 “직접적인 신호일수록 크게 반영한다”는 원칙으로 저자가 임의로 정했고 검증 데이터로 튜닝하지 않았다고 명시한다 — 이 편의 핵심 수치인 28.5%·25.0%·14.14%p는 이 가중치와 무관하게 \(H(t)\) 지표 자체에서 직접 나온 값이라는 점도 논문이 강조한다.
더 흥미로운 건 이 취약성이 실제 리더보드 성적에 영향을 준다는 대규모 분석이다. SWE-bench Verified에 제출된 프론티어 모델 134개의 결과를 모아, 같은 난이도 구간 안에서 hackable로 표시된 과제와 그렇지 않은 과제의 pass@1을 비교했다. hackable 과제에서 pass@1이 평균 14.14%p 더 높았다(95% 신뢰구간 [11.80, 16.48], \(p < 10^{-6}\), 134개 모델 중 123개가 이 방향으로 양성). 난이도를 통제했는데도 이 정도 차이가 나온다는 것은, 모델들이 실제로 이슈를 더 잘 풀어서가 아니라 테스트가 허술한 과제에서 우연히든 의도적으로든 더 자주 통과하고 있다는 뜻으로 읽힌다.
방어 절차. 이 논문은 문제를 짚는 데서 그치지 않고 수선 절차도 제시한다. 생성한 보강 테스트를 실제 테스트 파일에 추가하되, 곧바로 신뢰하지 않고 gold-sanity gate를 먼저 통과시킨다 — 그 테스트를 정답 patch에 대해서도 돌려서, 정답조차 실패시키는 결함 있는 테스트인지 먼저 걸러내는 것이다. 게이트를 통과한 테스트만 LLM judge에게 넘겨 “이 테스트가 실제로 표적 exploit을 막아내는가”를 판정시키고, 실패하면 다양성을 준 재시도를 반복한다. 11개의 취약한 과제에 이 절차를 적용했더니, LLM judge가 “이 테스트로 결정하겠다”고 판단한 105개 테스트 중 65개(61.9%)가 정작 정답 patch 자체에서도 실패하는 결함 테스트였다 — gold-sanity gate가 없었다면 LLM judge 혼자로는 놓쳤을 결함이다. 최종적으로 11개 중 9개 과제가 이 반복 절차로 수선됐다.
이 결과가 이 편에서 갖는 의미는 분명하다. “테스트가 판정 정의다”라는 명제는 방향만 맞는 게 아니라, 그 정의 자체를 검증하는 별도의 검증 절차(정답에 대해 테스트를 먼저 돌려보는 것)가 필요할 만큼 깨지기 쉽다. judge 하나만으로는 부족하고, judge와 gold 실행을 겹쳐야 한다는 점에서 이 도메인도 결국 #11이 다룬 judge의 한계에서 자유롭지 않다.
해킹 패턴과 방어를 정리하면
네 논문에 흩어져 있던 해킹 경로와 방어 장치를 한데 모아보자. “판정을 통과하되 실제로 이슈를 고치지 않는” 경로는 크게 세 층위로 나뉜다.
- 판정 그 자체를 조작하는 경로. 가장 노골적인 형태는 테스트 파일을 직접 고쳐 assert 조건을 완화하거나 삭제하는 것, 혹은 예외를 조용히 삼켜(bare
except: pass같은 패턴) 테스트가 실패할 기회 자체를 없애는 것이다. SWE-bench의 평가 프로토콜은 이 경로를 구조적으로 막는다 — 모델의 patch가 코드베이스에 적용된 뒤에야 정답 test_patch가 별도로 적용되므로, 모델은 테스트 파일을 애초에 건드릴 위치에 두지 않는다. - 판정 기준 자체가 허술한 경로. 테스트 파일은 안 건드리지만, 그 테스트가 애초에 허술해서 겉모습만 맞춘 patch도 통과하는 경우다. R2E-Gym이 실측한 “변별력 20% 미만”과 “독성 테스트 최대 10%”, Rajan이 실측한 “28.5%/25.0% hackable”이 전부 이 층위에서 일어난다. 모델이 의도적으로 노린 게 아니라, 테스트 커버리지가 원래 그 정도로 허술했던 것도 섞여 있다는 점이 이 층위의 까다로운 부분이다.
- 판정을 새로 만드는 과정 자체가 오염되는 경로. SWE-RL·SWE-Gym·R2E-Gym처럼 논문이 직접 재현 테스트나 학습 데이터를 합성하는 경우, 그 생성 파이프라인 자체가 결함 있는 테스트를 양산할 수 있다. R2E-Gym의 테스트 생성 에이전트가 실패하는 사례(생성 테스트가 정답 patch에서도 실패)나, Rajan이 LLM judge 혼자였다면 놓쳤을 결함 테스트 61.9%가 이 층위의 증거다.
| 층위 | 구체적 해킹 예시 | 확인된 방어 |
|---|---|---|
| 판정 자체 조작 | 테스트 파일 직접 수정, assert 완화·삭제, 예외 삼키기 | test_patch를 patch 적용 이후 별도로 주입하는 평가 프로토콜(SWE-bench) |
| 판정 기준의 허술함 | 표면 테스트만 통과하는 땜질 patch, 독성 테스트(오답 통과·정답 실패) | 회귀 테스트 필터로 기존 기능 훼손 배제(R2E-Gym), execution-based·execution-free 신호 결합(R2E-Gym) |
| 판정 생성 자체의 오염 | 자동 생성된 재현 테스트가 정답 patch에서도 실패 | gold-sanity gate — 새 테스트를 정답 patch에 먼저 돌려 결함 여부 확인(Rajan) |
이 표에서 드러나는 공통 원칙은 하나다. 판정자를 하나만 세우지 말라. 실행(환경)과 텍스트 판단(judge)을 겹치거나(R2E-Gym), 새로 만든 판정 기준을 정답에 대해 먼저 검증하거나(Rajan), 판정 대상 자체를 모델의 편집 범위 밖에 두는(SWE-bench 프로토콜) 식으로, 판정 경로 자체를 이중화하는 것이 지금까지 확인된 유일하게 일관된 방어다.
Experiments
네 논문의 reward 설계를 나란히 놓으면
| 논문 | 정책 학습에 실제로 쓴 reward | 조달처 | 스칼라 형태 | 학습 알고리즘 | 테스트 실행은 어디에 쓰나 |
|---|---|---|---|---|---|
| SWE-RL | patch 텍스트 유사도 | 규칙 기반(비실행) | 연속 \([-1,1]\) | GRPO(진짜 RL) | 안 씀 |
| SWE-Gym | 테스트 통과 여부(궤적 채택 기준) | 환경(실행) | 이진(채택/기각) | rejection sampling FT | 궤적 필터링에만 |
| R2E-Gym | 없음(policy는 SFT) | — | — | SFT | 추론 시점 후보 재채점(EB+EF)에만 |
| Rajan 감사 | 해당 없음(reward 설계 논문 아님) | — | — | — | 기존 테스트의 견고성 자체를 측정 |
이 표를 보면 이 편 서두에서 던진 관찰이 다시 확인된다. 네 편 중 어느 것도 테스트 통과를 reward로 삼아 policy gradient를 직접 굴리지 않는다. 이름에 RL이 들어간 SWE-RL조차 실행을 아예 건너뛰고, 실행 환경을 공들여 만든 SWE-Gym·R2E-Gym은 그 신호를 필터나 재채점기로만 쓴다. 테스트가 있다고 해서 그 테스트를 온라인 RL의 매 스텝 reward로 바로 꽂을 수 있는 건 아니라는 뜻이다 — 실행 비용과 (뒤에 보일) 부분 통과의 함정이 그 사이를 가로막는다.
부분 통과 보상의 함정 — 토이 계산
R2E-Gym이 실측한 “20% 미만의 테스트만 변별력이 있다”는 결과를 손으로 재구성해보자. 어떤 이슈에 테스트 10개가 딸려 있고, 그중 7개는 “함수가 예외 없이 도는가”, “반환 타입이 맞는가” 같은 표면 테스트, 나머지 3개는 실제 버그의 근본 원인을 건드리는 의미 테스트라고 하자. reward를 통과 비율로 준다: \(R = (\text{통과한 테스트 수})/10\).
정책이 취할 수 있는 두 전략을 비교한다.
| 전략 | 행동 | 성공 확률 | 성공 시 \(R\) | 실패 시 \(R\) |
|---|---|---|---|---|
| A. 정직한 수정 | 근본 원인을 찾아 고친다 | \(p_A=0.2\) | \(1.0\)(10개 전부 통과) | \(0.5\)(리팩터링 중 기존 로직 일부 손상, 평균 5개만 통과) |
| B. 땜질 patch | 이슈 설명에 언급된 특정 예외·입력만 조건문으로 특수 처리 | 거의 결정적 | \(0.7\)(표면 7개 통과, 의미 3개는 구조적으로 불가능) | 사실상 항상 성공 쪽에 수렴 |
전략 A는 “제대로 고치거나, 어설프게 고치다 오히려 망가뜨리거나”의 양극단을 오가고, 전략 B는 애초에 의미 테스트를 통과할 능력이 없는 대신 표면 테스트만큼은 거의 확실하게 챙긴다 — 상한은 낮지만 변동성도 낮은 전략이다. 기댓값을 비교하면,
\[\mathbb{E}[R \mid A] = 0.2 \times 1.0 + 0.8 \times 0.5 = 0.6\] \[\mathbb{E}[R \mid B] = 0.7\]전략 B가 전략 A보다 기대 reward가 높다. 여기에 GRPO의 group-relative advantage를 얹으면 문제가 더 커진다. Advantage는 그룹 평균 대비 상대값이다.
\[A_i = \frac{R_i - \mathrm{mean}(R_{1:G})}{\mathrm{std}(R_{1:G})}\]SWE-RL이 실제로 쓴 그룹 크기는 문제당 rollout 16개였다. 이 정도 그룹 크기에서, 베이스 모델이 애초에 표면적인 패턴 매칭(B류)을 근본 원인 추론(A류)보다 훨씬 쉽게 생성한다고 하면, 한 그룹 안의 rollout 대부분이 B류로 채워진다. 그룹 평균은 0.7 근처로 수렴하고, B류 rollout들은 advantage가 거의 0(이미 다수라 서로를 상쇄)이지만, A류 rollout은 80% 확률로 그룹 평균보다 낮은 0.5를 받아 음의 advantage로 벌점을 받는다. 어쩌다 성공한 20%의 A류만 큰 양의 advantage를 받는데, 애초에 드물게 시도되는 전략이라 이 신호 자체가 희소하다. 결과적으로 gradient는 “근본 원인을 찾으려는 시도”를 체계적으로 억누르고 “안전하게 표면만 맞추는 시도”를 강화하는 쪽으로 편향된다 — R2E-Gym이 실측한 낮은 변별력, Rajan이 실측한 28.5%/25.0% 해킹률이 바로 이 동역학의 결과물이다.
손익분기점은 어디인가. 전략 A가 전략 B를 이기려면 근본 원인을 실제로 찾아낼 확률 \(p_A\)가 얼마나 높아야 할까? \(\mathbb{E}[R \mid A] = 0.5 + 0.5\,p_A\)이므로, 이것이 \(0.7\)을 넘으려면
\[0.5 + 0.5\,p_A > 0.7 \;\Longrightarrow\; p_A > 0.4\]즉 정직한 수정이 적어도 40% 확률로 성공해야 비로소 표면 patch보다 기대 reward가 높아진다. 문제는 학습 초반의 policy일수록 \(p_A\)가 이 문턱보다 한참 낮다는 점이다 — 근본 원인을 정확히 짚어내는 능력은 학습이 진행되며 서서히 오르는 것이지, 처음부터 갖춰져 있는 게 아니다. 즉 학습 초반일수록 비율 보상은 하필 그 시점에 하필 표면 patch를 편애한다. 초반의 편애가 group-relative advantage를 통해 그 방향의 gradient를 강화하면, \(p_A\)가 문턱을 넘을 기회 자체가 줄어드는 자기강화 루프가 생길 수 있다. R2E-Gym과 SWE-Gym이 policy 학습에서 실행 reward를 직접 쓰는 policy gradient 대신 “일단 성공한 궤적만 골라 쓰는” rejection sampling/SFT로 물러난 것도, 이 자기강화 루프를 아예 학습 루프 밖에서(온라인이 아니라 오프라인 필터로) 끊으려는 선택으로 볼 수 있다.
그렇다면 비율 대신 “10개 전부 통과해야 1점, 아니면 0점”인 완전 이진 reward로 바꾸면 이 함정을 피할 수 있을까? 이건 가정이 아니라 SWE-RL의 §3.6 ablation이 실제로 답한 질문이다 — 이산 reward는 수정 점수가 오히려 더 낮았다(29.0 vs 연속 34.8). 부분 통과를 아예 인정하지 않으면 표면 patch를 억누를 수는 있지만, 그 대신 학습 신호 자체가 거의 항상 0이 되어 아무것도 배우지 못한다. 부분 점수를 주면 게이밍을 유인하고, 안 주면 학습이 멈춘다 — 이게 이 도메인에서 테스트를 곧이곧대로 reward로 못 쓰는 진짜 이유다.
결과 수치 종합
SWE-bench Verified 기준으로 이 편에서 나온 수치를 한데 모으면 다음과 같다(빈 칸은 원문에서 확인하지 못한 값).
| 시스템 | 학습 방식 | 재채점 없이(pass@1 또는 end-to-end) | 재채점 후(best@k) |
|---|---|---|---|
| Llama-3.3-70B-Instruct(베이스) | — | 5.4* | 16.6*(20-sample 다수결) |
| Llama3-SWE-SFT-70B | SFT | 36.2 | — |
| Llama3-SWE-RL-70B | GRPO(유사도 reward) | 41.0 | — |
| SWE-Gym-32B | rejection sampling FT | 20.6 | 32.0(k=16, ORM) |
| R2E-Gym-32B | SFT | 34.4 | 51.0(k=26, hybrid verifier) |
| GPT-4o + Agentless(참고) | — | 38.8 | — |
| Claude-3.5-Sonnet + Agentless(참고) | — | 50.8 | — |
* 오라클 위치 지정 상태에서의 수정 전용 점수(Table 2 기준, end-to-end 수치와 스케일이 다르다).
재채점 후보 수를 늘렸을 때의 수확체감도 SWE-RL과 R2E-Gym 양쪽에서 같은 모양으로 나타난다.
| 늘리는 축 | 적을 때 | 많을 때 | 포화 지점 |
|---|---|---|---|
| SWE-RL, repair 샘플 수 | 20개 → 33.6% | 500개 → 41.0% | 160개 이후 완만(40.0%→41.0%) |
| SWE-RL, 재현 테스트 수 | 1개 → 38.8% | 20개 → 41.0% | 20~30개 구간에서 차이 없음 |
| R2E-Gym, best@k의 k | k=1 → 20.6% | k=26 → 51.0%(hybrid 적용 시) | hybrid 없이는 42~43%에서 먼저 정체 |
세 축 모두 초반 구간에서 이득이 집중되고 그 이후로는 완만해진다는 공통점이 있다. 다만 R2E-Gym은 hybrid verifier를 더했을 때만 51.0%까지 계속 오르고, verifier 없이 순수 표본 수만 늘리는 SWE-RL·R2E-Gym 단독 execution/execution-free 축은 42~43% 부근에서 먼저 멈춘다는 차이가 있다. 표본을 늘리는 것과 표본을 잘 고르는 것은 서로 다른 자원이고, 이 도메인에서는 후자 없이 전자만으로는 한계가 뚜렷하다.
이 표에서 두 가지가 눈에 띈다. 첫째, 재채점(best@k)의 효과가 학습 방식보다 크다. R2E-Gym은 SFT만으로 34.4%였다가 hybrid verifier로 51.0%까지 오른다 — policy 자체의 개선(SFT vs RL)보다 추론 시점에 여러 후보를 잘 고르는 것이 더 큰 폭의 향상을 만든다. 둘째, GRPO로 진짜 RL을 돌린 SWE-RL(41.0%, 재채점 없이)이 재채점 이전 단계의 SFT/rejection-sampling 결과들(20.6%, 34.4%)보다는 높지만, 재채점을 더한 R2E-Gym(51.0%)에는 못 미친다. 이 시리즈의 문맥에서 읽으면, credit을 촘촘히 나누는 학습(온라인 RL)과 후보를 여러 개 뽑아 잘 고르는 것(추론 시점 앙상블)이 서로 다른 축의 개선이고, 이 도메인에서는 아직 후자가 더 저렴하고 효과적이라는 뜻이다.
통계 요약
이 글에서 나온 네 논문의 설계 선택과 이 편의 결론을 한 표로 묶는다.
| 논문 | 핵심 기여 | reward/판정 설계의 결정적 선택 | 이 편의 결론에 대한 기여 |
|---|---|---|---|
| SWE-RL | 273K PR 규모의 RL, GRPO | 테스트 대신 patch 유사도(연속) | 이진 vs 연속 reward의 sparsity 차이를 직접 ablation으로 증명 |
| SWE-Gym | 첫 실행 가능 SWE 학습 환경(2,438개) | 실행 결과는 궤적 필터로만(rejection sampling FT) | 부분 통과의 롱테일 편향과 자기개선 실패를 실측 |
| R2E-Gym | 절차적 환경 확장(8.1K+), hybrid verifier | execution-based + execution-free 결합 | 테스트 변별력 20% 미만·독성 테스트 10%를 실측 |
| Rajan 감사 | 테스트 견고성 자체의 정량 감사 | EQS로 KEEP/FIX/DROP 분류, gold-sanity gate | 해킹률 28.5%/25.0%와 리더보드 왜곡 14.14%p를 실측 |
네 논문을 관통하는 한 문장으로 압축하면, “테스트가 있다”는 이 도메인의 축복은 판정의 존재를 보장할 뿐 판정의 저렴함이나 견고함을 보장하지 않는다. 저렴함이 없어서 SWE-RL은 실행을 포기했고, 견고함이 없어서 R2E-Gym은 두 판정자를 섞었고, 그 견고함의 크기를 재는 것만으로 논문 한 편(Rajan)이 나올 만큼 이 문제는 아직 해결되지 않았다.
참고로 이 편에서 다룬 네 논문은 모두 2024년 말~2025년 상반기 작업이고, SWE-bench Verified 점수 자체는 이후로도 계속 올랐다. Moonshot AI의 Kimi-Dev(2025)는 워크플로 기반(Agentless류) 방식만으로 60.4%를 냈다고 보고한다. 이 편의 핵심 논점 — 부분 통과의 함정, 판정 정의의 취약성, 긴 궤적의 credit 문제 — 은 리더보드 숫자가 올라가는 것과 별개로 여전히 유효하다. 오히려 점수가 오를수록 “정말 더 잘 고치는 것”과 “판정을 더 잘 통과하는 것”을 구분하는 일(바로 Rajan의 감사가 하는 일)이 더 중요해진다.
Conclusion
코드 에이전트는 테스트라는 자동화된 판정자를 갖고 있다는 점에서 이 시리즈 4부의 다른 도메인보다 유리한 출발선에 있다. 그런데 이 편에서 다룬 네 논문을 관통하는 결론은 역설적이다.
- 테스트가 있어도 그것을 곧바로 online RL의 reward로 쓰는 논문이 없다. SWE-RL은 실행 대신 패치 유사도를, SWE-Gym과 R2E-Gym은 policy gradient 대신 rejection sampling/SFT를 택했다. 이유는 실행 비용과, 앞서 계산한 대로 부분 통과 reward가 만드는 게이밍 유인이다.
- 테스트 커버리지가 판정 정의 자체다. R2E-Gym은 자기 손으로 만든 재현 테스트조차 20% 미만만 변별력이 있다는 것을, Rajan의 감사는 SWE-bench Verified 과제의 28.5%가 오답도 통과시킨다는 것을 직접 쟀다. #9의 “함수가 아니라 판정 정의가 뚫린다”는 명제가 사람이 만든 벤치마크에서나 에이전트가 만든 테스트에서나 똑같이 성립하고, 이를 막는 유일하게 일관된 방어는 판정 경로를 하나가 아니라 둘 이상 겹치는 것이었다.
- 부분 점수와 완전 이진 사이에 안전한 지대가 없다. 부분 점수는 쉬운 표면 테스트만 노리는 전략을 기대 reward에서 이기게 만들고, 완전 이진은 학습 신호를 거의 0으로 만든다. SWE-RL의 연속 vs 이산 ablation이 이 트레이드오프를 숫자로 보여준다.
- 긴 궤적의 credit 문제는 컨텍스트 설계로 우회하거나 인프라로 감당하는 수밖에 없다. 평균 19턴·19,000토큰짜리 궤적 끝에 이진 신호 하나만 두는 비효율은 #3의 문제 그대로다. SWE-RL은 파일 전체를 한 번에 주는 프롬프트 설계로 궤적 자체를 압축했고, SkyRL-Agent는 비동기 디스패치로 긴 궤적의 비용을 낮췄다 — 아직 이 문제를 정면으로 푼 논문은 없고, 두 우회로만 있다.
다음 편(#14)은 웹·GUI 에이전트다. 코드 에이전트와 달리 “정답 판정”이 텍스트 diff가 아니라 픽셀과 DOM 상태로 나온다 — 테스트라는 축복이 없는 도메인에서 reward를 어떻게 조달하는지가 이어지는 논점이다.
참고 문헌
- Wei et al., 2025. SWE-RL: Advancing LLM Reasoning via Reinforcement Learning on Open Software Evolution. NeurIPS 2025.
- Pan et al., 2024. Training Software Engineering Agents and Verifiers with SWE-Gym. ICML 2025.
- Jain et al., 2025. R2E-Gym: Procedural Environments and Hybrid Verifiers for Scaling Open-Weights SWE Agents.
- Rajan, 2026. Auditing Reward Hackability in Code RL Training Environments.
- Jimenez et al., 2023. SWE-bench: Can Language Models Resolve Real-World GitHub Issues?. ICLR 2024.
- Dihan & Khan, 2026. SWE-Shepherd: Advancing PRMs for Reinforcing Code Agents.
- Cao et al., 2025. SkyRL-Agent: Efficient RL Training for Multi-turn LLM Agent.
- Yang et al., 2025. Kimi-Dev: Agentless Training as Skill Prior for SWE-Agents. Moonshot AI, arXiv 2025.
Agentic RL 설계 시리즈
이 글은 Agentic RL 설계 시리즈의 열세 번째 글이다.
1부. 왜 에이전트는 다른가
- 에이전트 RL은 무엇이 다른가 — 장기 지평·희소 보상·긴 궤적
- 공을 어디에 돌릴 것인가 — credit assignment 47개 방법의 지도
- 멀티턴 RL 실무 가이드 — 무엇이 실제로 작동하는가
2부. credit assignment — 공을 어디에 돌릴 것인가
- 결과만으로는 부족하다 — 장기 지평에서 증폭되는 RLVR의 한계
- 턴 단위로 공을 나눈다 — turn-level reward 설계
- 스텝을 단위로 삼는다 — 행동 단위 궤적 표현과 credit
- 토큰과 세그먼트로 더 잘게 — 세밀한 입도의 득과 실
- shaping은 약인가 독인가 — 중간 보상의 효율과 위험
3부. reward를 어디서 얻나
- 환경이 곧 reward다 — 샌드박스·테스트·상태 검증
- 도구 호출을 어떻게 채점하나 — ToolRL·ToolRM
- 궤적을 judge가 채점한다 — rubric 생성형 reward의 확장
4부. 도메인별 설계
- 검색 에이전트 — Search-R1에서 DeepDive까지
- (현재 글) 코드 에이전트 — SWE-RL과 테스트라는 reward
- 웹·GUI 에이전트 — end-to-end 멀티턴 RL
5부. 실패와 방어
- 에이전트의 reward hacking — 판정기가 뚫린다, 그리고 조합의 실패
6부. 실전 종합
- 프론티어 모델은 실제로 어떻게 하나 — 최신 모델들의 agentic RL 설계
본 시리즈는 16편으로 구성된다.
Enjoy Reading This Article?
Here are some more articles you might like to read next: