3-1. 빈 저장소에서 첫 글자까지 (6/3 ~ 6/12)
첫날에 뼈대를 다 세웠다
시작은 코드가 아니라 계획서 검토였다.
"문서 읽고 평가해줘, 내가 지금 구현하려고 이것저것 계획 세웠거든." — 2026-06-03
"수정해야되는 부분은 다 수정해주세요 수행전에 계획 엄청 명확하게 잡고 싶어요" — 2026-06-03
그리고 계획서를 고칠 때마다 같은 요청이 반복된다 — "또 한번 수정했는데 메인기준으로 적대적 관점으로 리뷰해줘요". 첫날에만 이 왕복이 여러 번 있었다.
clean-room 원칙도 첫날 질문에서 구체화됐다. 무엇을 근거로 삼고 무엇을 오라클로 쓸지가 쟁점이었다.
"공개명세는 어디서 참고해요? 공게명세도 레퍼런스에 당연히 있어야 하고 개발시 참고해야하는데" — 2026-06-03
"외부 오라클에 고스티는 없어요? 가능한 오라클 뭐뭐 있죠?" — 2026-06-03
"libvterm이 가장 표준에 가까운거예요??" — 2026-06-03
"tmux는 붙이면 어떤 이득이 있어?? 얜 고스티같은 터미널은 아니잖아" — 2026-06-03
6월 3일 하루에 들어간 것들이다.
- Zig 개발환경 부트스트랩
- 터미널 전략 노트, 구현 계획, 사전 계약 문서
- 에이전트 규칙과 프로젝트 구조
- 클린룸 터미널 코어 정책
- 헤드리스 E2E 스캐폴드
- 외부 oracle,
@import경계 검사, 포맷 게이트 - 성능 예산 하네스와 스트레스 테스트 계층
코드보다 게이트가 먼저 섰다는 게 특징인데, 이것도 의도적이었다.
"구현전에 미리 가능한 테스트는 미리 붙이고 싶은데." — 2026-06-03
"그리고 구현파일에 테스트코드가 있는게 아니라 _test로 분리하거나 폴더로 분리하는건 어떻게 생각하나요? 고스티는 테스트코드 어떻게 작성..." — 2026-06-03
경계 검사기와 성능 예산이 첫날부터 CI에 걸려 있었기 때문에, 이후 두 달 반 동안 경계를 넘는 커밋이 조용히 들어오지 못했다. PR 규칙(템플릿·라벨·담당자)도 같은 날 정해졌다.
PTY: 읽는 쪽부터 계약으로
6월 4~5일에 터미널 호환성과 스키마 계약을 정리하고 PTY 리더를 세웠다.
- macOS
openpty세션 - PTY reader 생명주기 — bounded 큐, self-pipe wake, kqueue
NOTE_EXIT - 종료 정책
HUP → TERM → KILL - runtime event pump와 surface runtime 라우팅
- 헤드리스 PTY 데모
같은 시기에 셀 폭 모델과 폰트 렌더링 전략을 정리하면서, grapheme·ZWJ·ambiguous-width·faux bold 같은 어려운 항목은 미룬다고 명시했다. 나중에 6월 23일에 이 항목들을 정면으로 다시 연다.
CoreText → Metal
6월 6~7일은 렌더링에 집중한 이틀이다. 6일에는 Metal 스모크, CoreText 셰이핑 스모크, glyph texture·glyph text 스모크를 쌓고 appearance 색 해석과 프레임 probe, 스크린샷 캡처로 파이프라인을 실측했다. 7일에는 40커밋으로 파이프라인을 완성했다.
- CoreText 셰이퍼·rasterizer·font adapter 경계 추출
- DrawList를 CoreText로 셰이핑해 Metal로 렌더
- shaped glyph record 어댑터, render frame이 glyph quad를 소유하는 구조
- font identity registry와 제품 atlas 샘플링 검증
"셰이핑은 CoreText, 그리기는 Metal, 그 사이는 DrawList"라는 구조가 이때 굳었다. 이 시기 PR은 대부분 브랜치 하나에 슬라이스 하나였고, 머지 전에 /code-review max --fix를 브랜치에 직접 돌렸다 — 6월 5~7일 사흘 동안 이 명령이 30번 넘게 반복된다.
렌더링 품질은 눈으로 보고 잡았다. 첫 글자가 화면에 뜬 직후부터 이런 보고가 이어진다.
"mise 도 m i s e 처럼 보여요 폰트 렌더링 여전히 잘못되고 있는것 같은데 루트커즈 찾아봐주세요" — 2026-06-09
"벌어짐은 해결됐는데 크고 또렷하지 않음" — 2026-06-09
"맥북 내장 화면에 옴기면 scr:2.0 win:2.0 외장 모니터에 하면 1.0 1.0 떠요" — 2026-06-09
해결 방식도 일정하다 — "다른 터미널 해결책은 어떤거예요? 특히 고스티는 어떻게 하고 있는지?"(6/9), "고스티 직접 코드 보고 확인해보세요 레퍼런스에 있는데"(6/9). 레퍼런스는 답을 베끼는 곳이 아니라 "우리만 안 하고 있는 것"을 찾는 대조군으로 쓰였다.
화면이 살아나기 시작한다
6월 12일 하루에 들어간 PR만 40건이 넘는다. 탭·사이드바·OSC 133·SplitTree 네 축을 동시에 밀었다.
멀티탭의 모양은 cmux를 기준으로 잡았다.
"씨먹스는 왼쪽 사이드탭도 있고, 그 탭 하나하나당 또 일반적인 화면 나누는 탭을 열 수 있고 위치도 드래그 되는데요, 이런걸 원하..." — 2026-06-12
"그리고 스피릿 탭같은경우(패널로 지칭할게) 마우스 상단에 패널(탭) UI가 따로 있어서 드래그도 되고, X도 있고" — 2026-06-12
이 시기의 결정
- PTY는 논블로킹으로. 마스터 fd를 논블로킹으로 두고 배치 큐로 받는다. 출력이 많은 명령에서 UI가 멈추지 않게 하는 토대다.
- 탭은 cmux 정도로. 첫 문서의 "tmux 호환 대체물은 만들지 않는다"를 지키면서, 분할은 SplitTree로 일반화했다.
- IME는 미루지 않는다. 한국어 입력을 쓰는 사람이 만드는 터미널이라, 조합 표시와 커서 처리를 초기에 넣었다. 이 축은 이후에도 계속 회귀 검사 대상이 된다.
- 방어 코드를 기본값으로 두지 않는다. "방어코드는 정말 불가피할때만 나와 상의하고 진행해"(6/12). 실패를 삼키는 대신 계약을 명확히 하고 assert로 잡는 방향이다.
- 아까우면 버린다. "기존 설계 아끼려하지말고 엎어야한다면 엎어서 진행하세요"(6/12), "장기적으로 기존 코드 갈아엎는게 유지시키는것보다 이득이라면 갈아엎어도 상관없어요"(6/13). 7~8월에 여러 축을 통째로 재설계하는 결정들이 이 원칙 위에서 나온다.
- Swift는 최소한만. "스위프트 코드 최소화는 지키면서 하시는거죠?"(6/13), "그리고 문서 정책에도 쓰여있지 않았나요? 네이티브 의존성은 최대한 줄인다로"(6/9).