- 터미널 Emacs에서 Solarized 같은 테마를 제대로 보려면 24비트 색상 자체보다 터미널, terminfo, tmux, mosh가 같은 색상 기능을 끝까지 이해하는지가 중요함
- RGB 색상은
ESC[38;2;<r>;<g>;<b>m형태로 널리 쓰이지만, 표준에 가까운 콜론 구문과 실제 구현에서 퍼진 세미콜론 구문이 함께 남아 호환성을 복잡하게 만듦 xterm-256color와xterm-direct는 각각 256색 팔레트와 16,777,216색을 광고하지만, terminfo의 팔레트 중심 모델은 직접 RGB 색상을 깔끔하게 표현하지 못함- 실제 환경에서는
ncurses-term의-direct항목,tmux-direct, mosh 1.4 계열,vscode-direct같은 대체 TERM 값이 필요할 수 있으며 일부 계층은 여전히 세미콜론 방식만 받음 - 현대 터미널 기능을 안정적으로 쓰려면 TERM과 terminfo만으로는 부족하며, 터미널 이름·버전별 기능을 더 빠르게 갱신하는 별도 표현 방식이 필요함
터미널 Emacs에서 24비트 색상이 필요한 이유
- 그래픽 환경의 Emacs는 자동으로 24비트 색상을 지원해 Solarized 같은 테마와 글꼴을 제대로 보여줌
- 터미널에서 같은 테마를 쓰면 색 표현이 제한되어 화면이 덜 보기 좋게 나올 수 있음
- 인기 터미널들은 오래전부터 24비트 색상을 지원했지만, 프로그램이 이를 쓰려면 기능 감지와 설정이 모두 맞아야 함
- 목표는 두 가지임
- 현재 터미널 환경에서 truecolor 지원을 켜는 방법 찾기
- Emacs 색상 문제가 1970~1990년대 터미널 표준과 어떻게 이어지는지 확인하기
ANSI 이스케이프 코드와 색상 확장 역사
- 초기 하드웨어 터미널은 서로 다른 제어 코드 체계를 썼고, 이식 가능한 소프트웨어를 만들려면 ANSI 표준화가 필요했음
- ANSI escape codes는 1970년대부터 이어졌으며, 색상에서는 SGR(Select Graphics Rendition) 이 핵심임
- 굵게 또는 밝기
- 이탤릭
- 깜박임
- 전경색과 배경색
- 기타 문자 표시 속성
- 처음 색상은 RGB 큐브의 8개 꼭짓점에 해당하는 3비트 색상이었음
- 검정, 흰색, 가산 원색, 감산 원색이 포함됨
- 이후 밝은 색 또는 굵게 비트가 추가되며 16색으로 확장됨
- “bright black”은 짙은 회색에 해당함
- 1999년 Todd Larason은 xterm에 256색 지원 패치를 추가함
- 6x6x6 RGB 색상 큐브 샘플링
- 24단계 그레이스케일 램프
- 드물지만 여전히 지원되는 88색 변형도 존재함
24비트 색상 구문이 만들어진 경로
- 8비트 색상과 24비트 색상은 호환 터미널에서 다음 형태로 설정됨
ESC[38;5;<n>m: 팔레트의 색상 번호n을 전경색으로 설정ESC[38;2;<r>;<g>;<b>m: RGB 값r,g,b를 전경색으로 설정
- 숫자
5와2는 ISO 8613-6, 즉 ITU T.416의 확장 색상 모드와 연결됨2: RGB 공간의 직접 색상5: 인덱스 색상
- 표준화 흐름은 다음과 같음
- 1970년대: ANSI가 터미널 이스케이프 시퀀스를 표준화해 ANSI X3.64와 ECMA-48로 이어짐
- 1979년: ECMA-48 2판이 SGR 30~37, 40~47을 3비트 전경색과 배경색에 할당함
- 1984년: ECMA-48 3판이 기본 전경색과 배경색 개념을 도입하고 39, 49를 할당함
- 1991년: ECMA-48 5판은 38과 48을 “미래 표준화용”으로 남기고 ISO 8613-6을 단서로 둠
- 1993년: ISO 8613-6이 38과 48을 확장 전경색·배경색 모드로 정의함
- 하위 파라미터 구분에는 콜론을 쓰는 쪽이 표준에 가깝지만, 실제 구현은 세미콜론을 널리 채택함
ESC[38;5;3m은 SGR 38을 모르는 터미널에서38,5,3이라는 별도 파라미터처럼 해석될 수 있음- Thomas Dickey의 xterm FAQ는 당시 ITU T.416 사본이 비쌌고, RGB 값을 다른 SGR 파라미터처럼 세미콜론으로 구분한 것이 잘못이었다고 설명함
- 관련 타임라인은 다음과 같음
- 1999년: Thomas Dickey가 Todd Larason의 256색 패치를 xterm에 병합했고, 모호한 세미콜론 구문이 들어감
- 2006년: Konsole이 xterm과 같은 세미콜론 구문으로 256색과 24비트 truecolor를 지원함
- 2012년: xterm이 표준에 가까운 콜론 구문도 받도록 수정됨
- 2016년: Windows 10 내장 콘솔이 ANSI 이스케이프 코드와 24비트 색상을 지원했지만 세미콜론 구문을 사용함
- 2019년: Windows Terminal도 ANSI 이스케이프 코드를 지원하지만 세미콜론 구문을 사용함
- 2022년: Microsoft가 레거시 VGA 스타일 콘솔 서브시스템에서 ANSI 터미널 에뮬레이션으로의 생태계 전환을 발표함
- 2022년: Konsole이 표준 호환 콜론 구문을 지원함
terminfo가 색상 기능을 표현하는 방식
- terminfo는 터미널 기능 데이터베이스와 적절한 이스케이프 시퀀스 생성 기능을 제공함
TERM환경 변수는 프로그램이 사용할 terminfo 레코드를 가리키며,ssh연결에서도 자동으로 전달됨toe는 설치된 terminfo 레코드 목록을 보여주고,infocmp는 특정 레코드의 기능 확인에 쓰임- 색상과 관련해 중요한 기능은 세 가지임
colors: 터미널이 지원하는 색상 수setaf: 전경색 설정setab: 배경색 설정
xterm-256color의setaf는 색상 번호에 따라 다른 시퀀스를 냄- 0~7: ANSI 30~37 SGR 파라미터 사용
- 8~15: 비표준 90~97 밝은 색상 사용
- 그 이상:
38;5;<n>형태의 256색 팔레트 사용
xterm-direct는colors를 16,777,216으로 광고하는 24비트 RGB용 terminfo 항목임ccc를 끄며, 색상 인덱스에 새 RGB 값을 할당할 수 없음을 나타냄initc,oc,rs1같은 런타임 색상 변경 관련 항목도 빠짐setaf와setab는 콜론 기반38:2::...형태를 사용함
terminfo의 직접 색상 모델 한계
- terminfo와 ncurses의 프로그래밍 모델은 기본적으로 팔레트 엔트리 중심임
- N개의 팔레트 엔트리가 있음
- 각 엔트리에 기본 RGB 값이 있음
- 터미널이 이 값을 바꿀 수 있다는 모델을 가정함
-direct터미널은 16,777,216개의 팔레트 엔트리가 있는 것처럼 표현해 24비트 색상을 나타냄- 각 엔트리는 8:8:8 RGB 큐브에 대응함
- 값은 변경할 수 없음
- 호환성을 위해
xterm-direct방식은 가장 어두운 파란색 7개를 기본 ANSI 8색과의 호환에 사용함- 검정은 제외됨
- 기존 프로그램이
setaf의 의미를 가정하다가 거의 보이지 않는 짙은 파란색을 출력하는 일을 피하기 위한 장치임
- 이 때문에
-direct방식과-256color방식은 서로 호환되지 않음- 프로그램은 256색이 인덱스 색상이고 16,777,216색이 직접 색상임을 알아야 함
- 가장 어두운 파란색 7개를 피해야 하는 예외도 있음
- termwiz 관련 문제에서는 프로그램이 xterm-256color 팔레트를 기대했지만 실제로는 읽기 어려운 짙은 파란색 계열을 출력했음
- 해당 이슈는 작성 시점에는 열려 있었지만, @quark-zju가 수정 사항을 반영해 현재 termwiz는 합리적으로 동작함
- 핵심은 터미널 자체보다 terminfo 제약에 가까움
- 24비트 색상을 지원하는 터미널은 xterm 256색 팔레트와 RGB 값 동적 변경도 지원하는 것으로 보임
- terminfo는 현대 터미널 에뮬레이터 생태계를 정확하고 빠르게 표현하기에 부족함
TERM 설정과 세미콜론 호환성
- terminfo를 많은 프로그램이 사용하므로
TERM값은 올바르게 설정해야 함 - 콜론 기반 SGR 구문으로 통일하고 싶어도 여러 환경은 여전히 세미콜론 구문만 지원함
- terminfo 항목은 빌딩 블록으로 구성됨
xterm+direct: 표준에 가까운 콜론 구문xterm+indirect: 세미콜론만 지원하는 레거시 터미널용
xterm+indirect를 검색한 결과,vscode-direct가 가장 적합해 보였음- Microsoft 터미널을 대상으로 하므로 Windows Terminal과 Windows Console에 충분히 가깝다고 판단됨
- 모든 기능을 감사한 것은 아니지만 동작함
- 많은 서버에는
-directterminfo 항목이 설치되어 있지 않을 수 있음- 대부분의 시스템에서 기본 terminfo 데이터베이스는
ncurses-base패키지에 있음 - 확장 터미널 항목은
ncurses-term패키지가 필요함
- 대부분의 시스템에서 기본 terminfo 데이터베이스는
- ncurses에는 작성 중
winconsoleterminfo 항목이 추가됐지만, 24비트 색상을 지원하지 않고 아직 어떤 ncurses 버전에도 릴리스되지 않았음
Emacs가 truecolor를 감지하는 방식
- Emacs는 TTY에서 truecolor 지원을 감지하는 방식을 문서화함
M-x eval-expression에서(display-color-cells)를 실행하면 Emacs가 16,777,216색을 인식하는지 확인할 수 있음- Emacs 문서는
-direct모드의 terminfo 한계도 다룸RGB기능이 있는 터미널은#000001부터#000007까지를 직접 RGB가 아닌 인덱스 색상처럼 취급할 수 있음- 이는 direct color를 모르는 애플리케이션과의 하위 호환을 유지하기 위함임
- 문제가 되면
setb24,setf24가 있는 커스텀 터미널 정의를 쓸 수 있음
- Emacs는 먼저
setf24와setb24문자열을 찾고, 없으면RGB를 대체 기능으로 사용함 - 확인한 시스템의 terminfo 항목에는
setf24가 포함되어 있지 않았음
중첩 터미널에서 모든 계층이 맞아야 함
- 일반적인 작업 흐름은 여러 터미널 계층을 중첩함
- 로컬 데스크톱의 그래픽 터미널 에뮬레이터 열기
- 원격 머신이나 VM에 mosh로 접속하기
- tmux 시작하기
- Emacs 내부 터미널, Asciinema, GNU Screen 등을 추가로 사용하기
- 각 계층은 자체적으로 ANSI 이스케이프 시퀀스 상태 기계를 구현함
- 24비트 색상이 작동하려면 모든 계층이 안쪽
TERM값의 terminfo에서 생성한 이스케이프 시퀀스를 이해하고, 바깥쪽 terminfo에 맞게 정확히 전달해야 함 - 따라서 관련 소프트웨어가 충분히 최신이어야 함
- 현재 Ubuntu LTS는 mosh 1.3을 제공하므로 mosh-dev PPA를 활성화해야 했음
- 각 계층 안의
TERM도 정확해야 함- tmux 안에서는
tmux-direct를 사용함 - mosh에는 표준 terminfo가 없으므로 충분히 가까운 값을 골라야 함
- tmux 안에서는
환경별 설정
-
그래픽 터미널 에뮬레이터
- 대부분의 터미널은 적절한 기본
TERM을 설정하거나 사용자가 재정의할 수 있음 - Konsole에는
TERM값을 선택하는 옵션이 있음
- 대부분의 터미널은 적절한 기본
-
ssh
ssh는TERM값을 새 셸로 전달함- 원격 호스트에 같은 terminfo 레코드가 있으면 설정이 비교적 단순함
-
tmux
- tmux를 실행하면
TERM이screen으로 설정될 수 있음 ~/.tmux.conf에서 기본 터미널을 바꿔 해결함
set -g default-terminal "tmux-direct"- 바깥쪽
TERM이 24비트 색상을 지원할 때만 조건부로tmux-direct를 설정하고, 그렇지 않으면screen이나tmux-256color를 유지하는 방식도 고려할 수 있음
- tmux를 실행하면
-
mosh
- 최신 mosh는 24비트 색상을 지원하지만, 자체적으로는 8색 또는 256색만 광고함
- 따라서 사용자가
TERM을 적절히 설정해야 함 - mosh는 xterm 호환을 목표로 하지만 SGR 38과 48에서 세미콜론 구문만 지원함
TERM=xterm-direct는 동작하지 않음vscode-direct가xterm-direct에 가장 가까운 대안으로 쓰였음- mosh 실행 여부를 알려주는 편한 변수가 없어
detect-mosh.rs스크립트를 작성해.bashrc에서 호출함 - 셸 프로세스가
mosh-server의 자식인지 확인하는 방식임 - 로그인 경로에서 Rust를 컴파일하는 방식이 저성능 호스트에 적합한지는 확정하지 않았음
최종 결과와 남은 문제
- 설정 후 tmux와 mosh 안의 Emacs에서도 테마가 24비트 색상으로 표시됨
- 남는 문제는 세 가지로 정리됨
- 터미널들은 구문과 기능에 완전히 합의하지 않음
- terminfo는 기능 조회의 표준적 경로임
- terminfo는 제한적이고 때때로 부정확하며, 새 버전 릴리스도 자주 나오지 않음
terminfo 이후의 방향
- 현대 터미널 기능을 충분히 활용하는 소프트웨어라면 terminfo에서 벗어날 필요가 있음
- 가능한 방향은 다음과 같음
- 널리 지원되는
TERM변수는 계속 사용함 - 운영체제나 배포판의 오래된 terminfo에만 의존하지 않고, 프로그램이 터미널 기능을 독립적으로 알 수 있게 함
- 자주 갱신되는 라이브러리에 최근 10년 정도의 터미널 에뮬레이터 정보를 이름과 버전 기준으로 담음
- 더 이상 쓰기 어려운 하드웨어 터미널 지원은 포함하지 않음
- OS 제공 terminfo 파일과 terminfo 파일 형식은 계속 지원하되, 어느 정보가 최신인지 판단할 수 있는 프로토콜을 둠
- 선택적
TERMVERSION으로 2022년 Konsole과 2023년 Konsole 같은 버전별 기능 차이를 구분함 - 24비트 색상, 256색 팔레트 애니메이션, URL 링크, Kitty 그래픽 프로토콜 같은 현대 기능을 모호하지 않게 표현함
- 널리 지원되는
- 레거시 프로그램을 위한 역호환 방식도 가능함
.bashrc에서 실행하는 프로그램이TERM과TERMVERSION을 사용해$HOME/.terminfo/에 바이너리 terminfo 파일을 생성함RGB,setf24,setb24같은 명확한 24비트 색상 기능을 생성함- RGB를 모르는 프로그램은 256색 팔레트를 가정한다고 보고
colors#0x100,initc,oc를 유지함