
다시 찾을 수 있는 회의: 타임라인 릴리스
GeekBye v1.7.3은 회의 드롭다운을 진짜 타임라인으로 교체했습니다 — 사람이 읽는 날짜, 검색, 지금 어떤 회의에 있는지 말해주는 브레드크럼. 그 아래에는: 자동 선택 레이스, 자기 회의보다 먼저 찍힌 스크린샷, 그리고 28분 동안 이루어진 다섯 번의 Windows 수정이 있었습니다.
2026년 1월 즈음, GeekBye 사용자들에게는 히스토리 문제가 생겼습니다. 앱은 회의를 잘 녹음하고 분석해 놓고는 — 그 결과를 드롭다운에 넣어 보관했습니다. 항목이 세 개일 때는 드롭다운도 괜찮습니다. 하지만 열다섯 번째 회의쯤 되면 "지난 화요일의 그 면접"을 찾는 일은 똑같이 생긴 행들 사이를 파헤치는 고고학 발굴 작업이 됩니다. v1.7.3 — 12월 중순부터 1월 16일 사이의 64개 커밋 — 은 회의가 마침내 다시 찾을 수 있는 무언가가 된 릴리스입니다.
(장부 정리 차원의 메모 하나 — 버전 번호는 정직하지 않을 때도 git 히스토리는 정직하니까요: v1.7.2 릴리스 태그는 존재하지 않습니다. 버전은 올라갔지만 다음으로 출시된 태그는 v1.7.3이었고, 그래서 v1.7.2 시절의 Windows 수정들은 이 릴리스에 함께 실려 나갔습니다.)
드롭다운에서 타임라인으로
대표 변경은 pull request 하나입니다: 12개 파일, +640줄, 그 대부분이 새로 만든 381줄짜리 MeetingsTimeline 컴포넌트입니다. 드롭다운은 스크롤 가능한 회의 카드 타임라인이 됐고, 네 개의 버킷 — Today, Yesterday, This Week, Older(오늘, 어제, 이번 주, 이전) — 으로 묶이며, 날짜는 사람이 말하는 방식으로 렌더링됩니다: Today, 2:30 PM, Yesterday, 2:30 PM, 이번 주는 Mon, 2:30 PM, 그 이전은 Jan 5, 2:30 PM. Cmd/Ctrl+K는 제목으로 필터링하는 검색 박스에 포커스를 줍니다. 회의 상세 뷰는 진짜 내비게이션 페이지가 됐고, 그래서 내비바의 뒤로·앞으로 버튼이 마침내 의미를 갖게 됐으며, 브레드크럼은 "Meetings / Meeting" 대신 "Meetings / Interview with John"이라고 읽히기 시작했습니다(말줄임표로 잘립니다 — 회의 이름을 소설 제목처럼 짓는 사람은 언제나 있으니까요).
작지만 삶의 질을 높이는 두 가지가 함께 출시됐습니다: 회의 뷰 안의 삭제 버튼(삭제 후 죽은 페이지에 사용자를 버려두는 대신 타임라인으로 되돌려 보냅니다), 그리고 자동 내비게이션 — 리스닝 세션이 실제 전사 내용을 담은 채 끝나면 대시보드가 곧바로 그 회의의 상세 페이지로 열립니다. 통화를 끝내면, 회의가 보입니다. 빈 채로 끝난 세션은 타임라인을 어지럽히는 대신 조용히 삭제됩니다.
내비게이션을 개선하면 스스로 만들게 되는 레이스
여기부터가 체인지로그에는 없는 이야기입니다. 옛 회의 목록에는 버릇이 하나 있었습니다: 로드될 때마다 최신 세션을 자동 선택하는 것. 목록이 어쩌다 한 번 건드리는 드롭다운일 때는 무해했습니다. 회의가 직접 돌아다니는 페이지가 되는 순간 치명적이 됐습니다: 회의 #5를 클릭하면, 백그라운드 refetch가 완료되고, 목록이 친절하게도 최신 회의를 선택합니다 — 2초 전에 내린 선택을 덮어쓰면서요. 수정은 더 영리한 가드가 아니라 자동 선택을 통째로 삭제하는 것이었습니다. 사용자를 대신해 무언가를 선택하는 목록은 언젠가 반드시 사용자와 싸우게 됩니다.
이걸 제거하자 두 번째 레이스가 드러났습니다. 자동 내비게이션은 세션이 끝나는 그 순간 회의로 점프합니다 — 그런데 그 시점은 세션이 로컬 SQLite 데이터베이스에 쓰기를 마치기 전일 수 있습니다. 너무 빨리 이동하면 아직 존재하지 않는 회의에 도착하게 됩니다. 출시된 수정은 상세 뷰에 도착할 때 세션 로드 전에 500밀리초 딜레이를 두는 것이고, 내비게이션 핸들러도 자기 몫의 안전장치를 지니고 다닙니다 — 대시보드가 방금 생성됐다면 창의 did-finish-load를 기다린 뒤 100ms 추가, 이미 열려 있었다면 50ms. 우리의 해석은 이렇습니다: 세션 종료 내비게이션은 세 개의 타이밍 영역 — 데이터베이스 쓰기, 창 로드, React 마운트 — 을 가로지르고, 각각이 자기만의 작은 딜레이를 얻었습니다. 작동은 합니다. 다만 매직 넘버를 쌓아 올린 것은 승리가 아니라 정직하게 인정해야 할 부채라는 점도 분명히 말해두겠습니다.
자기 회의보다 먼저 찍힌 스크린샷
이 릴리스에서 죽은 가정이 하나 더 있습니다: "스크린샷은 세션 중에 찍힌 경우, 그리고 그 경우에만 그 세션에 속한다." 완벽하게 논리적입니다. 그리고 틀렸습니다. 실제 사용자는 채용 공고, 안건, 곧 논의할 코드 위에서 Cmd+H를 누릅니다 — Start를 누르기 전에요. Report 탭은 스크린샷을 세션의 시간 범위와 엄격하게 매칭했고, 그래서 그 준비용 스크린샷들은 자기가 찍힌 이유였던 바로 그 리포트에서 사라졌습니다. 수정은 매칭 윈도우를 세션 시작 전 60초만큼 넓히는 것이었습니다. (시간 범위 장치 자체는 더 오래됐습니다 — v1.6.15에서 조용히 출시됐고; v1.7.3의 기여는 회의가 시작되기 조금 전에 시작된다는 것을 그 장치에 가르친 것입니다.)
28분 동안 다섯 번의 수정
이 릴리스의 무용담은 타임라인에 있지 않습니다 — Windows 온보딩 오버레이에 있고, 교과서적인 "수정을 수정하는" 연쇄입니다: 같은 날 아침 10:50–11:18 사이의 다섯 커밋.
GeekBye의 메인 창은 마우스 패스스루를 사용합니다 — 마우스가 움직일 때마다 Electron의 setIgnoreMouseEvents를 토글해서 투명한 영역에서는 클릭이 아래로 통과하게 하는 훅입니다. Windows에서 온보딩 중에 이 훅이 튜토리얼 오버레이와 싸웠고, 대시보드 창이 나타나는 단계에서 앱이 멈춰버렸습니다. 첫 번째 수정: 온보딩이 진행 중인 동안 훅이 아무것도 하지 않게 만들기. 무장 해제를 통한 평화입니다.
그런데 이제 온보딩 버튼이 반응하지 않았습니다. 이벤트 포워딩이 클릭을 오버레이 아래에 있는 대시보드 창으로 실어 나르고 있었기 때문입니다. 두 번째와 세 번째 수정은 마법사별로 forward: false를 만지작거렸습니다. 그다음에 진짜 근본 원인을 찾아낸 커밋이 왔습니다: 대시보드 창이 열릴 때 그 창의 드래그 핸들러가 메인 창을 클릭 통과 모드로 리셋한다 — 그리고 첫 번째 수정이 패스스루 훅을 수동적으로 만들어 놓았기에, 그 간섭을 바로잡을 수 있는 것이 아무것도 남아 있지 않았던 것입니다. 진짜 수정은 전략을 뒤집었습니다: 이제 훅은 온보딩 중에 마우스가 움직일 때마다 setIgnoreMouseEvents(false)를 능동적으로 다시 단언합니다. 외부 코드가 언제든 그것을 리셋할 수 있다는 바로 그 이유 때문에요. 그리고 앞선 마법사별 우회책 75줄도 삭제했습니다.
그러고도 다섯 번째 커밋이 있었습니다. 입력 전쟁에서 이기는 것이 z-order 전쟁에서 이기는 것은 아니기 때문입니다: 오버레이와 대시보드가 같은 always-on-top 레벨에 앉아 있었고, Windows는 포커스를 받는 창을 위로 올립니다. 오버레이는 더 높은 창 레벨로 옮겨졌고, 대시보드가 나타난 뒤 딜레이를 두고 스스로를 다시 올립니다. 이 궤적은 기억해 둘 만합니다: 유일한 수비수를 무장 해제시키는 수동적 수정은 원래의 싸움보다 나쁩니다.
이 릴리스가 우리에게 가르쳐 준 세 가지
- 내비게이션 업그레이드는 상태 버그를 수면 위로 끌어올린다. 자동 선택 레이스는 v1.7.3 이전에도 존재했습니다; 드롭다운이 그것을 체감하게 해 주지 않았을 뿐입니다. 회의가 의도적으로 이동해 다니는 페이지가 되는 순간, 사용자를 대신해 무언가를 선택하던 모든 코드가 버그가 됐습니다.
- 사용자 의도를 둘러싼 시간 경계에는 여유가 필요하다. 세션, 녹음, 리포트 — 사용자는 기계의 공식적인 윈도우보다 조금 먼저, 그리고 조금 늦게 행동합니다. 60초 스크린샷 버퍼는 사람들이 실제로 행동하는 방식을 반영한 한 줄입니다.
- 교정 역할을 하는 코드를 절대 수동적으로 만들지 마라. Windows 멈춤이 다섯 번의 수정을 잡아먹은 이유는, 첫 번째 수정이 외부 간섭에 맞설 수 있는 유일한 메커니즘을 꺼버렸기 때문입니다. 다른 코드가 언제든 당신의 불변식을 깰 수 있다면, 당신의 일은 물러서는 것이 아니라 그것을 지속적으로 다시 단언하는 것입니다.
v1 이야기의 이전 장 — 이 하나의 코드베이스에서 두 개의 브랜드 앱을 만든 이야기 — 은 하나의 코드베이스, 두 개의 앱: 포크 없이 화이트라벨링하는 방법(v1.7.1)을 보시고; 전체 궤적은 소프트웨어를 완벽하게 출시하는 것의 해부학을 보세요.