# 느린 터미널에 쓰기엔 인생은 너무 짧다

> Clean Markdown view of GeekNews topic #30236. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30236](https://news.hada.io/topic?id=30236)
- GeekNews Markdown: [https://news.hada.io/topic/30236.md](https://news.hada.io/topic/30236.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-06-07T09:06:04+09:00
- Updated: 2026-06-07T09:06:04+09:00
- Original source: [mijndertstuij.nl](https://mijndertstuij.nl/posts/life-is-too-short-for-a-slow-terminal/)
- Points: 5
- Comments: 1

## Topic Body

- 하루 종일 사용하는 **터미널의 속도**는 작업 효율을 좌우하며, 새 탭 열기·타이핑·자동완성의 미세한 지연이 하루에 수백 번 누적되면 비효율적  
- 완전히 로드된 인터랙티브 셸이 자동완성·구문 강조·자동제안·fzf·direnv를 포함하고도 **약 30밀리초**만에 시작하고, 새 탭은 즉각적으로 열리도록 개선  
- 가장 큰 비결은 oh-my-zsh나 prezto 같은 **프레임워크와 플러그인 매니저를 쓰지 않는 것**으로, 플러그인 3개만 직접 git clone해 `.zshrc`에서 source함  
- `compinit` 캐싱, **지연 로딩(lazy-loading)**, 비동기 프롬프트, GPU 가속 터미널 등으로 시작·프롬프트·입력 지연을 모두 최소화함  
- 대부분의 최적화는 무언가를 추가하는 것이 아니라 **불필요한 것을 덜어내는 것**이며, 실제로 자주 쓰는 것만 의도적으로 추가하는 절제가 핵심임  
  
---  
  
### 빠른 터미널이 필요한 이유  
  
- 거의 모든 작업이 터미널 안에서 이루어지며, Git·kubectl·tmux·서버 ssh 접속 등을 하루 종일 사용함  
- 그만큼 자주 쓰는 도구는 빨라야 하며, 새 탭 열기·문자 입력·탭 자동완성에서의 지연을 하루에 수백 번 체감함  
- 이런 미세한 지연이 누적되는 상황은 **천 번의 칼질로 인한 죽음(death by a thousand cuts)** 과 같음  
  
### 셸 시작 속도 측정 결과  
  
- 업데이트 결과, 셸이 약 **30밀리초**만에 시작하며, 측정 명령으로 `for i in {1..5}; do /usr/bin/time zsh -i -c exit; done` 사용  
- 자동완성, 구문 강조, 자동제안, fzf, direnv가 모두 포함된 완전한 인터랙티브 셸이 **30fps 단일 프레임보다 짧은 시간**에 로드됨  
- 큰 최적화 프로젝트가 있었던 것이 아니라, 수년간 셸을 최소화하고 빠르게 유지한 **습관**의 결과임  
- 모든 설정은 [dotfiles 저장소](https://github.com/mijndert/dotfiles)에 공개되어 있음  
  
### 프레임워크 없음  
  
- 가장 큰 이점은 존재하지 않는 것에서 나오며, oh-my-zsh·prezto·플러그인 매니저를 쓰지 않음  
- oh-my-zsh의 수백 개 플러그인과 테마 중 약 5%만 사용하면서, 나머지 95%에 대한 **시간과 컴퓨팅 자원 비용**을 셸을 열 때마다 지불하게 됨  
- 플러그인 매니저는 그 위에 추가 오버헤드를 더함  
- 정확히 **3개의 플러그인**만 사용하며, 설치 스크립트가 한 번 git clone한 뒤 `.zshrc`에서 source함  
  - `fzf-tab`, `zsh-autosuggestions`, `zsh-syntax-highlighting`  
  - 시작 시 의존성 해석을 수행하는 플러그인 매니저가 없으며, 이미 디스크에 있는 파일을 source하는 것은 사실상 비용이 없음  
  
### 자동완성 캐싱  
  
- `compinit`은 일반적인 `.zshrc`에서 가장 비용이 큰 작업 중 하나로, 기본적으로 셸을 열 때마다 모든 자동완성 파일에 대한 **보안 감사**를 수행함  
- 해결책은 캐시(`.zcompdump`)가 24시간보다 오래된 경우에만 전체 실행을 하고, 그 외에는 `-C`로 검사를 건너뛰는 것  
  - glob 한정자 `#qNmh-24`는 "존재하며 최근 24시간 이내에 수정됨"을 의미함  
  - 하루에 한 번만 전체 `compinit`을 실행하고, 나머지 시간에는 캐시된 읽기를 사용함  
  
### 지연 로딩 (Lazy-loading)  
  
- nvm은 가장 악명 높은 셸 시작 속도 저하 원인으로, 시작시점에 즉시 source하면 **0.5초**가 쉽게 추가될 수 있음  
- 모든 셸에서 nvm이 필요한 것이 아니라 `nvm`을 입력할 때만 필요하므로, 첫 사용 시 자기 자신을 대체하는 함수로 감쌈  
  - 첫 `nvm` 호출이 스텁을 삭제하고 실제 nvm을 source한 뒤(`--no-use`로 node 버전 해석도 막음) 인자를 전달함  
- kubectl 자동완성도 같은 방식으로, `kubectl` 바이너리를 호출해 자동완성 스크립트를 생성하므로 실제로 처음 실행한 뒤에만 로드함  
- `eval "$(tool init zsh)"`를 `.zshrc`에 넣으라고 안내하는 모든 도구는 시작 시 프로세스를 fork하고 출력을 평가하므로 **지연 로딩 후보**가 됨  
- direnv와 fzf는 빠르고 자주 사용하므로 즉시 로딩 상태로 유지하며, 실제로 자주 쓰는 것이 무엇인지 엄격하게 판단해야 함  
  
### 논블로킹 프롬프트  
  
- `git status`를 동기적으로 실행하는 프롬프트는 어느 정도 큰 저장소에서 지연이 생기며, 이는 Enter를 누를 때마다 체감되어 느린 시작보다 더 나쁠 수 있음  
- [pure](https://github.com/sindresorhus/pure)를 사용하며, 프롬프트를 즉시 렌더링하고 git 정보는 준비되면 **비동기적으로** 채움  
- zsh 내장 `vcs_info`로 교체를 잠깐 시도했으나, pure의 비동기 동작이 더 나았음  
- 직접 프롬프트에서 비동기 git status를 구현할 수도 있으나, pure가 해당 용도에 맞게 잘 감싸 줌  
  
### 터미널 에뮬레이터 자체  
  
- 셸 시작은 절반의 이야기일 뿐이며, 에뮬레이터 자체가 **입력 지연**을 추가함  
- GPU 가속 네이티브 터미널인 [Ghostty](https://ghostty.org)를 사용하며, 설정은 단 7줄임  
- `tmux new -A -s main` 별칭(`t`)과 결합해, 새 터미널 창이 기존 세션으로 바로 복귀시킴  
  
### 자신의 셸 성능 측정 방법  
  
- 직접 터미널에서 시간이 어디에 쓰이는지 측정할 수 있으며, 확인할 지연은 **시작 시간, 프롬프트 지연, 입력 지연** 세 가지임  
- 기본 측정은 `time zsh -i -c exit`를 몇 번 실행하는 것으로, 첫 실행은 콜드 캐시 때문에 항상 더 느림  
  - **100ms 미만이면 괜찮고, 50ms 미만이면 훌륭하며, 500ms 이상이면 손볼 부분이 있음**  
- 정확한 통계를 위해 hyperfine을 사용: `hyperfine --warmup 3 'zsh -i -c exit'`  
- zsh에 내장된 프로파일러 활용  
  - `.zshrc` 맨 위에 `zmodload zsh/zprof`, 맨 아래에 `zprof`를 넣으면 시간이 어디에 쓰였는지 정렬된 표를 출력함  
  - 상위 항목은 보통 `compinit`, `nvm.sh` source, `eval "$(...)"`이며, 가장 위 항목부터 고치고 재실행을 반복함  
  - 완료 후 두 줄을 제거함  
- zprof로 부족하면 타임스탬프로 전체 시작을 추적: `zsh -ixc exit 2>&1 | ts -i '%.s' | sort -rn | head -20`  
  - 또는 `PS4='+%D{%s.%6.}: '`를 설정하고 `zsh -ixc exit 2> startup.log` 실행 후 줄 간 큰 점프를 확인함  
- 시작은 빠른데 프롬프트 redraw가 느릴 수 있으며, 가장 큰 git 저장소로 `cd`한 뒤 Enter를 눌러 다음 프롬프트가 나타나기 전 지연이 있으면 프롬프트가 동기 작업을 하는 것임  
  - 비동기 프롬프트로 전환하거나 Git 기능을 제거하는 선택지가 있음  
  
### 마무리  
  
- 대부분의 최적화는 무언가를 덜어내는 것에 관한 것으로, 의도적으로 행동하고 **실제로 사용할 것만 추가하는 것이 핵심**임  
- 이렇게 하면 하루에 여는 수십 개의 세션이 모두 즉시 열리고, 터미널은 기다려야 하는 애플리케이션이 아니라 **머리의 확장**처럼 느껴지는 도구가 됨  
- 하루 종일 사용하는 도구에 대해 이 속도는 타협 불가능함  
- 위의 모든 설정은 [dotfiles 저장소](https://github.com/mijndert/dotfiles)에 공개되어 있음

## Comments



### Comment 59050

- Author: neo
- Created: 2026-06-07T09:06:06+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/k0sbbv/life_is_too_short_for_slow_terminal) 
- 엄밀히 말하면 대부분 **터미널**이 아니라 **셸**을 뜻하는 것임

- 기본값이 제대로 된 도구를 쓰는 게 낫고, 그래서 **fish**를 쓰면 됨
  - 회사의 **ZSH**가 1년쯤 전부터 말도 안 되게 느려져서 fish를 써봤고, 삶의 질 기능이 정말 마음에 들었음  
    화살표 키로 고를 수 있는 현대적인 탭 완성 같은 기능이 기본으로 들어 있는 점이 좋았고, 개인 장비에서는 아직 ZSH를 쓰지만 그건 Nix 설정과 home manager를 손볼 시간이 없어서임
  - 누군가 **bash 호환 fish**를 만들어주면 좋겠음  
    합리적인 기본값과 빠른 내장 완성이 있으면서, bash 기반 도구를 버리거나 다시 쓰지 않아도 되는 셸이면 좋겠음
  - 새 도구를 설치하기엔 인생이 너무 짧고, 그냥 합리적인 기본값만 있으면 됨

- **비차단 프롬프트**나 OpenGL 기반 터미널 같은 작업이 xterm에 `PS1="\W: "` 정도만 쓰는 것보다 정말 가치가 있는지 가끔 의문이 듦
  - 몇 년간 일부러 **xterm**을 쓰지 않았는데, 여러 터미널 에뮬레이터를 살펴보니 xterm이 OpenType 글꼴, UTF-8, 대부분의 이모지, 24비트 색상, 낮은 메모리 사용량을 모두 지원해서 꽤 놀랐음  
    게다가 매우 빠르고 “표준”이라는 장점이 있어서, 남아 있는 버그도 대개 사소하거나 그 안에서 실행되는 프로그램들이 정상 동작으로 간주할 가능성이 큼  
    그래서 다시 xterm을 쓰게 됨
  - 그만한 가치가 있지는 않음  
    **zsh 시작**은 원래 매우 빠르고, 느려지는 건 사용자가 느리게 만들었을 때뿐임  
    이해하지 못하는 것들을 잔뜩 넣지 않으면 되고, “미니멀”이라 부르면서 프롬프트를 만들 때마다 수백 개 명령을 실행하는 라이브러리도 여기에 포함됨  
    내 zsh 설정은 90년대부터 아주 천천히 발전해 온 몇백 줄짜리이고, 모든 줄을 이해하며 왜 있는지도 알고 있음  
    특별히 빠르게 만들려고 한 적은 없지만 여전히 20ms에 시작하고, 느려질 만한 바보 같은 변경을 하면 바로 알아채고 고칠 수 있음

- `time zsh -i -c exit` 같은 깨진 **벤치마크**가 아직도 흔히 쓰이는 게 싫음  
  완전히 잘못된 대상을 측정하고, 일부 zsh 플러그인 관리자들은 실제 셸 시작 지연을 희생하면서까지 이 쓸모없는 지표에 최적화했음  
  zsh-bench에는 이 벤치마크가 왜 무의미한지 설명하는 섹션이 있음: https://github.com/romkatv/zsh-bench#how-not-to-benchmark  
  zsh-bench가 측정하는 첫 프롬프트 지연이나 입력 지연 같은 지표가 훨씬 유용함

- GPU 가속 터미널 버그 얘기일 줄 알았는데 아니라서 반가웠음  
  **완성 캐싱**은 좋은 팁이고, Mac 회사 장비에서 zsh를 쓰는데 새 탭을 열 생각만 해도 비치볼이 떠서 도움이 되길 바람  
  kubectl 완성의 경우 느린 부분이 완성 생성인지 읽어들이기인지 궁금하고, 전자라면 파일로 저장한 뒤 읽어들이면 시작 시간이 줄어들지 궁금함  
  `jj`에서는 그렇게 하고 있고, `jj`로 옮기면서 `git status`를 실행하는 프롬프트는 버렸음  
  작성자의 시간을 같이 보여줬으면 내 0.287초가 평균인지 느린 편인지 알 수 있었을 텐데 아쉬움  
  이후 측정해 보니 거의 빈 `.bashrc`는 0.007초, skim 키 바인딩 후 0.043초, mise 후 0.115초, jj 완성 후 0.186초, `/etc/bashrc`까지 읽으면 0.294초라 개선 여지가 있어 보임
  - 글에서는 셸 자체가 앞단에서 **30ms**라고 했고, 같은 `time shell -c exit` 테스트에서 내 것은 약 50ms가 나옴  
    다른 사람의 Linux 환경을 쓸 때 가장 짜증나는 건 곳곳의 쓸데없는 애니메이션임  
    내 컴퓨터에서는 단축키를 누르면 터미널 창이 거의 즉시 열리고, 가끔 창과 프롬프트 사이에 짧은 깜빡임만 보임  
    그래서 새 창을 열고 셸에서 뭔가 한 뒤 닫는 전체 종단 간 테스트가 중요하며, `time myterm` 후 창에서 Ctrl+D를 눌러 닫으면 항상 0.120초 아래였음  
    쓸데없는 애니메이션과 합성을 없애면 가능한 일이 많아지고, 두 스프레드시트 차이를 볼 때도 창 두 개를 최대화한 뒤 창 말아올리기 단축키로 빠르게 번갈아 보니 차이가 즉시 보였음  
    Windows에서 Excel 애니메이션과 함께 같은 일을 하려면 너무 산만함
  - **100ms 미만**은 내 환경에서는 어려워 보임  
    빈 설정으로도 `zsh -i -c exit`가 평균 129.8ms이고, 전체 설정은 약 250ms로 비슷하게 걸림  
    compinit 캐싱으로 평균 5ms 정도 줄이긴 했지만, 완성이 누락될 수 있어서 그만한 노력의 가치는 크지 않다고 봄

- 최근 **zsh 시작**이 거의 멈춘 것처럼 느려졌고, 원인은 정확히 찾지 못했지만 compinit이 임계 경로 대부분을 차지한다는 건 확인했음  
  글에서 제안한 방식과 거의 비슷하게 캐싱을 구현해 느려짐을 없앴고, 멋진 glob qualifier를 보고 내 방식도 개선해야겠다고 느낌  
  그런 기능이 가능한지도 몰랐고, 솔직히 좀 의심스러운 기능처럼 보이지만 그래도 쓸 예정임  
  기존에는 대상 경로를 만들 때 비교적 투박한 `date -Id` 방식을 썼음  
  zsh처럼 완전한 프로그래밍 언어로 설정되는 도구가 좋고, 작성자가 캐싱 기능을 추가할 필요 없이 직접 구현할 수 있음  
  거의 20년간 zsh를 쓰면서 프레임워크나 플러그인 관리자를 써본 적은 없고, 이런 것들이 주로 스타일링 때문에 쓰이는 듯함  
  나는 컴퓨팅 환경의 미관에 신경 쓰지 않아서 운이 좋고, 직접 만든 프롬프트도 기본적이고 작고 정보성은 있지만 전혀 화려하지 않으며 검은 배경의 기본 터미널 테마를 씀
  - **compinit 캐싱**은 캐시가 오래될 수 있어 답답함  
    여러 셸 인스턴스가 병렬로 같은 일을 할 수도 있고, tmux에서 실습용 병렬 인스턴스를 띄울 때 자주 겪었음  
    또 여러 호스트, 특히 컨테이너 사이에서 홈 디렉터리를 공유할 수도 있어서, 결국 잠금 파일과 만료 검사, `zcompile` 조건 처리까지 넣은 방식으로 정리했음
  - ZSH 로드 시간이 너무 나빠져서 그냥 **fish**를 시도했음  
    안타깝게도 fish 설정도 서서히 같은 방향으로 흘러간 것 같고, 월요일 쉬는 시간에 프로파일링을 해 보며 지연 로딩 기법이 실제로 내 경우에 유용한지 확인할 예정임  
    느려지는 시간 대부분은 Starship의 git 모듈 때문일 것 같지만, 지연 로딩할 수 있는 별칭과 도우미 함수도 꽤 있음

- Emacs에서는 오래전부터 백그라운드 **스테이징 셸**을 미리 초기화해 둠  
  터미널을 연다는 건 그 버퍼로 새 창을 열고 이름을 바꾸는 것이고, 다음번을 위해 셸을 다시 준비하는 스레드를 포크함  
  그래서 시작 지연이 없음  
  예전에 reptyr로 Emacs 밖의 해법도 억지로 만들어보려 했던 기억이 있지만, 결국 그쪽을 계속 쓰지는 않았고 이유는 잘 기억나지 않음  
  https://github.com/nelhage/reptyr
  - Android의 **zygote 프로세스** 같은 느낌이라 좋음

- 비슷하게 살펴보다가 `zsh-abbr`이 시작 시간 약 **100ms**를 잡아먹는다는 걸 알았지만, 그 정도는 괜찮음  
  여기저기서 10ms씩 줄일 수는 있어도 잃는 기능을 생각하면 가치가 없어 보임  
  약 300ms 시작 시간으로 살겠고, 충분히 빠르며 터미널을 연속으로 마구 열거나 즉시 타이핑해야 하는 경우도 별로 없음  
  그래도 글은 좋았고, `hyperfine`을 알게 되었으며 zsh 시작 파일 몇 개를 들여다보게 됨

- 덕분에 오래 미뤄둔 **zshrc 수정**을 했고, 이제 80ms까지 내려와서 아주 좋음

- 내 인생은 느린 터미널을 감당할 만큼 길고, 가끔은 터미널이 더 느렸으면 좋겠음  
  예를 들어 root 콘솔에서 실제 실행 전에 기본 **5초 지연**을 넣어 오타를 Ctrl+C로 취소할 시간을 줬다면, 반항적이던 젊은 시절 며칠은 아꼈을지도 모름
