Glyph v0.2: 릴리스는 결합이다
Source: Dev.to
Glyph v0.2가 오늘 배포되었습니다. v0.1 다음 날에 나온 것입니다. 새 컴포넌트 7개: text-input, select, modal, confirmation, kbd, table, stat-card. 카탈로그가 16개에서 23개로 늘어났습니다. 하지만 카탈로그 자체가 릴리즈가 아니라, 릴리즈는 이들이 조합되는 것입니다.
컴포넌트와 함께, v0.2는 examples/ 트리 안에 세 개의 단일 바이너리 TUI를 제공합니다:
chat-cli: 에이전트 스타일 REPL로 13개의 컴포넌트를 조합합니다:status-bar,chat-thread,chat-bubble,chat-input,key-hints,notification-toast,spinner,command-palette,modal,text-input,confirmation,select,theme.log-viewer:journalctl스타일 실시간 피드로 9개의 컴포넌트를 조합합니다:log-stream,tabs,status-bar,key-hints,notification-toast,panel,text-input,select,theme.dashboard: 인게이지먼트 제어실로 9개의 컴포넌트를 조합합니다:tabs,stat-card,table,text-input,modal,status-bar,key-hints,notification-toast,theme.
각 TUI는 하나의 Go 파일로 이루어져 있습니다. 각각은 합성된 tea.Msg 값을 사용해 모델을 구동하고 렌더링된 뷰를 검증하는 헤드리스 테스트 스위트를 가지고 있습니다.
컴포넌트에 대한 단위 테스트는 “이 고립된 조각이 자체 입력에 대해 올바르게 동작하는가?”이고, 합성 테스트는 “text-input이 modal 안에, 다시 lipgloss.Place 로 그려진 탭 스트립 위에 감싸여 있을 때도 정상적으로 동작하는가?”입니다. 두 번째 테스트가 첫 번째 테스트로는 잡히지 않는 버그를 찾아냅니다.
저는 거의 dashboard를 10개의 컴포넌트가 조합된 형태로 배포하려고 했습니다. main.go 상단에 _ = panel.New(theme.Default) 라는 사용되지 않은 임포트 라인을 남겨두고, 문서 문자열에 “10개의 컴포넌트가 조합됨”이라고 적었죠. 그런데 panel은 실제로 어디에서도 그려지지 않았습니다. 커밋 중간에 이를 발견하고 임포트를 삭제했으며, 파일 내 문서 문자열, CHANGELOG, README 모두 9개로 수정했습니다.
dashboard는 실제로 9개의 컴포넌트를 조합합니다. 릴리즈 포스트에서 숫자가 과장된 것처럼 보인다면, 보통 실제입니다. 이를 잡아내는 방법은 푸시하기 전에 자신의 diff를 꼼꼼히 살펴보고, 문서 문자열에 적힌 단어들이 파일 전체를 검색해도 살아남는지를 확인하는 것입니다.
새로운 7개 컴포넌트 중 4개는 오버레이 형태입니다: modal, confirmation, select, 그리고 (덜 명확하게) command-palette(v0.1에 이미 포함). 이들 모두 호스트에게 동일한 세 가지를 요구합니다:
- 해제될 때까지 포커스를 잡는다.
Esc키를 취소 메시지로 라우팅해 부모가 매칭할 수 있게 한다.- 닫힐 때 부모 뷰의 키맵을 복원한다.
저는 modal, confirmation, select를 각각 별도 핸들러를 가진 형제로 구현했지만, 라우팅 패턴을 뒤늦게 깨달았습니다. chat-cli 데모에서는 채팅 스레드 위에 modal이 그려지고, 그 안에 confirmation이 열립니다. 라우팅이 정상 동작하는 이유는 각 오버레이가 자신에게 해당하는 키만 처리하고, 나머지는 부모의 Update로 넘겨주기 때문입니다. 이 패턴은 설계된 것이 아니라, 모든 오버레이가 같은 요구사항을 갖게 되면서 자연스럽게 나타난 것입니다.
앞으로 viewstack 원시 타입이 도입된다면 이 패턴을 정형화할 수 있을 겁니다. 하지만 v0.2에는 포함되지 않습니다. 원시 타입을 추출하기 적절한 시점은 중복보다 파라미터가 적게 되는 경우입니다. 최소 세 개의 오버레이가 있어야 하고, 저는 다섯 개가 될 때까지 기다리려 합니다.
v0.1 릴리즈 페이지에서는 각 컴포넌트별 갤러리 GIF를 제공하겠다고 약속했지만, README는 visuals/out/*.gif 를 가리키는 원시 HTML <img> 태그만 넣어두었습니다. GIF 파일은 제 로컬에만 존재했고, 레포에는 포함되지 않았습니다(visuals/out/*.gif 가 .gitignore에 의해 제외됨). 그 결과 첫날 전체