머지된 PR이 더는 증명해주지 않는 것
2월에 배움은 어디로 갔을까?라는 글을 썼습니다. 에이전트와 하루 종일 진짜 기능을 배포했는데, 정작 배운 것은 없는 것 같은 기분이 들었던 날이었습니다. 그때 제가 낸 답은 결정을 가설로 바꾸고 나중에 숫자로 확인하는 측정을 만들자는 것이었습니다.
지금도 그 답이 틀렸다고 생각하지는 않지만 질문의 절반에만 답했다는 생각이 듭니다.
비용 대시보드는 결정이 효과가 있었는지는 알려줍니다. 하지만 그 결정이 왜 효과가 있었는지 제가 이해하고 있는지, 조건이 바뀌면 어떻게 될지 예측할 수 있는지는 알려주지 않습니다. 둘은 서로 다른 문제이고 요즘 자꾸 마주치는 것은 두 번째 쪽입니다.
코드가 귀하던 시절, PR은 영수증이었습니다
Terence Tao의 Math 2.0 발표를 보고 이 문제를 설명할 말을 조금 더 정확하게 찾았습니다.
Tao의 설명은 이렇습니다. 수학은 오랫동안 증명이 귀한(proof scarcity) 상태로 굴러왔습니다. 무언가를 증명하는 일은 어렵고 드물었고 수학계의 관행과 인센티브도 대부분 그 전제 위에서 만들어졌습니다. 지금 AI는 수학을 증명이 흔한(proof abundance) 상태로 옮기고 있습니다. 그런데 연구에서 가장 눈에 잘 띄는 목표인 문제 풀이는 Tao의 표현으로 “더 가치 있는 장기 목표를 대신하는 지표일 뿐”입니다. 증명이 귀할 때는 이 대리 지표가 꽤 정확했지만 증명이 흔해지면서 어긋나기 시작했다는 것이 Tao의 주장입니다.
가장 기억에 남은 대목은 미해결 문제를 등대에 비유한 부분입니다. 미해결 문제는 “그 자체로 도달해야 할 목적지가 아니라 주변을 탐험하게 해주는 길잡이”라는 것입니다. 가는 길에 배우는 것은 실패한 시도까지 포함해서 답 자체보다 더 값질 때가 많다고 합니다.
소프트웨어도 비슷한 희소성 위에서 돌아갔습니다. 머지된 PR 하나에는 여러 가지가 묶여 있었습니다. 누군가 문제를 이해했고, 제약 조건을 따져봤고, 접근 방식을 골랐고, 실제로 돌아가게 만들었다는 사실입니다. 코드는 그중 눈에 보이는 부분이었고 배움은 대부분 그 코드에 이르는 과정에서 일어났습니다.
느린 요청 하나를 쫓다 보면 결과는 한 줄짜리 수정일 수도 있습니다. 하지만 그 과정에서 팀은 일이 어디에 쌓이는지, 부하가 걸리면 어떤 가정이 무너지는지, 두 가지 설명 중 어느 쪽이 맞는지를 가려주는 측정이 무엇인지 배웁니다. 다음 설계 결정의 바탕이 되는 것은 이 두 번째 결과물입니다.
그림 1. 과제는 변경 하나와 함께, 다음 과제를 더 잘 다룰 능력을 남깁니다. Tao의 도식을 엔지니어링에 맞게 옮겨 본 것입니다.
잘 모르는 코드를 배포하는 일은 언제든 가능했으니 PR과 이해 사이의 연결이 완벽했던 적은 없습니다. 그래도 구현에 진짜 노력이 들던 시절에는 결과물에 그 노력의 흔적이 어느 정도 남아 있었습니다.
에이전트와 일하면, 예전에는 코드를 쓰기 위해 먼저 갖춰야 했던 이해가 생기기도 전에 동작하는 구현이 먼저 도착하기도 합니다. 그렇다고 코드의 쓸모가 줄어드는 것은 아닙니다. 다만 그 코드가 존재한다는 사실만으로는 누군가 문제를 이해했는지 알기가 훨씬 어려워졌습니다.
그림 2. 제가 걱정하는 것은 이런 실패입니다. 변경은 더 빨리 도착하는데, 그 뒤의 이해는 조용히 새로 쌓이지 않게 됩니다. 일어날 수는 있지만 피할 수 없는 일은 아닙니다.
PR 숫자는 인상적이지만, 그것만으로는 부족합니다
Lauren Tan은 한 달에 프로덕션 PR을 2,500개 정도 머지한다고 밝혔습니다. Anthropic은 사내에서 Claude Code 도입이 늘면서 엔지니어 1인당 하루 머지 PR 수가 67% 늘었다고 했습니다. 둘 다 스스로 보고한 숫자이고 단위도 맥락도 다릅니다. 순위를 매길 수 있는 숫자도 아니고 AI가 생산성에 미치는 효과를 통제된 환경에서 잰 값도 아닙니다.
그렇다고 가볍게 넘기고 싶지도 않습니다. 그 정도 처리량 뒤에는 상당한 실력이 있기 때문입니다. 어떤 작업을 맡길지 고르고, 검증 장치를 만들고, 병렬로 돌아가는 작업들이 서로 부딪히지 않게 관리하는 일입니다. 그중 일부는 에이전트는 검사하는 것만 최적화해요에서 다룬 적이 있습니다.
하지만 제가 정말 궁금한 것은 숫자에 드러나지 않습니다. 사용자에게 더 나은 것이 전달됐는지, 리뷰하고 고치는 데 얼마나 들었는지, 시스템을 운영하기가 더 쉬워졌는지, 다음 장애가 났을 때 팀이 원인을 따라갈 수 있는지는 PR 수만 봐서는 알 수 없습니다.
PR 크기만 바꿔도 숫자의 의미가 달라집니다. 변경 하나를 PR 열 개로 쪼개면 숫자는 열 배가 되지만 결과물이 열 배가 되지는 않습니다.
Anthropic도 PR만으로는 “개발 속도를 재기에 불완전한 척도”라며 DORA 지표 같은 기존 지표와 함께 보라고 권합니다. 저도 같은 생각이고, 저라면 더 나은 숫자 하나를 찾기보다 주장마다 그에 맞는 증거를 고르겠습니다.
- 처리량: 범위가 비슷한 작업끼리 비교합니다.
- 결과: 사용자나 운영자가 실제로 체감하는 동작을 봅니다.
- 이해: 처음 보는 케이스를 예측하고 그 메커니즘을 설명해보라고 합니다.
- 비용: 쓸 만한 결과에 도달하기까지 든 사람의 주의력과 컴퓨팅 비용까지 셉니다.
통과한 검사에도 경계가 있습니다
소프트웨어에서는 검사마다 증명하는 것이 달라서 이 문제가 더 도드라집니다. 컴파일러는 코드로 적어둔 규칙을 확인합니다. 테스트는 우리가 고른 동작만 확인합니다. 형식 증명은 어떤 모델 안에서 특정 성질이 성립한다는 것을 보여줍니다. 프로덕션은 우리가 마침 관찰한 조건에서 시스템이 어떻게 동작했는지를 알려줍니다.
모두 증거이지만 그 모델이 현실과 맞는다는 것까지 알려주는 검사는 하나도 없습니다.
Tao의 발표에도 이런 사고 실험이 나옵니다. AI가 암 치료제를 찾아냈고, 그 수학적 모델의 예측은 Lean으로 확인됐고, 임상 3상까지 통과했습니다. 그런데 어떻게 찾았는지는 아무도 모릅니다. 그 약을 내 혈관에 넣기 전에, 메커니즘을 이해하는 사람이 적어도 한 명은 있기를 바라지 않을까요?
소프트웨어로 옮긴 작은 예시를 하나 만들어 보겠습니다. 에이전트가 재고 프로토콜을 설계하고 명시된 모델 안에서는 절대 초과 판매가 일어나지 않는다고 증명했습니다. 증명 자체는 맞습니다. 그런데 프로덕션에 남아 있는 오래된 writer 하나가 그 프로토콜을 거치지 않고 재고를 바꾸고 있습니다. 증명은 처음부터 그 경우를 다루지 않았습니다.
이 어긋남을 알아차리는 일이 엔지니어링이고 검사를 통과한 결과물을 더 빨리 만든다고 이 일이 사라지지는 않습니다. 승인 버튼을 하나 더 단다고 해결되지도 않습니다. 승인은 승인하는 사람이 결과를 판단할 만큼 맥락을 알고 있을 때만 의미가 있습니다. 모든 줄을 외울 필요는 없어도 그 결정이 기대고 있는 메커니즘과 가정은 이해해야 합니다.
값싸진 코드로 이해를 만들 수 있습니다
여기서부터는 조금 낙관적인 이야기입니다. 코드가 흔해지면서 대리 지표는 어긋났지만 바로 그 덕분에 의도적으로 이해를 쌓는 일도 싸졌습니다.
Karpathy는 모델에게 ASD-STE100으로 설명해달라고 해보라고 제안했습니다. ASD-STE100은 원래 항공기 정비 문서를 위해 만든 Simplified Technical English 규격입니다. 규격 전체는 꽤 엄격해서 그는 가끔 “ASD-STE100의 80% 정도로”라고 느슨하게 요청한다고 합니다. 문체를 바꾸는 요청일 뿐 정확성을 보장하지는 않습니다. 그래도 짧고 평이한 문장에는 이해하지 못한 단계를 숨길 틈이 적어서 저는 이 아이디어가 마음에 듭니다.
그가 더 강조한 것은 매체입니다. 글 대신 다이어그램을 달라고 하고 인터랙티브한 HTML 페이지를 달라고 하고 맞춤형 설명 영상을 달라고 해보라고 합니다. 코드가 이만큼 싸지면 질문 하나에 답하기 위해 도구를 만들고, 쓰고, 버려도 됩니다. 예전 같으면 만들 가치가 없던 도구가 이제는 조사 과정의 평범한 일부가 됩니다.
Tao도 비슷한 결론에 이릅니다. 그가 꼽은 “Math 2.0”다운 AI 활용 사례 중 하나가 “열린 설명 문제(open exposition problems)“입니다. 이미 증명은 있지만 그 증명이 불투명한 결과에 대해, 납득이 가는 설명을 찾는 일입니다. 소프트웨어로 옮기면 뜻이 꽤 분명합니다. 동작하는 코드는 이미 넘치는데 빠져 있는 것은 그 코드에 대한 설명입니다.
Thariq Shihipar의 Learn Quiz 프롬프트는 나머지 절반을 채워줍니다. 모델에게 세션 내용을 단계적으로 가르치라고 하는데, 먼저 사람이 자기가 이해한 것을 말로 정리하게 하고, 거기서 빈 곳을 채우고, 동기와 설계 결정, 비즈니스 로직, 엣지 케이스를 퀴즈로 확인하라고 합니다. 필요하면 코드를 보여주거나 디버거를 직접 써보게 하고, 이해했다는 것을 보여주기 전까지는 세션을 끝내지 말라고 합니다.
평이한 언어와 다이어그램은 설명을 받아들이기 쉽게 만듭니다. 다시 말해보고 새로운 질문에 답해보면 그 설명을 실제로 쓸 수 있는지가 드러납니다. 무언가를 직접 돌려보면 그 설명이 시스템과 맞는지가 확인됩니다.
그림 3. AI는 이 루프의 모든 단계에서 도울 수 있습니다. 우리가 안다고 생각하는 것을 시험해볼 도구를 만드는 일도 그중 하나입니다. 매끄러운 설명 하나만으로는 루프가 닫히지 않습니다.
제가 쓸모 있다고 생각하는 “Software Engineer 2.0”은 이런 모습입니다. 동작하는 소프트웨어를 배포하면서 그 소프트웨어를 이해하고 고칠 수 있는 능력도 의도적으로 함께 키우는 작업 방식입니다. (신경망이 코드를 대체한다는 Karpathy의 예전 “Software 2.0”과는 다른 이야기입니다.)
직접 해보기: 끝내 도착하지 않은 응답
작은 예시를 하나 보겠습니다. 서버가 결제를 커밋했는데, 응답이 클라이언트에 도착하지 않았습니다. 클라이언트는 타임아웃이 나서 재시도합니다.
더 읽기 전에 한번 예측해보세요. 재시도하면 고객에게 결제가 한 번 더 될까요? 그 답이 맞으려면 어떤 가정이 필요할까요?
그림 4. 타임아웃만으로는 첫 요청이 커밋됐는지 클라이언트가 알 수 없습니다. 단순화한 모델이며 특정 결제 시스템을 그린 것은 아닙니다.
답을 따져볼 수 있도록 조건을 단순하게 정해보겠습니다. 서버는 멱등성 키와 결과를 원자적으로 함께 저장하고 그 기록을 120초 동안 보관합니다. 그 밖에 중복 요청을 걸러주는 장치는 없습니다. 첫 요청은 이미 커밋됐고 그 응답은 유실됐습니다.
각 경우에 고객은 결제를 몇 번 하게 될까요? 펼쳐보기 전에 답을 먼저 정해보세요.
30초 뒤, 같은 키로 재시도
한 번입니다. 기록이 아직 남아 있으므로, 서버는 다시 결제하지 않고 저장된 결과를 돌려줍니다.
300초 뒤, 같은 키로 재시도
두 번입니다. 기록은 120초에 만료됐습니다. 서버 입장에서는 처음 보는 키이므로 결제를 다시 실행합니다.
30초 뒤, 새 키로 재시도
두 번입니다. 새 키에는 저장된 결과가 없습니다. 멱등성 계층은 설계대로 정확히 동작했지만 이 경우에는 아무 도움이 되지 않습니다.
정확히 120초에, 같은 키로 재시도
기록이 120초 시점에 만료되는지, 120초가 지난 뒤에 만료되는지에 달려 있습니다. 위의 설명은 거기까지 정하지 않았습니다. “멱등성 키를 쓰고 있습니다”라는 말은 누군가 경계값을 물어보기 전까지는 답처럼 들립니다. 그 질문이 나오면 결국 실제 코드를 열어봐야 합니다.
이런 실험 도구는 에이전트가 몇 분이면 만듭니다. 키, 지연 시간, 보관 기간을 바꿔볼 수 있게 하고, 결과를 보기 전에 먼저 예측하게 만들면 됩니다. 키가 바뀌거나 기록이 만료되는 경우를 직접 겪어보면, 대화가 “멱등성을 쓰고 있습니다”에서 끝나지 않습니다.
그래도 이것은 어디까지나 단순화한 모델입니다. 그럴듯한 화면은 맞는 가정만큼이나 틀린 가정도 충실하게 재현합니다. 이 교훈을 실제 서비스와 연결하려면 실제 구현을 대상으로 한 격리된 재현, 실제 트레이스, 또는 그에 준하는 신뢰할 만한 증거가 필요합니다.
예측이 틀리면 설명을 고치면 됩니다. 맞으면 그 가정과 적용 범위, 그리고 회귀 테스트 하나를 남겨두면 됩니다. UI는 사라져도 이해만 남으면 됩니다.
PR 숫자가 놓치는 부분이 여기에 하나 더 있습니다. AI가 만든 소프트웨어 가운데 가장 쓸모 있는 것 중 일부는 끝내 기능으로 배포되지 않을 수도 있습니다. 누군가 다른 무언가를 이해하도록 돕기 위해 존재하는 코드이기 때문입니다.
제 작업 방식에서 바꾸고 싶은 것
중요한 변경이라면, 넘겨받을 때 세 가지가 함께 오면 좋겠습니다. 이 접근이 맞으려면 성립해야 하는 가정, 그 가정을 뒷받침하는 증거, 그리고 이 접근을 깨뜨릴 수 있는 케이스입니다. 깊이는 위험에 맞추면 됩니다. 오타 수정에 튜토리얼까지 붙일 필요는 없습니다.
사람들이 따라가기 어려워하는 부분이 있다면, 구체적인 질문 하나를 중심으로 에이전트에게 설명을 만들어달라고 하고 싶습니다. 재시도 문제라면 요청 타임라인, 마이그레이션이라면 의존성 지도, 서로 다른 지연 시간 가설을 가려내야 한다면 작은 실험 매트릭스입니다.
그다음에는 그 부분을 실제로 유지보수해야 하는 사람에게 새로운 케이스를 예측해보라고 하고 싶습니다. 예측과 결과가 어긋나는 지점이 바로 다음으로 메워야 할 이해의 빈칸입니다.
무엇을 인정받을 만한 일로 볼지도 달라집니다. 기능을 배포하는 것도 좋은 기여입니다. 하지만 어떤 기능이 필요 없다는 것을 알아내는 일, 메커니즘 하나를 지우는 일, 다음 열 번의 변경을 더 안전하게 만들어주는 검증된 설명을 남기는 일도 기여입니다. 각각 자기가 주장하는 바에 맞는 증거가 있으면 됩니다.
값싸진 구현은 보통 “더 많은 패치를 더 빨리”로 이야기됩니다. 저는 그보다 더 큰 기회가, 예전에는 너무 비싸서 못 하던 조사와 설명을 이제는 할 수 있게 됐다는 데 있다고 생각합니다.
다음 작업에 들고 가고 싶은 질문은 이것입니다. 변경이 동작하고 나면, 다음 결정을 더 잘 내릴 만큼 우리는 무엇을 이해하게 될까요?
재고와 재시도 예시는 가상의 사례이고, 여기 적은 작업 방식은 제안일 뿐 배움을 개선한다는 측정된 근거는 아닙니다. 앞서 쓴 글들에서 이어지는 이야기입니다. 배움은 어디로 갔을까?, 에이전트가 커질 때 사람은 어떻게 배울까.