Image: AI generated
2026년 3월 31일, Anthropic이 클로드 코드 npm 패키지(v2.1.88)에 소스맵을 실수로 함께 발행했다. .npmignore에 한 줄이 빠진 탓이다.1 59.8MB의 소스맵이 난독화되지 않은 TypeScript 약 51만 2천 줄, 1,900여 개 파일을 그대로 드러냈다. Anthropic은 “보안 침해가 아니라 배포 패키징 실수, 사람의 실수"라고 밝혔고, 사용자에겐 v2.1.87로 고정(pin)할 것을 권고했다.
사람들이 들여다본 코드베이스에서, 한 파일(print.ts)의 단일 함수가 3,167줄에 달했다.2
세계에서 가장 잘 팔리는 코딩 에이전트, 우리에게 코드의 고삐를 쥐여준다고 광고하는 그 도구가 — 정작 자기 자신엔 고삐를 채우지 않았다.
이 아이러니를 비웃으려고 꺼낸 게 아니다. 정반대다. 이 사건은 내가 오랫동안 깔끔하게 답하지 못했던 한 질문에 대한 가장 선명한 답이다.
“Reins Engineering, 결국 harness engineering 아니에요?”
좋은 질문이다. 날카로운 질문이기도 하다. 둘은 분명 닮았다. 둘 다 모델 바깥의 무언가다. 둘 다 코드로 짜는 비-모델 구조물이다. 둘 다 에이전트가 엉뚱한 짓을 못 하게 한다. 그러니 “고삐는 마구의 한 부분일 뿐 아니냐"는 의심은 정당하다.
나는 한동안 이 질문에 깔끔하게 답하지 못했다. 답을 찾고 나니, 그 답 자체가 Reins가 무엇인지를 가장 정확하게 설명한다. 그리고 위의 유출 사건은, 그 답을 실물로 증명한다.
먼저, 둘은 대립하지 않는다
마구(馬具)를 떠올려 보자. 말 등에 채우는 안장과 굴레, 그리고 그 굴레에 물려 사람 손까지 이어지는 두 가닥의 줄 — 고삐.
고삐는 굴레에 물려 있다. 마구의 바깥에 있는 게 아니라, 마구에 장착된 부품이다. 그러니 “하네스와 레인스는 명백히 다른가, 대립하는가?“라고 물으면 답은 아니오다. 둘은 한 장비의 부분과 부분이다.
여기서부터 시작해야 한다. 흔한 카피 — “하네스는 울타리, 레인스는 조종” — 은 둘을 맞세운다. 맞세우는 순간 진다. “검증 게이트도 하네스의 일부잖아"라는 한마디에 무너진다. 맞는 말이기 때문이다. CI도, 타입 체크도, 테스트 스위트도 모델 바깥의 스캐폴딩이고, 그건 하네스가 포함하는 것이다.
그러니 질문을 바꿔야 한다. 대립하느냐가 아니라, 어디서 갈라지느냐.
레인스는 어디서부터 가능해지는가 — 세 겹의 루프
갈라지는 자리를 찾기 전에, 레인스가 어디서 비로소 가능해지는지부터 봐야 한다. 루프의 층으로 보면 셋이다.
① 채팅 루프 LLM → 사람 → LLM 전부 확률적. 레인스 불가능.
② 에이전트 루프 LLM → 실행 → 결과관측 → LLM 실행이 결정론적 땅을 침 → 레인스 가능.
③ Reins 루프 ② + 설계된 검증기 + 래칫 레인스 완성.
채팅 루프에는 굴레를 걸 곳이 없다. 말에 올라타지도 못한 상태다. LLM이 답하고 사람이 읽고 다시 LLM에 던지는 동안, 어느 한 칸도 결정론적인 데가 없다. 신호를 물릴 쇠가 없는 것이다.
에이전트 루프가 안장을 얹는다. 실행이 끼어드는 순간 — 컴파일러가 돌고, 테스트가 떨어지고, 파일이 쓰이고 — 루프가 결정론적인 땅을 처음 밟는다. 비로소 쥘 곳이 생긴다.
클로드 코드가 압도적으로 성공한 이유가 정확히 여기다. Bash, 파일 I/O, 테스트 실행이라는 결정론적 게이트를 루프 안에 (반쯤은 우연히) 끼워 넣어, “부분적 레인스"를 이미 갖고 있었다. 채팅 시절엔 없던 것이다.
이건 내 주장만이 아니다. 프린스턴의 HAL(Holistic Agent Leaderboard)은 같은 모델을 두고 스캐폴드만 갈아끼우면 정확도가 수십 퍼센트포인트씩 출렁인다는 걸 2만 1천여 회의 에이전트 실행으로 보였다.3 모델은 고정, 바뀐 건 모델을 감싼 구조뿐이다. Addy Osmani는 한 줄로 정리한다. “괜찮은 모델 + 훌륭한 하네스 > 훌륭한 모델 + 나쁜 하네스.” 그는 같은 Opus가 클로드 코드 안에서보다 커스텀 하네스 안에서 더 높은 점수를 낸다고도 적었다.4
여기까지가 업계가 “하네스 엔지니어링"이라 부르는 영토다. 옳은 발견이다. 그리고 이것이 바로, 레인스와 헷갈리기 쉬운 자리다. 둘 다 모델 바깥에서 결과를 만드니까.
하지만 ②는 레인스의 우연한 절반일 뿐이다. Reins Engineering은 그 절반을 의도적으로 완성하는 일이다. 우연히 끼어든 게이트를, 설계된 검증기와 래칫과 결정/구현 분리로 바꾸어 ②를 ③으로 끌어올리는 것. 하네스 담론은 레인스를 증명하지만, 대체하지는 못한다.
세 개의 축
말 한 마리를 두고 두 사람이 일한다.
한 사람은 마구를 만든다. 안장의 치수, 굴레의 강도, 재갈의 모양. 이건 어느 말, 어느 여정에도 똑같이 쓰인다. 한 번 잘 만들어 두면 서울을 가든 부산을 가든 같은 마구다. 만드는 사람은 마구 장인 — 말을 탈 사람이 아니다.
다른 사람은 고삐를 쥔다. 그는 이번 여정을 안다. 어느 갈림길에서 왼쪽으로 꺾어야 하는지, 어디가 목적지인지, 언제 “도착했다"고 할 수 있는지. 그가 쥔 줄은 같은 마구에 물려 있지만, 그가 보내는 신호는 여정마다 다르다. 신호를 보내는 사람은 마구 장인이 아니라 기수다.
여기 세 개의 축이 있다.
- 기능. 하네스는 막는다 — 못 하게 하는 경계. 레인스는 이끈다 — 어디로 가고 언제 끝났는지.
- 수명. 하네스는 한 번 만들어 모든 과제에 재사용된다. 레인스는 과제마다 새로 설계된다.
- 소유. 하네스는 벤더가 출고한다. 레인스는 아키텍트가 저술한다.
클로드 코드의 루프는 내 프로젝트가 무엇이든 동일하다. 그건 하네스다. Anthropic이 만들어 출고했고, 모든 사용자에게 같다. 하지만 “임차인 퇴거 = 지정 위치 다섯 곳 사진"이라는 완료의 정의는 내가, 이 도메인을 위해, 직접 쓴 것이다. 어떤 하네스에도 그건 들어있지 않다. 그게 레인스다.
의존은 한쪽으로만 흐른다
둘이 같은 것이라면, 한쪽만 떼어낼 수 없어야 한다. 떼어내 보자.
하네스는 있는데 레인스가 없다. 에이전트는 돈다. 멈추지 않고 돈다. 다만 헤맨다. 목표 마커도 없고 완료 판정도 없는 들판을 배회하다가, “대충 이쯤이면 됐겠지” 하고 멈춘다. 우리는 이걸 이미 안다. 바이브 코딩이라고 부른다.
레인스는 있는데 하네스가 없다. 이건 성립조차 하지 않는다. 고삐를 쥐었는데 물릴 굴레가 없다. 신호를 보낼 곳이 없다. 허공에 줄을 쥐고 있을 뿐이다.
의존은 일방향이다. 레인스는 하네스를 필요로 하지만, 하네스는 레인스를 필요로 하지 않는다. 하네스는 레인스 없이도 돈다 — 나쁘게 돌 뿐이다. 이 비대칭이 “둘은 같다"를 깨끗하게 논파한다. 같은 것이라면 떼어냈을 때 양쪽 다 무너져야 하는데, 하네스는 혼자서도 달린다.
겹치는 곳은 단 한 칸
그럼 정말 겹치는 데가 없는가? 있다. 정확히 한 칸이다.
실행되는 검증 게이트. CI가 에이전트 루프 안에서 돈다. 그 집행 표면은 양쪽에 걸친다 — 하네스의 일부이면서, 레인스가 거는 것이기도 하다. 여기가 “그거 하네스 아니냐"는 질문이 태어나는 자리다. 맞다, 그 한 칸에서는 둘이 같은 것을 가리킨다.
하지만 그 바깥은 갈라진다.
하네스만 교집합 레인스만
───────────────── ───────────────── ─────────────────
샌드박스·권한 검증 게이트 완료의 정의
툴 배선 (실행되는 체크) 치즈 방어 설계
컨텍스트 관리 프록시↔목적 분석
(방향 없는 봉쇄) (집행 표면) (기판 없는 의도)
하네스에는 방향이 없는 봉쇄가 따로 있다 — 샌드박스는 어디로 가라고 말하지 않는다, 그저 못 나가게 막을 뿐이다. 레인스에는 집행 기판이 없는 의도가 따로 있다 — “무엇이 완료인가"라는 정의는, 그것을 실행할 게이트가 없어도 먼저 존재한다. 어느 쪽도 상대를 통째로 담지 못한다. 둘은 교차한다. 포함하지 않는다.
부분집합이냐는 질문이 틀린 이유
“그럼 레인스는 하네스의 부분집합인가?”
부분집합이려면 둘이 같은 자로 재어져야 한다. 그런데 하네스는 누가 출고하고 얼마나 재사용되는가(기판의 축)로 정의되고, 레인스는 궤적에 무엇을 하는가(기능의 축)로 정의된다. 축이 다르다.
“빨강은 무거움의 부분집합인가?“라고 묻는 것과 같다. 빨갛고 무거운 것(=실행되는 게이트)은 있지만, 색이 무게에 담길 수는 없다. 재는 자가 다르기 때문이다. 부분집합이라는 관계 자체가 여기선 범주 오류다.
정확한 관계는 이렇다. 레인스는 하네스를 전제하지만, 하네스에 포함되지 않는다. 위에 얹히는 층은 안에 담기는 부분이 아니다. 얹힌 것은 기판 너머로 뻗는다.
진짜 갈라지는 자리 — 치즈
여기까지는 구조의 이야기다. 하지만 Reins가 하네스 담론과 결정적으로 갈라지는 자리는 따로 있다. 치즈다.
게임 디자이너들은 안다. “쥐 10마리를 잡아라"는 악명 높은 퀘스트다. 게이트가 검증하는 것(쥐 10마리 죽음)과 디자이너가 진짜 원한 것(플레이어가 콘텐츠를 경험하기) 사이에 틈이 있고, 플레이어는 그 틈을 파고든다. 이걸 치즈라고 부른다. AI 안전 연구가 “명세 게이밍(specification gaming)“이라 부르는 것과 정확히 같은 현상이다 — 보트 레이스 에이전트가 결승선 대신 점수 아이템만 빙빙 돌며 먹고, 테트리스 에이전트가 지지 않으려고 게임을 영원히 일시정지시킨다.5
내 임대 게이트도 치즈당한다. 사진 다섯 장은 “사진이 존재한다"를 검증하지 “퇴거가 멀쩡히 끝났다"를 검증하지 않는다. 담당자가 깨끗한 벽만 골라 찍었다면? 게이트는 통과한다. 측정이 목표가 되는 순간 측정은 망가진다 — 굿하트의 법칙이다.6
이제 핵심이다. 하네스는 “통과했나"까지만 답할 수 있다. 테스트가 초록인지, 타입이 맞는지, 스키마가 깨지지 않는지 — 거기까지다. 하지만 “그 통과가 목적을 포착하는가” 는 하네스가 영원히 답할 수 없다. 무엇이 치즈인지는 도메인의 목적을 알아야만 정의되기 때문이다. 깨끗한 벽만 찍은 사진이 왜 사기인지, 규칙은 다 통과했는데 왜 목적은 90%만 닫혔는지 — 그건 이 일이 무엇을 위한 것인지를 아는 사람만 안다.
그 사람이 기수다. 레인스를 쥔 자.
치즈 불가능한 게이트를 설계하는 일 — 프록시가 목적을 못 따라가는 지점을 미리 막는 일 — 은 본질적으로 과제마다 다르고, 도메인 지식을 담고, 운영자가 저술한다. task-agnostic한 하네스는 이걸 줄 수 없다. 줄 수 없는 게 아니라, 도메인을 모르니 애초에 다룰 수 없다.
여기가 Reins Engineering이 harness engineering, agentic engineering 담론에 없는 고유 영토다. 그들은 마구를 더 잘 만드는 법을 말한다. Reins는 이 여정을, 부서지지 않게, 어느 문으로 보낼지를 말한다.
그래서 다시, 유출 사건으로
이제 처음의 아이러니로 돌아가자. 그 사건이 왜 비웃음이 아니라 증거인지가 이제 보인다.
말은 천재였다. Opus는 확률적 힘 그 자체다. 안장도 작동했다 — 클로드 코드는 세계 최고의 마구이고, HAL의 숫자가 그걸 증명한다. 그런데 그 마구로 만든 자기 코드베이스는 정확히 예측된 실패 모드로 드리프트했다. 한 함수가 3,167줄. 200 엔드포인트의 벽이 코드로 현상한 모습 그대로다. 유출 자체도 .npmignore 한 줄 누락 — 배포 산출물에 게이트가 없었다는 뜻이다.
세계 최고의 마구를 만든 회사조차, 그 마구를 자기 마구간엔 걸지 않았다.
이건 안티테제가 아니라 테제의 결정적 증거다. 레인스는 모델이나 에이전트가 가진 속성이 아니라, 적용하는 규율이다. 에이전트가 똑똑한 것과, 그 에이전트로 만든 코드가 레인스 아래 놓이는 것은 완전히 별개의 일이다. 더 큰 모델이 답이 아니다. 더 좋은 마구도 답이 아니다. 고삐를 쥐고, 이 여정의 완료를 직접 정의하고, 치즈를 막도록 게이트를 설계하는 — 그 규율이 답이다.
그러니
하네스는 말을 달리게 한다. 레인스는 말을 어느 문으로 보낼지 정한다. 하네스는 한 번 채워 두는 것이고, 레인스는 매 순간 쥐고 있는 것이다. 하네스는 장인이 출고하고, 레인스는 기수가 손에 쥔다.
둘은 대립하지 않는다. 같은 마구의 다른 부품이다. 하지만 다른 부품이다. 하네스 없이 레인스는 존재할 수 없고, 레인스 없이 하네스는 헤맨다. 그리고 이 일이 제대로 끝났는지를 아는 건 — 언제나 고삐를 쥔 손이다.
다음에 누군가 “그거 결국 하네스 아니냐"고 묻거든, 이렇게 답하라.
“하네스는 벤더가 출고하는 것이고, 레인스는 내가 이 퀘스트를 위해 설계하는 것이다. 하네스 없는 레인스는 없지만, 레인스 없는 하네스는 그냥 헤맨다. 우리에게 고삐를 쥐여준 그 도구조차, 자기 코드엔 고삐가 없었다 — 레인스는 가지는 게 아니라 거는 것이기 때문이다.”
관련 글
- 고삐 있는 AI: Reins Engineering — 게이트=고삐 reframe의 출처
- ‘완료’는 누가 정의하는가 — 치즈 불가능한 게이트, 퀘스트 디자인으로서의 태스킹
- 코딩 에이전트는 왜 작동하고 왜 깨지는가 — “생성은 확률적이어도 검증은 결정론적이어야 한다”
- 왜 당신의 에이전트는 멈추지 않는가 — 멈출 수 있는 시스템 = 완료가 정의된 시스템
- 용골(yongol): 200 엔드포인트의 벽 — 운영자가 저술하는 명세 = 레인스의 실물
함께 읽을거리
이 글이 다룬 경계 — 하네스와 레인스, 멈추는 법, 게이밍되는 명세 — 를 더 깊게, 혹은 다른 각도에서 파고든 외부 글들.
- How Coding Agents Work — Simon Willison — “코딩 에이전트는 LLM을 감싸는 하네스다.” 본문에 들어가기 전 읽을 하네스의 결정판 정의.
- Agent Harness Engineering — Addy Osmani — 하네스를 하나의 엔지니어링 분과로 정식화. ‘sprint contract’로 종료조건을 다룬다 — 본문과 가장 정면으로 겹친다.
- Reward Hacking in Reinforcement Learning — Lilian Weng — 굿하트 법칙과 명세 게이밍의 이론적 척추. ‘치즈’가 왜 일어나는지를 RL·RLHF 관점에서 받쳐준다.
- Water Finds a Crack — Soren Johnson — “기회가 주어지면 플레이어는 게임을 최적화로 짜내 버린다.” 보상 해킹의 인간적 원형을 보여주는 게임 디자인 고전.
- Effective Harnesses for Long-Running Agents — Anthropic — “끝나지도 않았는데 끝났다고 선언하는” 실패를 1차 당사자가 다룬다. 종료조건과 결정론적 검증을 한 글에.
사건 사실(2026-03-31, v2.1.88,
.npmignore/Bun 소스맵 누락, ~512K줄·~1,900파일, “human error / 침해 아님” 입장, v2.1.87 핀 권고)은 The Register(“Anthropic accidentally exposes Claude Code source code”, 2026-03-31), InfoQ, VentureBeat로 교차 확인됨. ↩︎print.ts의 단일 함수 3,167줄은 claudefa.st, “Claude Code Source Leak: Everything Found"에서 확인. ↩︎Kapoor, Narayanan et al., “Holistic Agent Leaderboard: The Missing Infrastructure for AI Agent Evaluation”(Princeton), arXiv:2510.11977 — 9개 모델 × 9개 벤치마크, 21,730회 실행. 모델·스캐폴드·벤치마크를 분리해 스캐폴드의 영향을 정량화. 라이브 리더보드: hal.cs.princeton.edu. ↩︎
Addy Osmani, “Agent Harness Engineering” — “괜찮은 모델 + 훌륭한 하네스 > 훌륭한 모델 + 나쁜 하네스.” 같은 Opus가 클로드 코드보다 커스텀 하네스에서 더 높은 점수를 낸다는 관찰. ↩︎
Krakovna et al., Google DeepMind, “Specification gaming: the flip side of AI ingenuity”; 사례 모음: V. Krakovna, “Specification gaming examples in AI”(CoastRunners 점수 루프, 테트리스 영구 일시정지 등). “의도한 결과를 달성하지 않은 채 목표의 문자적 명세만 만족시키는 행동.” ↩︎
Marilyn Strathern(1997), “‘Improving ratings’: audit in the British University system,” European Review 5(3):305–321 — “측정이 목표가 되는 순간, 그것은 좋은 측정이기를 멈춘다"의 출처(Goodhart의 1975년 명제를 Hoskin 경유로 재진술). ↩︎