Ghostty 개발 로그 003
원문은 Mitchell Hashimoto님이 에 게재했습니다. 이 블로그 구독하기
안녕하세요! Ghostty 👻의 세 번째 공식 개발 로그에 오신 것을 환영합니다!
이전 개발 로그를 놓치셨거나 Ghostty가 무엇인지 더 자세히 알고 싶으시다면, 이 웹사이트의 Ghostty 페이지를 참고해 주세요.
커뮤니티 소식: 공개 Discord!
이제 공개 Discord 서버를 운영하게 되었다는 소식을 전하게 되어 기쁩니다! 누구나 참여해서 Ghostty에 대해 질문하고, 터미널 에뮬레이터나 시스템 프로그래밍, GPU 프로그래밍 등에 대해 이야기할 수 있습니다. Discord를 통해 베타 프로그램도 확대하고 있으니, 베타 참여에 관심이 있으시다면 Discord 서버에 참여해 어느 정도 활동해 주세요.
다음으로, 9월 5일에 Zig Showtime에서 Ghostty에 대한 발표를 할 예정입니다. 정확한 시간과 링크는 Zig Showtime 웹사이트, 트위터, Mastodon 등을 통해 확인해 주세요. 아직 발표를 준비 중이지만, 전반적으로 Ghostty 구현을 빠르게 훑어보면서 흥미로운 지점들을 짚어보는 내용이 될 예정입니다. 어쨌든 Zig Showtime인 만큼 Ghostty의 Zig 관련 측면에 좀 더 초점을 맞출 계획입니다.
키보드 입력 처리는 당신을 싫어합니다 (#282)1
저는 그냥 멍청한 미국식 키보드 레이아웃으로 타이핑하는 멍청한 미국 시민일 뿐입니다. 미국 표준 키보드에서는 a를 치면 “a”가 나오고, '(어퍼스트로피)를 치면 “'”가 나옵니다. shift+a를 치면 “A”가 나오죠. 정말 쉽습니다. 당신은 거짓의 왕좌 위에 앉아 있습니다.
문제의 첫 번째 조짐은 Dvorak이나 Colemak 같은 비표준이지만 영어 중심인 키보드 레이아웃입니다. 미국 표준 물리 키보드에서 Dvorak 사용자는 s를 치면 “o”가 나오길 기대하고, ctrl+i를 누르면 ctrl+c와 같은 동작을 기대합니다.
두 번째 조짐은 유니코드 시퀀스입니다. Mac에서 미국 표준 레이아웃으로 alt+a를 누르면 å가 생성됩니다. 최근 베타 그룹에 합류한 노르웨이 사용자 한 분이 이 부분이 특히 중요하다고 알려주셨는데, 미국 표준 레이아웃을 선호하면서도 alt 시퀀스를 이용해 노르웨이어 단어를 입력하기 때문입니다.
세 번째 조짐은 비표준 키보드 레이아웃입니다. 데드 키(dead key) 시퀀스가 무엇인지 아시나요? 저는 몰랐습니다(기억하시겠지만 저는 그냥 멍청한 미국 표준 사용자니까요). 미국 표준 레이아웃에서는 모든 키 입력이 상태를 갖지 않는 것에 익숙합니다. 문자를 대문자로 만들려면 shift+A를 동시에 누르죠. 데드 키 시퀀스라면 shift를 눌렀다 떼고, 그다음 a를 치면 A가 보이는 식입니다(이건 실제 데드 키 시퀀스는 아니고, 데드 키 시퀀스가 어떻게 동작하는지를 보여주는 예시입니다). 미국 국제 레이아웃에서의 실제 데드 키 시퀀스는 이렇습니다: '를 치고 손을 뗀 뒤 a를 치면 á가 됩니다.
사람이 키보드에서 키를 누르면 몇 가지 일이 일어납니다. 키보드는 물리적 스캔코드를 보냅니다. 소프트웨어 키보드 레이아웃 처리(즉, QWERTY 키보드에서 Dvorak 레이아웃을 사용하는 경우)는 이 스캔코드를 다른 스캔코드로 변환합니다(“i”가 Dvorak에서는 “c”처럼 동작합니다). 수정 키(ctrl, alt 등)와 다른 키(즉, 문자)의 조합은 경우에 따라 하나 이상의 문자를 생성할 수도, 하지 않을 수도 있습니다(즉, macOS에서 alt+p는 “π”를 생성하지만, 미국 물리 키보드에서 Dvorak을 쓸 때는 그와 동일한 입력이 alt+r입니다).
마지막으로, 모든 수정 키가 소모되는 것은 아니며, 이는 키 바인딩과 관련이 있습니다. 예를 들어 미국 레이아웃에서 ctrl+=로 바인딩하면, 노르웨이 레이아웃에서는 ctrl+shift+0가 됩니다. shift+0이 =를 만들었지만 ctrl은 소모하지 않았으므로 최종 입력은 ctrl+=이라는 것을 알아야 합니다. 그런데 사용자가 ctrl+shift+0도 함께 바인딩했다면, 둘 중 어느 것을 써야 할까요? 🤔
이 설명들은 모두 매우 두루뭉술하고 세부 내용이 부족합니다. 키보드 레이아웃, 입력 처리, 터미널 키보드 “프로토콜”, 그리고 OS 수준 API라는 불가해한 공포에 대해专门으로 다루는 블로그 글을 따로 쓸 계획이라 이번 개발 로그에서는 세부 사항을 생략하려 합니다. 기대해 주세요!
Ghostty는 이런 사용 사례들을 처리해야 할 뿐만 아니라(알고 보니 미국 표준이 아닌 키보드 사용자가 존재하더군요), 이미 macOS와 Linux에서 동작하고 향후 Windows에서도 동작하려는 목표가 있기 때문에 이를 크로스 플랫폼으로 처리해야 합니다. 😰 이제 Ghostty는 그렇게 합니다.
시각적으로 보여드릴 수 있는 것은 데드 키 상태 처리뿐인데, 이제 마지막으로 대기 중인 데드 키와 함께 렌더링됩니다. 나머지는 이제 잘 동작한다는 제 말을 믿어 주셔야 합니다.
위 내용에 더해, Ghostty는 이제 선택적인 명시적 물리 키 매핑을 지원합니다. 키 바인딩을 ctrl+physical:0(physical: 접두사에 주목하세요)로 지정하면, 물리적인 0 키를 눌렀을 때만 해당 바인딩이 동작합니다. 일부 키보드 레이아웃에서는 이로 인해 해당 키 바인딩을 사용할 수 없게 될 수도 있습니다. 기본적으로 키 바인딩은 논리적(변환된) 키를 기준으로 합니다.
Kitty 키보드 프로토콜 외 (#292, #295)
키보드 입력에 대해 배우는 것이 지겹다면, 이 섹션은 그냥 건너뛰세요.
키보드 키를 문자 입력에 매핑하는 것을 넘어, 키보드 이벤트는 터미널에서 실행 중인 프로그램이 어떤 키를 눌렀는지 알 수 있도록 이스케이프 시퀀스에도 매핑되어야 합니다.
초기 터미널 프로토콜은 키보드 키가 생성한 문자를 그대로 보냈습니다. “a”를 치면 “a”를 받고, “A”(shift+A)를 치면 “A”를 받는 식이죠. 여기에는 많은 한계가 있습니다. 예를 들어 터미널 프로그램은 ctrl-i와 ctrl-shift-i 같은 수정 키에 반응할 수 없었는데, 두 조합이 동일한 데이터를 생성했기 때문입니다.
이러한 단점을 해결하기 위해 여러 추가 키보드 프로토콜이 개발되었습니다. xterm은 modified keys 시퀀스를 개발했고, Paul Evans는 fixterms 프로토콜을, Kovid Goyal(Kitty 개발자)은 Kitty Keyboard Protocol을 개발했습니다. 이 프로토콜들의 요지는 키를 눌렀을 때 터미널이 실행 중인 프로그램에 무엇을 보내는지를 정의한다는 것입니다.
이건 가상의 문제가 아닙니다. 이 프로토콜들은 tmux, neovim 같은 주요 프로그램들에 구현되어 있어, 그렇지 않았다면 불가능했을 수백 개의 추가 키 바인딩을 가능하게 합니다.
Ghostty는 이제 이 모든 것을 구현합니다.
제가 아는 한, Ghostty는 이 모든 것을 구현한 몇 안 되는 터미널 중 하나입니다. xterm modified keys 와 Kitty를 모두 구현한 터미널은 iTerm, Foot, 그리고 아마도 WezTerm뿐인 것으로 알고 있습니다. 거기에 Kitty까지 더해야 Kitty 프로토콜 자체를 구현한 터미널이 됩니다. 대부분의 터미널(Terminal.app, Windows Terminal, Alacritty, Warp)은 키보드 프로토콜을 전혀 구현하지 않습니다.2
Kitty 키보드 프로토콜이 동작하는 영상은 다음과 같습니다:
그리고 xterm modified keys 프로토콜이 동작하는 영상은 다음과 같습니다:
데스크톱 Linux의 해 (GTK)
최근 베타 사용자 그룹 덕분에 상시 Linux 사용자 수가 기존의 두어 명에서 5~6명 정도로 늘었고, 그와 함께 Linux 경험에서도 많은 개선이 이루어졌습니다.
첫째, GTK 단일 인스턴스 모드(#247)가 이제 활성화되어 지원됩니다. GTK에서 Ghostty는 이제 단일 프로세스로 실행됩니다. Ghostty를 두 번째로 실행하면 기존 Ghostty 프로세스에 새 창이 열립니다. 이는 표준 그래픽 데스크톱 환경과 잘 어우러질 뿐만 아니라, 첫 실행 이후 Ghostty 실행을 매우 빠르게 만듭니다.
다음으로, Ghostty는 이제 primary (selection) 클립보드 지원(#266)을 갖추었습니다. Linux 데스크톱에는 여러 개의 클립보드가 있습니다. “primary”(또는 “selection”) 클립보드는 텍스트를 선택하면 자동으로 복사되는 곳이며, 붙여넣기는 보통 가운데 마우스 버튼으로 수행됩니다. 이는 ctrl+shift+c와 ctrl+shift+v가 사용하는 클립보드와는 별개의 클립보드이므로, 클립보드에 여러 항목을 동시에 보관할 수 있습니다. 이 기능은 때로 논란이 되기도 하니 걱정하지 마세요. copy-on-select 설정으로 비활성화할 수 있습니다. 아래 영상에서 동작하는 모습을 보실 수 있습니다. 키보드 바인딩을 전혀 누르지 않고 있다는 점에 주목해 주세요. 이는 selection 클립보드만 사용한 것입니다.
이제 Linux에서도 자동 셸 통합(#245)을 지원합니다. Devlog 001에서 셸 통합에 대해 이야기한 바 있습니다. 이전에는 Linux 사용자가 Ghostty의 share 디렉터리를 가리키도록 환경 변수를 설정해야 했습니다. 이제 Linux 애플리케이션은 ghostty 실행 파일부터 상위 디렉터리를 탐색하며 올바른 폴더 구조를 갖춘 share 디렉터리를 찾습니다. 표준 FHS 디렉터리 레이아웃(Ghostty가 패키징하는 표준 레이아웃)으로 Ghostty를 설치하면, Ghostty가 자동으로 셸을 찾아 설정합니다.
그 외에도 Ghostty 앱 아이콘이 제대로 표시되고(#251), GTK 애플리케이션이 미국 외 키보드 레이아웃을 처리하며(#271), GTK 애플리케이션이 반투명 창 배경을 지원(#264)하는 등 많은 개선이 있었습니다.
저는 Ghostty가 최고 수준의 GTK 기반 Linux 터미널이 되기를 진심으로 바랍니다. 저는 GTK를 상시로 사용하지 않기 때문에, 이 경험을 훌륭하게 만들기 위해 테스터들의 피드백에 크게 의존하고 있습니다. Ghostty가 이제 GTK에서 정말 좋은 느낌을 주고 있다는 소식을 전하게 되어 매우 기쁩니다! GTK 애플리케이션이 아직 macOS 경험에는 뒤처져 있지만, 두 환경을 동등한 수준으로 끌어올릴 수 있기를 기대하고 있습니다!
마무리
가장 최근 베타 테스터 분들은 정말 대단했습니다. 심각한 키보드 레이아웃 및 매핑 문제들을 모두 드러내고 이를 모두 고치도록 밀어붙여 준 @hovsater님께 감사드리고 싶습니다. @cryptocode님은 넓은 문자, 다중 코드포인트 그래핌(grapheme) 및 이들과 선택 영역·소프트 래핑 간의 상호작용과 관련된 엣지 케이스에서 십여 개 정도의 버그를 찾아내 주셨습니다. 그리고 Linux 개선에 기여해 주신, 감사드릴 만한 새로운 테스터 분들도 많이 계십니다. 감사합니다!
최신 소식을 계속 받아보고 싶으시다면 트위터나 Mastodon에서 저를 팔로우해 주세요(링크는 하단에 있습니다). 이 블로그에는 RSS 피드도 있습니다.
Boo. 👻
각주
이는 제가 적극 추천하는 훌륭한 블로그 글 Text Rendering Hates You에 대한 언급입니다. ↩
저는 이 모든 터미널 에뮬레이터 작성자 분들을 깊이 존경하며, 이 내용이 공격으로 보이지 않기를 바랍니다. 저는 단지 그들이 어떤 기능을 지원하고 지원하지 않는지를 사실대로 설명하려는 것뿐입니다. 제가 틀렸다면 알려주시면 바로 수정하겠습니다. ↩
글을 무작위로 읽기
댓글
로그인하고 댓글 남기기