
소프트웨어를 완벽하게 출시하는 해부학: 테스트가 놓친 것을 코드 리뷰가 잡아낸 방법
GeekBye v2 시리즈 전반에 걸쳐 똑같은 일이 계속 벌어졌습니다. 개발자의 머신에서는 모든 테스트를 통과한 수정이, 코드 리뷰에 이르러서는 거의 모든 사용자에게 실패했을 것이라는 사실이 증명됩니다. 이것은 아홉 번의 릴리스 뒤에 있었던 작업 흐름 — 리뷰 게이트, 수정보다 먼저 잡아내는 진단, 그리고 "내 컴퓨터에선 되는데"를 "된다"로 바꿔놓는 출시 전 테스트 규율 — 의 이야기입니다.
몇 주에 걸쳐 GeekBye는 아홉 번의 릴리스 — v2.0.0부터 v2.0.11까지 — 를 출시했고, 이 시리즈는 그 하나하나의 이야기를 전했습니다. 그것들을 함께 읽으면 어떤 개별 버그보다 흥미로운 패턴이 눈에 들어옵니다. 몇 번이고 반복해서, 어떤 수정이 개발자의 머신에서는 모든 테스트를 통과했는데, 코드 리뷰가 그 수정이 나머지 거의 모든 사람에게는 실패했을 것임을 증명한 것입니다.
그 간극 — "내 컴퓨터에선 되는데"와 "된다" 사이의 간극 — 이야말로 안정성이 실제로 사는 곳입니다. 이것은 그 간극을 닫는 작업 흐름이자, 그것이 만들어낸 모든 릴리스의 색인입니다.
패턴: 초록불 테스트, 틀린 답
시리즈에서 가장 명확한 세 가지 사례를 여기 소개합니다. 추상적인 것을 구체적으로 만들어주기 때문입니다.
- 멀티 모니터 캡처 수정(v2.0.10)에서, 첫 구현은 화면 캡처를 앱의 오버레이 창에 앵커링했습니다. 테스트는 통과했습니다 — 단일 모니터 개발 머신에서는요. 리뷰는 그 오버레이가 실제로 어디에 사는지(당신이 물리적으로 드래그하지 않는 한, 언제나 주 디스플레이)를 따졌고, 그 "수정"이 거의 모든 실제 사용자에게 다시 엉뚱한 모니터로 귀결됐을 것임을 증명했습니다. 올바른 앵커 — 커서 — 는 테스트 실행이 아니라 그 논증에서 나왔습니다.
- WebSocket 폴백 릴리스(v2.0.8)에서, 리뷰는 차단형 프록시가 반환하는 바로 그
403이 치명적 인증 오류 로 분류돼 있다는 것을 발견했습니다 — 그래서 그 기능이 존재하는 이유였던 폴백이 결코 발동될 수 없었습니다. 그 기능은 출시됐을 것이고, 해피 패스 테스트를 통과했을 것이며, 실제 대상 사용자에게는 아무것도 하지 못했을 것입니다. - 유휴 타임아웃 수정(v2.0.9)에서, 첫 버전은 일부 전사가 정당하게 건너뛰는 코드 경로 — 상대 화자의 것 — 안에서 "아직 살아있음" 시계를 찍었습니다. 리뷰는 미래의 변경이 지금 고치고 있는 바로 그 버그를 조용히 다시 불러올 수 있음을 잡아냈고, 그 타임스탬프는 조건 없이 찍히는 곳으로 옮겨졌으며, 그것을 그 자리에 붙들어 둘 테스트가 함께 붙었습니다.
이 중 어느 것도 코드를 실행해서 잡힌 것이 아닙니다. 전부 리뷰어가 코드가 왜 돌아가는지를 따지고 — 돌아가지 않는 경우를 찾아냄으로써 잡힌 것입니다.
게이트의 세 부분
시리즈 뒤에 있던 작업 흐름은 정교하지 않습니다. 예외 없이 적용된 세 가지 습관입니다.
1. 리뷰는 코드를 실행하는 것이 아니라 정확성을 따진다. 통과한 테스트는 당신이 생각해낸 경우에 대해 코드가 돌아간다는 것을 증명합니다. 리뷰는 시스템에 대한 두 번째, 적대적인 모델이 당신이 생각하지 못한 경우는 무엇인가? 를 묻는 것입니다 — 두 번째 모니터, 회사 프록시, 분기를 건너뛰는 전사, 한 버전 뒤처진 클라이언트. 이 시리즈의 리뷰 단계는 종종 수정을 축복하는 것이 아니라 반박 하도록 프롬프트된 독립 에이전트 리뷰어였습니다. 그 프레이밍이 핵심의 전부입니다. 당신의 논증을 깨뜨리려는 리뷰어는 승인하려는 리뷰어가 대충 훑고 넘어가는 구멍을 찾아냅니다.
2. 모든 동작 수정은 정확한 실패 지점을 고정하는 테스트와 함께 출시된다. 기능이 돌아간다는 테스트가 아니라 — 이 특정 버그 가 죽었다는 테스트입니다. 차단된 프록시의 403은 반드시 폴백으로 흘러가야 하고, 진짜 인증 403은 반드시 그러면 안 됩니다. 활동 시계는 반드시 어트리뷰션을 건너뛰는 전사에서도 찍혀야 합니다. 이 테스트들은 여섯 달 뒤 누군가가 근처를 리팩터링할 때 버그가 조용히 되돌아올 수 없도록 존재합니다 — 실패는 바닥에 못박혀 있습니다.
3. 빌드는 출시 전에 노터라이즈되고 검증된다. 이 수정들 중 여럿은 진단에서 서명·노터라이즈되고 자동 업데이트되는 릴리스까지 하루 안에 갔습니다. 그 속도는 게이트가 규율 있게 지켜지기 때문에만 안전합니다. 진단이 근본 원인을 증명하고(마이크 권한 릴리스는 진단을 먼저 출시했습니다), 테스트가 수정을 고정하고, 리뷰가 그 논증을 반박하고, 오직 그런 다음에야 진짜 노터라이즈 빌드가 나갑니다. 엄밀함은 속도를 안전하게 만드는 것이지, 속도와 맞바꾸는 것이 아닙니다.
왜 이것이 AI 앱에 더 중요한가
이 규율이 특히 GeekBye 같은 도구에 타협 불가인 데는 이유가 있습니다. 시리즈에서 가장 고약했던 버그들 중 여럿은 크래시로 요란한 게 아니라 조용히 틀린 것이었습니다. 스크린샷이 AI에게 엉뚱한 모니터 를 먹인 것(v2.0.10), 전사가 잡스러운 용어 쪽으로 치우쳐 "speak"가 이름으로 나온 것(v2.0.11), 어시스턴트가 엉뚱한 모드로 답하는데 그것을 볼 방법이 없던 것(v2.0.3 + v2.0.5). 당신의 앱이 모델에 컨텍스트를 먹일 때, 틀린 입력은 확신에 찬 틀린 출력을 만들고 어디에도 에러가 없습니다. 예외를 던지지 않는 실패는 테스트로 빠져나올 수 없습니다. 논증으로 빠져나와야 합니다 — 그리고 그것이 바로 리뷰 게이트가 존재하는 이유입니다.
시리즈, 순서대로
이것들 각각은 하나의 릴리스를 다룬 자족적인 사례 연구입니다. 처음부터 끝까지 읽으면, 제품을 "돌아간다"에서 "믿을 만하다"로 데려가는 해부학이 됩니다.
- 버전 2가 실제로 요구하는 것: 정직한 상태를 위한 206개의 커밋 — v2.0.0. 그 토대: 참이 아닌 상태는 결코 보여주지 않는다.
- 우리 앱이 스스로를 DDoS한 날 — v2.0.1 + v2.0.4. 시작 시 업로드 백로그가 우리 자신의 백엔드로 몰려든 사건과, 그것이 강제한 라이브니스 사다리.
- 차분한 소프트웨어: 깜빡임 수정과 답변 모드 칩 — v2.0.3 + v2.0.5. 신뢰를 한 번에 하나의 디테일씩 사들인, 기능 없는 릴리스들.
- 당신의 Mac 앱이 실행할 때마다 마이크 접근 권한을 잊는다 — v2.0.6. macOS 앱 트랜스로케이션과, 수정보다 먼저 진단을 출시하기.
- CSS 변수 하나, 다섯 번의 리뷰 라운드, 그리고 거짓말한 Swift 툴체인 — v2.0.7. 균일한 반투명함과, 문서가 강제 스크립트와 어긋나서 크기가 바뀐 바이너리.
- 방화벽이 WebSocket을 차단할 때의 라이브 전사 — v2.0.8. 순수 HTTPS 폴백과, 그것을 스스로에게서 숨겼을
403. - 당신의 AI 노트테이커가 회의 중간에 녹음을 멈추는 이유 — v2.0.9. 당신 소리만 들을 수 있었던 유휴 타이머와, 당신의 데스크톱을 잠가버릴 수 있었던 크래시.
- 화면 녹화가 엉뚱한 모니터를 잡는 이유 — v2.0.10. 엉뚱한 디스플레이 버그와, 모니터 하나에서는 통과하고 둘에서는 실패했을 수정.
- AI 전사가 기술 용어를 잘못 알아듣는 이유 — v2.0.11. 음성을 당신의 어휘 쪽으로 편향시키기 — 그리고 나아지기 전에 상황을 악화시킨 회귀.
핵심 메시지
완벽은 도달하는 상태가 아니라 지켜내는 게이트입니다. 아홉 번의 릴리스, 그리고 매번 똑같은 세 가지 질문. 당신이 생각하지 못한 경우는 무엇인가, 정확한 실패가 테스트로 고정돼 있는가, 그리고 진짜 서명된 빌드가 실제로 나갔는가? 그 어느 것도 화려하지 않습니다. 그리고 그 모든 것이 GeekBye v2가 차분하게 느껴지는 이유입니다. 당신이 소프트웨어를 만든다면 — AI든 아니든 — 옮겨 담을 수 있는 부분은 어떤 개별 수정이 아닙니다. 초록불 켜진 테스트 스위트를 논증의 끝 이 아니라 시작 으로 대하는 습관입니다.
위의 모든 릴리스는 자동 업데이트로 라이브 상태입니다. 이 수정들이 모여 만든 제품에 대해서는 GeekBye v2의 새로운 소식을 보세요.