사이드바를 드롭다운에서 플랫 카드로
이날은 두 프로젝트를 만졌다.
하나는 내가 만드는 AI 에이전트용 터미널 앱인 Agentree의 사이드바를 개편한 거다.
다른 하나는 코딩 에이전트 도구에 세션 상태별 프롬프트 주입 플러그인을 만든 거다.
Agentree의 사이드바를 개편했다.
이전에는 중첩 드롭다운 메뉴였다.
워크트리랑 브랜치가 클릭해서 펼치는 메뉴 안에 숨어 있었다.
이러면 스캔이 느리다.
뭐가 있는지 보려면 클릭을 여러 번 해야 한다.
시각적 깊이가 깊어서 한눈에 안 들어온다.
그래서 플랫 카드 레이아웃으로 바꿨다.
각 워크트리랑 브랜치를 카드로 만들었다.
활성 상태랑 비활성 상태가 카드에 바로 보인다.
클릭하지 않아도 전체가 한눈에 들어온다.
상호작용
카드에 여러 상호작용을 넣었다.
크기 조절, 케밥 메뉴로 삭제랑 이름 변경, 인라인 라벨 편집. 아코디언으로 워크트리 그룹을 접었다
펼 수 있다.
접기 상태는 로컬 스토리지에 저장해서 앱을 다시 켜도 유지된다.
툴팁이랑 팝오버 위치는 부동 UI 라이브러리로 처리했다.
화면 경계를 자동으로 감지해서 잘린다.
그리고 낙관적 UI를 써서 백엔드 응답을 기다리지 않고 화면을 먼저 업데이트한다.
실패하면 되돌린다.
워크트리랑 브랜치 분리
그리고 워크트리랑 브랜치를 분리했다.
이전에는 섞여 있었다.
이걸 독립 섹션으로 나눴다.
각자 활성 상태가 보인다.
브랜치 전환은 사이드바 하단의 전용 컴포넌트로 옮겼다.
이건 깃 워크트리 관리와 연결된다.
이전에 Zed 에디터 확장에서 워크트리 관리를 만든 적이 있었다.
같은 개념을 터미널 앱에 가져온 거다.
터미널 탭 버그 7개
워크트리 분리를 하면서 터미널 탭 버그도 7개 잡았다.
탭 전환하면 터미널 렌더링이 깨지는 문제, 탭 닫으면 빈 캔버스가 남는 문제, 비동기 닫기 경쟁 조건 등. 가장 중요한 건 워크트리별 탭 격리다.
각 워크트리의 탭을 독립적으로 관리한다.
워크트리를 전환하면 그 워크트리의 탭만 보인다.
섞이지 않는다.
이 버그들은 터미널 엔진을 최근에 바꿔서 생긴 거다.
이전 엔진에서 새 엔진으로 옮기면서 생명주기 관리가 어긋났다.
새 엔진에 맞춰서 정리하니까 해결됐다.
프롬프트 인젝션 플러그인
두 번째는 코딩 에이전트 도구에 프롬프트 인젝션 플러그인을 만든 거다.
배경은 Caveman이라는 압축 통신 모드다.
토큰 사용량을 약 75% 줄이는 모드인데, 이걸 체계적으로 만들고 싶었다.
세션 상태에 따라 적절한 프롬프트를 자동으로 주입하는 거다.
3상태 프롬프트
세션 상태에 따라 세 가지 프롬프트를 다르게 주입한다.
첫 번째 메시지일 때는 전체 규칙을 주입한다.
일반 턴에서는 핵심 요약이랑 “확실하지 않으면 확인하라”는 규칙을 주입한다.
압축 후에는 규칙을 다시 세운다.
압축하면 컨텍스트가 손실될 수 있으니까 규칙을 다시 주입하는 거다.
왜 플러그인이 필요한가
이건 원래 다른 도구의 기능이었다.
근데 내가 쓰는 도구는 이 타이밍 분리를 지원하지 않았다.
모든 호출에 같은 컨텍스트를 똑같이 주입한다.
첫 메시지든 일반 턴이든 압축 후든 구분 없이. 그러니까
타이밍을 인식하는 주입이 안 된다.
그래서 플러그인으로 이 기능을 다시 만든 거다.
세션 상태를 판단해서 그 상태에 맞는 프롬프트를 주입한다.
이 플러그인은 이후에 계속 다듬어졌다. 처음에는 메시지 훅으로 구현했는데 나중에 프롬프트 추가 훅으로 바꿨다.
한 번만 주입되고 중복이 안 되고 저장된 메시지를 변경하지 않는 훅이 더 적합했기 때문이다.
마무리
두 작업 모두 “더 나은 인터페이스”에 대한 것이었다.
사이드바는 클릭을 여러 번 해야 하는 드롭다운에서, 한눈에 보이는 플랫 카드로 바꿨다.
인터페이스가 평평해지니까 스캔이 빨라진다.
프롬프트 인젝션은 세션 상태를 인식하게 만들었다.
모든 호출에 같은 걸 주입하는 게 아니라, 상태에 맞는 걸 주입한다.
첫 메시지, 일반 턴, 압축 후에 각각 다른 프롬프트가 필요하다.
인터페이스가 좋으면 일이 빨라진다.
드롭다운을 클릭하는 시간, 잘못된 프롬프트를 처리하는 토큰, 이런 낭비가 줄어든다.
인터페이스를 개선하는 건 결국 비용을 줄이는 일이다.