본문 바로가기
잡(job)기술

X11 기초 이해하기: Display, Screen, 그리고 $DISPLAY의 정체

by 무니이구나 2026. 9. 21.

💡 한 줄 요약

  • 이 글은 리눅스 GUI 환경에서 당연하게 쓰지만 정확히는 모르고 지나가기 쉬운 Display, Screen, $DISPLAY 환경변수, /tmp/.X11-unix 소켓의 관계를, X 클라이언트-서버 통신 원리를 통해 정리한다. (Wayland/XWayland는 2부, 3부에서 다룬다)

 


🚨 1. 이 글을 쓰는 이유 및 대상 독자 {#1}

  • 동기: echo $DISPLAY를 치면 :0 같은 값이 나오는데, 이게 정확히 뭘 가리키는지, 왜 :0이고 :1은 뭔지, 소켓 파일과는 무슨 관계인지 설명 없이 그냥 "외워서" 쓰는 경우가 많다.
  • 대상 독자: 리눅스 GUI 환경(특히 임베디드 보드나 원격 SSH 환경)에서 $DISPLAY, X 서버 관련 에러를 마주쳐본 사람, 또는 X11의 내부 동작 원리가 궁금한 사람.

⚠️ 공통적인 Pain Point
SSH로 서버에 접속해서 GUI 앱을 띄우려다 cannot connect to X server 에러를 본 적이 있다면, 이 글이 그 원인을 이해하는 데 도움이 된다.


🛠️ 2. 사전 지식 & 개발 환경 {#2}

2.1 사전 지식

  • 유닉스 도메인 소켓(Unix domain socket)의 기본 개념
  • 클라이언트-서버 아키텍처에 대한 일반적인 이해

2.2 개발 환경

분류 기술 스택 / 도구 버전 비고
OS Ubuntu 22.04 / 24.04 대부분의 배포판에서 동일
디스플레이 서버 X.Org Server 21.x Xorg 기준
확인 도구 xdpyinfo, xrandr, netstat - 실습에 사용

🔍 3. 핵심 개념: Display와 Screen {#3}

X11 용어에서 서버(Server)클라이언트(Client)는 흔히 쓰는 웹 서버/클라이언트 감각과 반대다.

  • X 서버: 모니터, 키보드, 마우스 같은 실제 하드웨어를 직접 제어하는 쪽. 데스크톱 컴퓨터 자체가 X 서버다.
  • X 클라이언트: 그 하드웨어에 "이런 창을 그려줘"라고 요청하는 앱(파이어폭스, 터미널 등).

이 구도 위에 두 가지 논리적 단위가 있다.

  • Display: 키보드 + 마우스 + 모니터(들)로 구성된 하나의 입출력 세트. 하나의 X 서버 프로세스가 관리하는 단위다.
  • Screen: 하나의 Display 안에 속한 개별 물리 화면. 모니터 2대를 별도 Screen으로 구성하면 :0.0, :0.1처럼 구분된다. (참고로 요즘은 멀티모니터를 별도 Screen이 아니라 하나의 Screen 안에서 Xinerama/RandR로 확장하는 방식이 일반적이라, 실제로 .1 이상의 Screen 번호를 볼 일은 많지 않다)

$DISPLAY 환경변수는 이 둘을 다음 문법으로 표현한다.

[hostname]:displaynum[.screennum]
예시 의미
:0 로컬 머신의 0번 Display, Screen 생략(기본 0번)
:0.1 로컬 머신의 0번 Display, 1번 Screen
localhost:10.0 로컬호스트의 10번 Display (SSH 포워딩 시 흔히 보이는 번호대)

🧪 4. 실습으로 확인하기 {#4}

# 현재 세션의 $DISPLAY 값 확인
echo $DISPLAY
# :0

# 해당 디스플레이에 대응하는 유닉스 소켓 확인
ls -la /tmp/.X11-unix/
# srwxrwxrwx 1 root root 0 ... X0

# 디스플레이 정보 상세 조회 (Screen 개수, 해상도 등)
xdpyinfo | head -20

 

:0이라는 값과 /tmp/.X11-unix/X0라는 파일명이 정확히 대응하는 것을 볼 수 있다. 이는 우연이 아니라 X11의 고정된 규칙이다.


🔬 5. 원인 분석: 클라이언트가 서버를 찾아가는 과정 {#5}

X 클라이언트(예: xterm)가 실행되면 내부적으로 다음 순서를 거친다.

 

핵심은 X 서버가 시작될 때 displaynum에 해당하는 유닉스 소켓 파일을 /tmp/.X11-unix/X<N> 경로에 미리 만들어 놓고 그 위에서 listen()하고 있다는 점이다. 클라이언트는 $DISPLAY에서 숫자만 뽑아내 이 소켓 경로를 그대로 조립해서 접속을 시도한다. 즉 :0이라는 짧은 문자열은 실제로는 "/tmp/.X11-unix/X0 소켓에 연결하라"는 지시나 다름없다.

원격 접속(hostname:10.0처럼 호스트명이 붙은 경우)은 경로가 다르다. 이때는 유닉스 소켓 대신 TCP 6000+N번 포트(예: 10번 디스플레이면 6010번)로 접속하며, SSH X11 포워딩(ssh -X)은 이 TCP 연결을 SSH 터널 안으로 감싸서 전달하는 방식이다. 로컬 소켓과 원격 TCP, 두 경로 모두 최종적으로는 같은 X11 프로토콜 메시지를 주고받는다는 점은 동일하다.


💡 6. 흔한 오해 {#6}

  • ❌ "$DISPLAY가 없으면 X 서버가 없다"$DISPLAY는 어디에 접속할지를 알려주는 주소일 뿐, X 서버 존재 여부와는 별개다. 환경변수만 안 잡혀 있을 수도 있다.
  • ❌ "Display 번호는 모니터 개수와 같다" → Display 번호는 세션(로그인 인스턴스) 단위다. 모니터 여러 대는 보통 하나의 Display, 하나의 Screen 안에서 RandR로 확장된다.
  • ❌ "소켓 파일이 있으면 X 서버가 살아있다" → 비정상 종료 시 소켓 파일이 남아있는데 서버 프로세스는 죽어있는 경우도 있다(stale socket). xdpyinfo처럼 실제로 프로토콜 통신을 해보는 것이 확실하다.

🏁 7. 마무리 {#7}

7.1 결론

$DISPLAY는 단순한 환경변수가 아니라, X 클라이언트가 X 서버의 유닉스 소켓(또는 TCP 포트) 주소를 조립하기 위한 규격화된 문자열이다. Display는 입출력 세트 단위, Screen은 그 안의 물리 화면 단위이며, /tmp/.X11-unix/X<N> 소켓이 이 모든 것을 실제 통신 채널로 연결한다.

7.2 참고 자료

7.3 다음 단계

  • 2부: Wayland와 컴포지터 — X11의 3자 구도(클라이언트-서버-WM)가 Wayland에서 어떻게 클라이언트-컴포지터 2자 구도로 재편되는지
  • 3부: XWayland — Wayland 세션에서 X11 앱이 어떻게 $DISPLAY와 소켓을 다시 만들어내며 동작하는지