
버전 2에 정말로 필요한 것: 정직한 상태를 위한 206개의 커밋
GeekBye v2는 기능 릴리스가 아니었습니다. 그것은 단 하나의 생각을 겨냥한 206개의 커밋이었습니다 — 앱은 결코 자신의 상태에 대해 거짓말해서는 안 된다는 것. 그 대가가 무엇인지 여기 적습니다 — 우리가 그 어느 것도 출시하지 못할 뻔하게 만든, 한 줄짜리 잠금 파일 실수까지 포함해서.
대부분의 "버전 2" 릴리스는 더 큰 숫자가 붙은 새 기능 더미입니다. GeekBye v2는 그 반대였습니다. 사용자에게 보이는 새로운 능력은 거의 아무것도 출시하지 않았습니다. 그 206개의 커밋은 단 하나의, 화려하지 않은 생각을 겨냥했습니다:
앱은 사실이 아닌 상태를 당신에게 보여줘서는 안 된다.
이것은 당연하게 들립니다 — 데스크톱 앱이 조용히 거짓말하는 방법이 몇 가지나 되는지 세어보기 전까지는. 아직 전송 중인 업로드에 체크마크를 표시합니다. 1분 전에 죽은 소켓 위에서 "연결됨"이라고 말합니다. 당신의 회의록이 바닥에 떨어지는 동안 침묵합니다. 이들 중 어느 것도 크래시가 아닙니다. 크래시보다 나쁩니다. 왜냐하면 앱은 틀렸는데도 멀쩡해 보이니까요 — 그리고 당신은 나중에야 알게 됩니다, 필요했던 녹음이 거기 없을 때.
v2는 우리가 그 작은 거짓말 하나하나를 사냥하러 나선 릴리스였습니다.
우리가 가장 싫어한 거짓말: "성공한" 업로드
GeekBye는 당신의 녹음을 Google Drive에 백업할 수 있습니다. v1에서 Drive로의 연결은 배경의 세부 사항으로 취급되었습니다 — 잘되면 좋고, 안 되면 그 실패는 대부분 보이지 않았습니다. 앱은 연결된 것처럼 보인 채로 계속됩니다. 당신은 녹음이 안전하다고 믿습니다. 때로는 그렇지 않았습니다.
v2는 이것을 정직한 연결 상태를 중심으로 다시 만들었습니다. Drive는 이제 항상 몇 가지 명시적이고 참된 상태 중 하나 — 연결됨, 재연결 중, 끊김 — 에 있으며, 앱은 그 상태가 바뀌는 순간 그 변화를 인터페이스 전체로 방송합니다. 연결이 끊겼을 때, 전역 재연결 배너가 어디서든, 분명하게 당신에게 알립니다. 앱은 더 이상 업로드가 성공하지 않았는데 성공한 척하지 않습니다. 백업이 지금 될 수 없다면, 당신은 지금 그것을 압니다 — 파일을 찾으러 가는 다음 주가 아니라.
그 아래에 있는 것은 슬로건이 아니라 작은 아키텍처입니다: 연결에 대한 단 하나의 진실의 원천, 그것이 바뀔 때 UI의 모든 부분으로 퍼지는 이벤트, 그리고 그 상태에서 직접 읽는 배너. 연결이 끊겼는데 UI가 연결된 것처럼 보이는 경로는 존재하지 않습니다. 왜냐하면 둘은 같은 사실에서 읽으니까요.
잃어버린 녹음이라는 거짓말
두 번째 큰 정직함의 수정은 녹음 복구였습니다. 실시간 전사에는 살아있는 연결이 필요합니다. v1에서는 그 연결이 세션 도중에 딸꾹질하면 — Wi-Fi 끊김, 터널, VPN 재연결 — 그 공백 동안의 오디오가 그냥 사라질 수 있었습니다. 회의록에는 구멍이 뚫리고, 아무것도 그것을 알려주지 않았습니다.
v2는 계약을 바꿨습니다: 오디오는 연결 공백 동안 로컬에 보존되고 나중에 대조됩니다. 링크가 끊기면 GeekBye는 오디오를 당신의 기기에 안전하게 보관합니다. 돌아오면 그 버퍼된 오디오가 전송되어 올바른 위치에서 회의록에 꿰매어집니다. 나쁜 30초의 네트워크가 더 이상 30초의 회의를 앗아가지 않습니다. 이것은 이후의 신뢰성 릴리스들이 직접 그 위에 쌓아 올린 토대입니다 — 당신의 AI 노트테이커가 나쁜 Wi-Fi에서 멈추는 이유에 있는 재연결-그리고-버퍼 장치는, 같은 생각을 더 단단하게 만든 것입니다.
팝업 폭풍이라는 거짓말
앱이 문제를 보고하는 방식에는 더 미묘한 부정직함이 있습니다: 과도하게 보고하는 것입니다. 한 번의 불안정한 네트워크 순간이 같은 오류를 다섯 번 발화시킬 수 있고, 갑자기 당신은 동일한 빨간 토스트 더미를 갖게 되어, 정작 중요한 하나의 메시지를 파묻어 버립니다. 그것도 정직하지 않습니다 — 그것은 정보인 척하는 소음입니다.
그래서 v2는 카테고리 키 기반 토스트 조절과 오류 라우팅을 추가했습니다. 오류는 실제로 무엇인지에 따라 그룹화되고, 각 카테고리는 속도 제한이 걸리므로, 하나의 근본 문제가 집중 포화가 아니라 하나의 명확한 메시지를 만듭니다. 속도 제한 문제는 속도 제한 메시지로, 연결 문제는 연결 메시지로 라우팅됩니다. 앱은 무엇이 참인지를, 한 번 말합니다 — 나중에 우리 앱이 스스로를 DDoS한 날에서 429가 로그아웃으로 위장하는 것을 막은 것과 같은 규율입니다.
206이라는 숫자가 요점입니다
정직한 상태, 재연결 배너, 녹음 복구, 토스트 라우팅 — 이것으로 네 가지 아이디어입니다. 릴리스는 206개의 커밋이었습니다. 나머지는 어디로 갔을까요?
"결코 거짓 상태를 보여주지 않는다"가 실제로 요구하는, 화려하지 않은 롱테일로 갔습니다. 옛 UI가 현실과 어긋날 수 있었던 모든 곳을 찾아내어, 낡은 복사본이 아니라 진실에서 읽도록 다시 배선해야 했습니다. 모든 재연결 경로가 로컬에서 추측하는 대신 공유 상태를 업데이트하도록 만들어야 했습니다. 녹음, 전사, 업로드에 걸친 수십 개의 작은 신뢰성 수정 — 그 하나하나가 앱이 옳아 보이면서 틀릴 수 있는 특정한 틈을 막았습니다.
이것이 목표가 기능이 아니라 신뢰일 때, 진짜 "버전 2"가 요구하는 것입니다. 단 하나의 헤드라인 커밋은 없습니다. 아무도 개별적으로 가리킬 수 없는 206개의 작은 커밋이 있고, 릴리스가 오직 한 가지 — 고요함 — 처럼 느껴지는 것은, 그 206개 모두가 같은 방향으로 당기기 때문입니다.
릴리스는 하마터면 출시되지 못할 뻔했습니다
여기 무용담이 있고, 게다가 좋은 것입니다. 왜냐하면 그것은 우리 자신의 앱이 우리에게 거짓말한 이야기니까요.
릴리스를 낼 때, 버전 올리기 스크립트가 새 숫자를 프로젝트 전체에 찍습니다. v2.0.0에서 그것은 앱의 버전을 업데이트했습니다 — 그러나 npm의 정확한 의존성 장부인 package-lock.json은 옛 버전 1.9.0을 가리킨 채로 남겨졌습니다. 로컬에서는 모든 것이 괜찮았습니다. 빌드하려고 의존성을 다시 설치하는 사람은 없으니까요. 하지만 CI는 npm ci를 실행하고, npm ci의 일 전체는 잠금 파일이 매니페스트와 어긋나면 진행을 거부하는 것입니다. 그것은 엄격함 기능이며 — 그리고 그것은 정확히 해야 할 일을 했습니다, 우리가 낸 가장 큰 릴리스의 빌드를 실패시킴으로써.
그런 다음, 그 아래에서 더 교활한 두 번째 것이 떠올랐습니다. 더 새로운 npm이 선택적 전이 의존성을 가지치기해 버린 것입니다 — node-fetch가 끌어오는 encoding 패키지를 — 불필요하다며 잠금 파일에서. 그런데 우리 CI의 깨끗한 설치는 그것을 필요로 했으므로, 설치는 우리 코드와는 아무 관계도 없고 장부가 미묘하게 틀렸다는 데 전적으로 원인이 있는 방식으로 망가졌습니다.
둘 다 한 줄 수정이었습니다: 잠금 파일을 진짜 버전에 재동기화하고, 가지치기된 항목을 복원하는 것. 둘 다 또한 v2가 다뤘던 바로 그것의 완벽하고 겸손하게 하는 예입니다 — 참이라고 주장했으나 참이 아니었던 상태. 잠금 파일은 앱이 무엇에 의존하는지의 정직한 기록이어야 합니다. 그것이 현실에서 어긋났을 때, 빌드는 우리 앱이 이제 사용자를 위해 하는 것과 정확히 똑같은 일을 했습니다: 모든 것이 괜찮은 척하기를 거부한 것입니다. 신뢰성 릴리스를 출시하는 일은, 알고 보면 밑바닥까지 신뢰성 문제입니다.
v2가 우리에게 가르쳐 준 세 가지
- 위험한 실패는 조용한 것들이다. 크래시는 스스로를 알립니다. 거짓 "연결됨", 유령 같은 업로드 성공, 보이지 않는 구멍이 뚫린 회의록 — 그것들이 당신의 신뢰를 앗아가는 것은 바로 아무것도 잘못돼 보이지 않기 때문입니다. 조용한 거짓말을 사냥하세요.
- 정직함은 아키텍처이지 메시지가 아니다. "진실을 말하라"를 배너로 UI에 덧붙일 수는 없습니다. 배너는 다른 모든 것과 같은 단 하나의 진실의 원천에서 읽어야 합니다. 그러지 않으면 그것은 틀릴 수 있는 또 하나가 되어 버립니다. 하나의 사실을, 퍼뜨리는 것 — 어긋날 수 있는 두 개의 복사본을 결코 만들지 않는 것.
- 숫자에 값하는 버전 2는 대부분 보이지 않는다. 당신의 v2가 기능 목록이라면, 그것은 마케팅이 붙은 v1.5입니다. 진짜 v2는 아무도 개별적으로 가리킬 수 없는 206개의 커밋이며, 그것들이 합쳐져 그저 당신에게 거짓말하기를 멈추는 제품이 됩니다.
GeekBye v2.0.0은 그 이후 모든 릴리스가 그 위에 쌓아 온 토대입니다. 그 토대가 무엇을 지탱하는지에 대해서는, 당신의 AI 노트테이커가 나쁜 Wi-Fi에서 멈추는 이유, 우리 앱이 스스로를 DDoS한 날(v2.0.1), 그리고 방화벽이 WebSocket을 막을 때의 실시간 전사(v2.0.8)를 보세요. 그 모든 것이 봉사한 고요함에 대해서는, GeekBye v2의 새로운 점을 보세요.