Libghostty가 온다
원문은 Mitchell Hashimoto님이 에 게재했습니다. 이 블로그 구독하기
2년여 전, Ghostty에 대한 첫 공개 발표 중 하나에서 저는 libghostty에 대한 비전을 공유했습니다. 어떤 애플리케이션이든 완전한 기능을 갖춘 현대적이고 빠른 터미널 에뮬레이터를 임베드할 수 있게 해주는 라이브러리라는 구상이었죠. libghostty가 드디어 형태를 갖추기 시작했고, 앞으로의 계획에 대해 더 자세히 공유하게 되어 기쁩니다.
첫 번째 libghostty 라이브러리는 libghostty-vt가 될 것입니다. 터미널 시퀀스를 파싱하고 터미널 상태를 유지하는 API를 제공하는, 의존성이 전혀 없는 라이브러리로, 실제 환경에서 검증된 Ghostty의 코어에서 직접 추출한 것입니다. 심지어 libc조차 필요하지 않습니다!
알림: 이 글은 주로 libghostty의 로드맵 업데이트이며, 첫 번째로 출시될 구성 요소를 알리기 위한 글입니다. Zig API는 현재 테스트용으로 사용할 수 있지만, C API는 아직 준비되지 않았으며 곧 제공될 예정입니다. 두 경우 모두 초기 테스트 단계의 품질로, 일반적인 사용에는 아직 적합하지 않습니다.
왜 libghostty인가?
먼저 왜 libghostty가 반드시 필요하다고 생각하는지에 대한 배경부터 이야기해 보겠습니다.
어떤 형태로든 터미널 에뮬레이션을 구현한 프로그램은 수백 개에 이릅니다. 가장 obvious한 예는 Ghostty, Kitty, iTerm2 같은 범용 터미널 에뮬레이터들입니다. 하지만 tmux나 zellij 같은 터미널 멀티플렉서 역시 완전한 터미널 에뮬레이터입니다!1 에디터들도 자체 터미널 에뮬레이터를 내장하고 있습니다. JetBrains 제품을 위한 jediterm, VS Code를 위한 Xterm.js, Zed에 들어간 Alacritty 등이 그 예입니다.
완전한 기능을 갖춘 터미널 에뮬레이터 외에도, 많은 웹사이트와 애플리케이션이 로그나 명령어 출력을 표시하기 위해 읽기 전용 터미널 에뮬레이션을 구현합니다. 예를 들어 GitHub Actions 출력은 단순한 색상 시퀀스를 파싱합니다(그 외에는 거의 하지 않죠). 그리고 Vercel이나 Render 같은 호스팅 제공업체도 빌드 로그 안에서 줄을 지우고 다시 그리거나 색상을 파싱할 수 있는 단순한 형태의 터미널 에뮬레이션을 구현합니다.
이러한 구현 중 상당수는 임시방편의 일회성 해결책입니다. 공유 라이브러리나 코드베이스를 사용하는 경우가 거의 없습니다.2 터미널 에뮬레이션은 겉보기에는 단순해 보이지만 예상치 못한 복잡성과 엣지 케이스로 가득한 고전적인 문제입니다.3 그 결과 대부분의 구현은 불완전하고, 버그가 많으며, 느립니다.4
정확성을 떠나, 어떤 형태든 터미널 에뮬레이션을 구현하는 것 자체가 대부분의 개발자에게는 시간 낭비입니다. 터미널 에뮬레이션은 JetBrains, Visual Studio Code, GitHub, Vercel, Render 등의 핵심 비즈니스가 아닙니다. 어디서나 일관되게 동작하는 안정적이고 재사용 가능한 솔루션이 있다면 그들에게도 분명 도움이 될 것입니다.
이에 대한 제 해답이 바로 libghostty입니다. 기능이 풍부하고 정확하며 빠른 터미널 기능을 어떤 애플리케이션이든 어디서나 임베드할 수 있도록 C API를 제공하는 크로스 플랫폼, 최소 의존성 라이브러리 말입니다.
시작: libghostty-vt
첫 번째 libghostty 라이브러리는 libghostty-vt가 될 것입니다. 터미널 시퀀스를 파싱하고 커서 위치, 현재 스타일, 텍스트 래핑 등 터미널 상태를 유지하는 API를 제공하는, 의존성이 전혀 없는(libc조차 없는) 라이브러리입니다.
터미널 시퀀스 파싱은 터미널 에뮬레이터의 가장 핵심적인 기능으로, Ghostty 같은 완전한 터미널 에뮬레이터부터 GitHub Actions나 Vercel 빌드 출력 같은 단순한 읽기 전용 스타일 전용 뷰에 이르기까지 모두 필요합니다.
상태 다이어그램은 언뜻 보면 비교적 단순해 보일 수 있지만, 이를 정확하게 구현하는 것은 예상보다 훨씬 어렵습니다. 예를 들어 Jediterm은 intermediate를 올바르게 처리하지 못해 이 글을 쓰는 시점 기준으로 모든 JetBrains 에디터에서 널리 지원되는 “커서 모양 변경” 시퀀스가 문자 하나를 삼켜버리는 현상이 발생합니다.
스타일 전용 파싱의 경우, 많은 개발자들이 전체 상태 다이어그램을 건너뜁니다. 대신 가볍게 웹 검색을 해서 \e[31이나 \e[41m 같은 단순한 ANSI 시퀀스만 파싱하고 “색상 지원”이라고 주장합니다. 하지만 스타일 전용 시퀀스는 그보다 훨씬 복잡합니다. 예를 들어 RGB를 지원하는데, RGB 자체도 열두 가지가 넘는 형식으로 표현될 수 있습니다. 그리고 저는 아직 이 복잡한 스타일 시퀀스를 올바르게 렌더링하는 웹 콘솔을 단 하나도 찾지 못했습니다.5
libghostty-vt는 이 모든 문제를 해결하는 것을 목표로 합니다.
libghostty-vt는 Ghostty에서 추출되었으며, SIMD 최적화 파싱, 뛰어난 유니코드 지원, 고도로 최적화된 메모리 사용, 퍼징 및 Valgrind 테스트를 거친 견고한 코드베이스, Kitty Graphics Protocol이나 Tmux Control Mode 파싱과 같은 우수한 기능 호환성 등 실제 환경에서 검증된 모든 이점을 그대로 계승합니다.
이 모든 것이 의존성이 전혀 없는 단일 C API(libc에도 의존하지 않습니다)로 패키징되어, 어떤 인기 언어 생태계에도 쉽게 임베드할 수 있습니다.
최소한의 풋프린트 덕분에 libghostty-vt는 폭넓은 이식성을 갖추게 될 것입니다. 초기 타깃은 애플리케이션으로서의 Ghostty의 주요 타깃인 macOS와 Linux의 x86_64 및 aarch64 아키텍처가 될 것입니다. 하지만 Windows, 임베디드 기기, WASM을 통한 웹 등 추가 타깃으로 지원을 확장할 계획입니다. libghostty는 범위가 더 좁은 만큼 GUI로서의 Ghostty보다 더 넓은 플랫폼을 지원하게 될 것입니다.
장기적인 계획
libghostty-vt는 시작에 불과합니다. 장기적으로는 입력 처리(키보드 인코딩이 대표적입니다), GPU 렌더링(OpenGL이나 Metal 서피스를 제공하면 나머지는 저희가 처리합니다), 전체 터미널 뷰를 처리하는 GTK 위젯과 Swift 프레임워크 등 추가 기능을 제공하는 더 많은 libghostty-<x> 라이브러리를 제공할 예정입니다.
핵심 구성 요소들이 안정화되면 더 많은 기능을 계속해서 제공할 것입니다. 이들은 의존성 요구사항, 코드 크기, 전반적인 유지보수 복잡성을 최소화하기 위해 라이브러리 패밀리 형태로 구성될 예정입니다.
libghostty-vt 현황
방금 libghostty-vt를 Zig 모듈로 노출하는 풀 리퀘스트를 머지했습니다. 이 PR에는 최소한의 예제 프로그램도 포함되어 있습니다. Zig 개발자라면 지금 바로 libghostty-vt를 실험해 볼 수 있습니다.
C API는 아직 준비되지 않았지만, 현재 제가 작업 중인 부분이며 곧 테스트용으로 제공될 예정입니다. 핵심 로직은 이미 모두 존재하고 수년간 Ghostty에서 사용되어 온 만큼, 필요한 작업은 C API를 정의하는 것뿐입니다. 게다가 Ghostty macOS 앱은 이미 내부 전용 C API를 사용하고 있습니다.
내부 전용 C 헤더를 보게 되더라도, 그 엉망인 상태는 무시해 주시기 바랍니다. 좋은 C API가 아닙니다. 내부 전용이며 macOS 애플리케이션의 요구사항을 충족하기 위해 존재할 뿐입니다. 일반적으로 쓸 수 있는 libghostty는 아니지만, 이미 실제 상용 제품에서 Ghostty를 임베드하기 위해 사용되고 있긴 합니다. 더 넓은 활용을 위한 C API는 백지 상태에서 새롭게 정의할 예정입니다.
libghostty는 애플리케이션인 Ghostty와 별도로 버전을 관리할 계획입니다. 이 블로그 게시물은 공개 알파(API 안정성을 보장하지 않음)를 알리는 것이며, 이를 계기로 여러 개발자가 직접 사용해 보고, C API가 준비되면 언어 바인딩을 작성해 주기를 기대하고 있습니다.
앞으로 6개월 안에 libghostty-vt의 태그된 버전을 출시하고 싶지만, 준비 여부에 따라 달라질 것입니다.
피드백을 기다립니다
지금은 libghostty의 API를 설계하는 중요한 단계에 있으며, API를 설계하는 가장 좋은 방법은 실제 사용자로부터 피드백을 받는 것입니다. Ghostty가 하나의 사례이고, 커뮤니티 멤버 중에는 다른 libghostty 기반 프로젝트를 작업 중인 분들도 있지만, 가능한 한 많은 분들의 참여가 필요합니다!
프로젝트나 조직에서 libghostty를 활용할 만한 사례가 있다면, Ghostty Discord에 참여해 이 작업을 진행 중인 개발자들과 협업해 주시기 바랍니다. Discord에 참여하고 싶지 않다면 이메일로 연락해 주세요(이 웹사이트 하단에 이메일이 있습니다).
현 단계의 libghostty 상태는 알파라고 볼 수 있으므로, 매끄럽고 안정적인 경험을 기대하지는 마시기 바랍니다. 일찍부터 함께할 해커들을 찾고 있습니다.
“알파”라는 품질은 API(함수와 타입) 자체에 대한 것입니다. 핵심 로직은 Ghostty와 공유되며 실제 환경에서 극도로 안정적이고 검증되어 있습니다.
다음 프론티어
애플리케이션으로서의 Ghostty가 마침내 libghostty라는 목표를 향해 나아갈 수 있을 만큼 안정화된 것이 무척 기쁩니다. libghostty는 Ghostty의 다음 프론티어이며, 단독 애플리케이션으로서의 Ghostty보다 훨씬 더 큰 임팩트를 만들 수 있다고 생각합니다.
걱정하지 마세요, 애플리케이션으로서의 Ghostty에도 많은 변화가 예정되어 있으며, 이 중 어느 것도 Ghostty에 대한 제 열정이나 계획을 약화시키지 않습니다. Ghostty 자체도 libghostty의 사용자이기 때문에, libghostty가 더 널리 사용될수록 Ghostty 애플리케이션도 더욱 기능이 풍부하고 안정적이 될 것입니다.
Boo. 👻
각주
이들은 자식 프로세스에 대한 pty를 소유하고, 모든 이스케이프 코드를 파싱하며, 화면 상태를 관리하고, 궁극적으로는 부모 터미널 에뮬레이터에 자체 이스케이프 코드를 보내 “렌더링”합니다. ↩
많은 웹사이트가 Xterm.js를 사용하고, GTK 생태계에는 libvte가 있습니다. 하지만 이는 전체 중 극히 일부에 불과하며, 앞서 언급한 각 사례들도 각자의 범위에서 제한적입니다. ↩
3년 가까이 터미널 에뮬레이션 작업을 해왔지만, 아직도 이상한 엣지 케이스들을 발견하고 있습니다. 여전히 이상한 엣지 케이스를 찾고 있습니다. ↩
실제로 영향을 준 문제의 몇 가지 사례입니다: Jediterm은 intermediate를 제대로 처리하지 못했고, Apple의 Terminal.app은 DCS 시퀀스를 그대로 출력에 흘려보냅니다. 특정 대상을 지목하려는 것이 아니라, 이러한 문제들이 존재하며 터미널 에뮬레이션을 올바르게 구현하는 것이 매우 어렵다는 것을 보여드리기 위함입니다. ↩
많은 범용 터미널 에뮬레이터들도 이를 잘못 구현했으며, Ghostty 역시 불과 9개월 전까지 그랬습니다. ↩
글을 무작위로 읽기
댓글
로그인하고 댓글 남기기