Transcript
00:00:00이것은 Vasell이 만든 웹 기반 터미널 에뮬레이터인 Wterm입니다.
00:00:03캔버스가 아닌 DOM에 직접 렌더링되죠.
00:00:06그래서 텍스트 선택, 브라우저 찾기,
00:00:08그리고 스크린 리더까지 모두 문제없이 작동합니다.
00:00:10Zig로 작성되어 12KB WASM 바이너리로 컴파일되며,
00:00:14LibGhosty로 구동되는 옵션 백엔드도 있어서,
00:00:17고스트 터미널(Ghosty terminal)을 구동하는 동일한 엔진으로
00:00:19브라우저에서 완벽한 터미널 호환성을 제공합니다.
00:00:22하지만 12KB짜리 WASM 바이너리가
00:00:24정말로 네이티브 터미널 에뮬레이터를 대체할 수 있을까요?
00:00:28아마 아닐 겁니다. 하지만 구독하고 같이 확인해 보죠.
00:00:33웹 터미널은 이제 거의 어디에나 있습니다.
00:00:36GitHub Codespaces 같은 클라우드 IDE,
00:00:39Portainer나 Qualify 같은 인프라 도구,
00:00:41심지어 VS Code나 Cursor 같은 데스크톱 IDE에도요.
00:00:44하지만 모두 Xterm.js를 사용하는데,
00:00:47오래전부터 존재해 왔고
00:00:49사실상 기본값이기 때문이죠.
00:00:51하지만 Xterm에는 큰 문제가 있습니다.
00:00:52캔버스 요소에 렌더링한다는 점입니다.
00:00:54그래서 텍스트를 선택하거나
00:00:56페이지 내에서 단어를 찾는 것 같은 작업들이
00:00:58모두 처음부터 다시 구현되어야 하고,
00:01:00항상 매끄럽게 작동하는 건 아니죠.
00:01:02Wterm은 완전히 다른 접근 방식을 취합니다.
00:01:04DOM에 직접 렌더링하는 방식이죠.
00:01:05즉, 터미널 출력이 그냥 HTML이 되므로
00:01:08브라우저가 알아서 처리해 줍니다.
00:01:10Wterm은 이런 HTML 렌더링을 활용해
00:01:13정말 멋진 기능들을 수행할 수 있습니다.
00:01:14매 프레임마다 전체 터미널을 다시 그리는 대신
00:01:17업데이트된 행만 다시 렌더링할 수 있거든요.
00:01:20또한 React나 Vue 같은
00:01:22다양한 프레임워크에서 사용 가능합니다.
00:01:23테마 변경도 가능하고요.
00:01:24별도의 Wterm Ghosty 패키지도 있어서,
00:01:27Zig 코어를 Lib Ghosty로 교체할 수 있는데,
00:01:29다른 웹 Ghosty 프로젝트보다
00:01:31놀랍도록 더 잘 작동합니다.
00:01:33그건 영상 뒷부분에서 더 자세히 다루겠습니다.
00:01:35일단은 간단한 데모 프로젝트로
00:01:37Wterm을 테스트해 보죠.
00:01:38React에 Wterm을 설치한 후,
00:01:40컴포넌트와 CSS를 가져왔고,
00:01:43여기 컴포넌트를 렌더링하고 있습니다.
00:01:45이제 앱을 실행하고 브라우저로 가보면,
00:01:48터미널이 보이는 걸 확인할 수 있습니다.
00:01:49하지만 ls 같은 명령어를 입력해도,
00:01:51아무 일도 일어나지 않죠.
00:01:52이유는 정보를 읽어올
00:01:53다른 컴퓨터와 연결되어 있지 않기 때문입니다.
00:01:56설명해 드릴게요.
00:01:57지금 클라이언트가 백엔드에 연결되지 않아서,
00:01:59정보를 가져올 곳이 없는 상태입니다.
00:02:01그래서 다른 머신에 연결해야 합니다.
00:02:04제 로컬 머신이 될 수도 있고,
00:02:06클라우드상의 머신일 수도 있죠.
00:02:07그 머신 내에서 동일한 크기의
00:02:10가상 터미널이나 의사 터미널(pseudo terminal)을
00:02:13렌더링해야 합니다.
00:02:14키 입력을 하면,
00:02:16그 키 정보가 다른 머신으로 전송되고,
00:02:18거기서 실행된 결과를 렌더링한 다음,
00:02:20그 모든 정보를 클라이언트로 다시 보냅니다.
00:02:22이런 왕복 과정이
00:02:23최소한의 지연 시간으로 아주 빠르게 일어나야 하죠.
00:02:25그래서 클라이언트와 다른 머신을
00:02:26가장 잘 연결하는 방법은 웹소켓을 쓰는 겁니다.
00:02:28한번 해보죠.
00:02:30Node가 설치된 Ubuntu 서버를
00:02:31이미 준비해 두었습니다.
00:02:32서버 스크립트가 있는 Wterm 서버도 있고요.
00:02:34이걸 살펴보면,
00:02:35슬래시 API 슬래시 터미널 경로에
00:02:37웹소켓 서버를 만드는 걸 볼 수 있습니다.
00:02:38나중에 좀 더 자세히 설명하겠지만,
00:02:40여기 아래에서
00:02:42터미널 타입과 일치하는 이름으로
00:02:43의사 터미널을 생성하고 있습니다.
00:02:45궁금하시다면 여기서 자신의 것을 찾을 수 있습니다.
00:02:48그리고 여기 아래에서는,
00:02:49클라이언트로부터 키 입력을 받아
00:02:49서버에서 처리하고,
00:02:51가상 터미널 안에서 실행한 뒤
00:02:53다시 클라이언트로 반환하고 있습니다.
00:02:55서버는 업데이트된 특정 행만이 아니라
00:02:56모든 걸 반환하죠.
00:02:58이제 app.tsx 파일의 클라이언트 쪽을 보면,
00:02:59슬래시 API 슬래시 터미널 경로로
00:03:01웹소켓 연결을 하고 있습니다.
00:03:02그리고 Wterm의 웹소켓 트랜스폼을 사용해서
00:03:03자동 재연결 옵션과 함께
00:03:05그 URL로 연결하죠.
00:03:07이게 여기서 서버로 키 정보를 전송합니다.
00:03:10브라우저 크기 조절도 여기서 처리하고요.
00:03:11그다음 여기, handle data 함수가
00:03:14서버로부터 들어오는 모든 정보를 처리합니다.
00:03:16ZIG 코어의 멋진 점은
00:03:19이 정보를 분석해서 바뀐 부분이 무엇인지 파악하고,
00:03:21그 부분만 HTML로 다시 렌더링한다는 점입니다.
00:03:23여기 열과 행의 크기도
00:03:24서버에서 설정한 것과 맞춰야 합니다.
00:03:26나머지는 직관적이라 이해하기 쉬울 겁니다.
00:03:27자, 이제 클라이언트와 서버가 실행 중이니,
00:03:28브라우저로 돌아와서 ls를 입력해 보면,
00:03:30사용 가능한 파일 목록이 보입니다.
00:03:31ls에 L 옵션을 붙여서
00:03:33파일 정보를 자세히 볼 수도 있고,
00:03:35디렉토리를 이동해서
00:03:36파일 내용을 확인하거나
00:03:39실행 중인 컨테이너 목록을 볼 수도 있죠.
00:03:41Vim으로 파일을 열어서
00:03:42내용을 탐색할 수도 있습니다.
00:03:45물론 작동은 하지만,
00:03:47완벽하게 매끄럽지는 않습니다.
00:03:49예를 들어 텍스트를 드래그해 보면,
00:03:52일부 문자를 전혀 알아볼 수 없습니다.
00:03:53이걸 고치려면
00:03:55Ghosty 코어를 로드하고
00:03:57React prop에 추가해서
00:03:59Wterm을 Ghosty와 설정할 수 있습니다.
00:04:01이제 서버 파일을 열고
00:04:02텍스트를 선택해 보면,
00:04:03훨씬 더 읽기 좋아졌죠.
00:04:04열린 코드를 올바르게 렌더링하고,
00:04:06모델을 전환하며,
00:04:07이모지 지원과 함께 프롬프트를 입력할 수도 있습니다.
00:04:09기본 Wterm 코어 렌더러보다
00:04:10색상 표현도 살짝 더 나은 걸 볼 수 있습니다.
00:04:12하지만 Zig 코어는 12KB인 반면,
00:04:13Ghosty는 400KB입니다.
00:04:15파일 크기가 중요하다면,
00:04:16Zig 코어를 유지하는 게 나을 수도 있습니다.
00:04:18어쨌든 Vercel의 Wterm에 대한 간단한 개요였습니다.
00:04:20물론 다루지 않은 기능이 정말 많습니다.
00:04:22마크다운을 멋진 터미널 출력으로 바꾸거나,
00:04:23백엔드 접근 권한이 없을 때
00:04:24Bash만으로 가상 파일들을 탐색하는 것,
00:04:26심지어 브라우저 터미널을 통해
00:04:27SSH 클라이언트를 설정하는 예제도 있죠.
00:04:29하지만 Wterm이 완벽하다고 생각하진 않습니다.
00:04:31Ghosty 버전을 사용할 때
00:04:31NeoVim이나 OpenCode를 오갈 때 렌더링 문제가 있었고,
00:04:34BUN 프론트엔드에서 Ghosty 렌더러를 작동시키려면
00:04:36Ghosty의 400KB와 비교하면 말이죠.
00:04:39JS가 아닌 파일은 복사하지 않아서
00:04:40직접 가져와야 했거든요.
00:04:43하지만 DOM 렌더링 방식 자체는 마음에 듭니다.
00:04:46따로 애쓰지 않아도 접근성과
00:04:48브라우저 네이티브 기능을
00:04:49그대로 활용할 수 있으니까요.
00:04:51Xterm은 10년이 넘게 지났는데도
00:04:52그걸 구현하느라 고생했거든요.
00:04:55하지만 Xterm.js는 방대한 생태계를 갖춘
00:04:57검증된 솔루션이므로,
00:04:58선택한다고 해서 잘못되는 건 아닙니다.
00:05:00Coda의 GhostyWeb도 있습니다.
00:05:02이건 다른 접근 방식을 취하죠.
00:05:05실제 Ghosty 터미널에 사용된 것과
00:05:06동일한 libGhosty 엔진을 사용하지만,
00:05:08NeoVim을 오가면서
00:05:10혹은 OpenCode를 쓸 때도요.
00:05:11동일한 API를 씁니다.
00:05:13하지만 더 나은 터미널을 사용할 수 있죠.
00:05:15WASM 파일을 가져와야 했습니다
00:05:17BUN은 Node 모듈 폴더에서
00:05:19JS가 아닌 파일은 복사하지 않으니까요.
00:05:21하지만 DOM 렌더링 방식은 마음에 듭니다.
00:05:23따로 작업을 하지 않아도
00:05:25웹 접근성과 네이티브 브라우저 기능을
00:05:27그대로 사용할 수 있으니까요.
00:05:29Xterm은 이 부분에서 고전해 왔죠.
00:05:3110년 넘게 사용되어 왔음에도 말입니다.
00:05:33하지만 Xterm.js는 방대한 생태계를 갖췄고
00:05:35이미 검증된 솔루션이기 때문에
00:05:38선택하셔도 후회는 없을 겁니다.
00:05:40Coda의 GhostyWeb도 있는데
00:05:42이건 접근 방식이 다릅니다.
00:05:43실제 Ghosty 터미널에서 사용하는
00:05:45동일한 libGhosty 엔진을 사용하죠.
00:05:48Xterm의 대체제로 바로 쓸 수 있고
00:05:50여전히 캔버스 렌더링 방식을 사용하며
00:05:52API도 동일합니다.
00:05:54하지만 더 나은 터미널을 경험할 수 있죠.
Community Posts
No posts yet. Be the first to write about this video!
Write about this video