이번 주는 hyper의 대화 구조를 통째로 뜯어고쳤다.
그동안 hyper에는 봇과의 1:1 대화가 있고, 여러 봇을 묶는 그룹이 따로 있었다. 처음엔 그게 자연스러워 보였는데, 봇이 늘어나니까 같은 주제를 어디서 얘기했는지 내가 못 찾겠더라. 1:1에서 시작한 얘기를 그룹으로 못 옮기고, 그룹에서 정리한 걸 다시 1:1로 못 가져오고. 결국 슬랙처럼 채널 하나로 다 통일하기로 했다. DM도 그냥 봇 하나짜리 채널이다.
한번에 갈아엎는 대신 단계를 잘게 쪼갰다. 채널 저장소를 먼저 만들고, 그 위에 라운드/릴레이/스레드를 도는 턴 러너를 올리고, 기존 그룹을 채널로 승격시키는 마이그레이션을 붙이고, 루틴을 채널로 흘려보내고, HTTP API와 SSE를 뚫고, 웹 UI와 네이티브 UI를 각각 얹고, 마지막에 플래그로 컷오버. 여러 갈래를 동시에 밀어붙였다. 마이그레이션보다 롤백을 먼저 만들었는데, 이번 작업에서 제일 잘한 선택인 것 같다. 되돌릴 수 있다는 걸 알고 나니까 그 뒤로는 겁 없이 밀 수 있었다 (실제로 롤백을 쓴 적은 없지만, 그건 별개다).
--
그리고 나서는 계속 지웠다. 레거시 1:1 채팅과 그룹 채팅 웹 컴포넌트, 그룹 HTTP 표면, 네이티브의 죽은 대화/그룹 탭과 그 생성 시트, 안 쓰는 훅, 완료된 plan 문서 스물한 개. 음성 모드(STT/TTS)도 이번에 통째로 들어냈다. 만들 때는 꽤 공들였던 기능인데, 몇 달을 안 쓰더라. 텍스트로 봇한테 시키는 게 훨씬 빠르고 정확한데 굳이 말을 걸 이유가 없었던 것 같다.
새 기능 커밋보다 삭제 커밋을 볼 때가 더 후련했다. 왜 만들 때보다 지울 때 기분이 좋은 걸까. 만드는 건 미래에 대한 약속이고 지우는 건 그 약속을 이제 안 지켜도 된다는 확인이라 그런가 (아닐 수도 있고).
--
채널이 생기고 나니 슬랙에서 당연한 게 여기엔 하나도 없다는 게 보였다. 그래서 남은 시간은 대부분 그걸 채우는 데 썼다. 멘션 자동완성과 멘션 칩, 리액션, 북마크, ⌘K 검색과 메시지로 점프, 슬래시 커맨드, 클립보드 이미지를 붙여넣으면 그대로 첨부되는 것, 프로필 이름과 아바타, 같은 사람이 연달아 쓴 메시지는 하나로 합치기. 하나하나는 별거 아닌데 이게 없으면 채팅 같지가 않다.
제일 마음에 드는 건 봇이 지금 뭘 하고 있는지 흘려보내는 거다. 예전엔 봇한테 뭘 시키면 한참 조용하다가 결과만 툭 떨어졌다. 그 침묵이 늘 불안했다. 지금은 도구를 부르는 중이면 부르는 중이라고, 루틴이 돌고 있으면 돌고 있다고 그 자리에 보여준다. 결과가 빨라진 건 아무것도 없는데 체감은 완전히 다르다.
봇 말투도 손봤다. 이모지 불릿을 강제로 붙이던 규칙을 걷어내고, 절을 이어붙이는 em dash를 금지하고, 조직 공통 규칙을 봇에 물려서 톤 감사를 돌게 했다. 봇이 사람처럼 말하게 만들려고 규칙을 이렇게까지 쌓는 게 맞나 싶긴 한데, AI가 쓴 티 나는 문장을 매일 읽는 것보단 낫다고 생각하는 중이다.
--
이번 주엔 문서도 꽤 고쳤다. README에 없는 기능이 적혀 있고, 아키텍처 문서가 이미 사라진 모듈을 가리키고 있었다. 채널로 갈아엎으면서 코드는 다 바뀌었는데 문서만 옛날 세계에 남아 있던 거다. 다 고치고 나서 문서가 또 어긋나면 테스트가 깨지도록 가드를 두 개 붙였다. 파이썬·타입스크립트·스위프트 린트도 CI에 다 물렸고, 타입 힌트 누락 여든여섯 건을 한 번에 정리했다. 재미있는 일은 아닌데, 이런 걸 안 해두면 다음에 크게 갈아엎을 때 내가 고생한다.
곁다리로 제주 주차 앱은 1.0.0 첫 제출 준비를 마쳤다. 패키지 이름 통일하고, 런치 화면 정리하고, 요금 계산 결과 다듬고, 배너를 폭 100% 어댑티브로 바꾸고, 스크린샷 캡처 하니스까지. 서류 채우는 게 힘든 건 지난주에 이미 배웠는데도 또 오래 걸렸다. 맛집 앱에는 AdMob 배너를 붙였고, heg-core엔 이번 주에도 지식이 조금씩 쌓였다.
다음 주엔 채널을 실제로 며칠 써보면서 뭐가 불편한지 볼 생각이다. 만든 사람이 쓰기 시작하면 그때부터가 진짜인 것 같다.
26.07.26 — 새로 만든 줄보다 지운 줄이 더 많았던 주.


