디스크립터
고친 사람 github-actions[bot]
디스크립터는 어떤 대상이 무엇인지를 따로 적어 둔 작은 데이터입니다. 프로그램은 대상 본체를 옮기는 대신 이 데이터를 건네 서로 같은 것을 가리킵니다. 자바 클래스 파일이 타입을 적어 두는 문자열도, 그래픽스에서 그림에 쓸 자원을 물려주는 항목도 디스크립터라 부릅니다. 분야마다 생김새는 다르지만 본체 대신 건네는 설명이라는 쓰임은 같습니다.
쉽고 빠른 이해
디스크립터는 대상의 정체를 정해진 형식으로 적어 둔 작은 데이터입니다. 정수 둘을 받아 정수를 돌려주는 자바 메서드를 클래스 파일은 (II)I 라는 여섯 글자로 적습니다.
본체를 통째로 건네면 받는 쪽이 무겁습니다. 그래픽 메모리에 올라간 그림이나 운영체제가 들고 있는 열린 파일은 아예 옮길 수 없습니다. 작고 형식이 정해진 데이터를 대신 건네면 양쪽이 같은 대상을 가리킬 수 있습니다.
어떻게 도나:
- 대상마다 무엇을 적을지 형식을 미리 정합니다
- 대상을 만들 때 그 형식대로 디스크립터를 채웁니다
- 쓰는 쪽은 본체 대신 디스크립터를 받아 대상을 다룹니다
대가는 한 겹이 늘어난다는 것입니다. 본체가 사라졌는데 디스크립터만 남으면 이미 없는 대상을 가리키게 됩니다.
상세
부동산 유리창에 붙은 매물 쪽지를 떠올리면 됩니다. 집은 그 자리에서 움직이지 않으므로 손님에게 건네지는 것은 층수와 방 개수와 값을 적은 종이 한 장입니다. 이미 팔린 집 쪽지가 그대로 남아 있으면 손님은 없는 집을 보러 갑니다.
디스크립터는 어떤 대상의 정체를 정해진 형식으로 적어 둔 작은 데이터입니다. 자바에서 정수 둘을 받아 정수를 돌려주는 메서드의 디스크립터는 (II)I 입니다. 이 여섯 글자만 있으면 그 메서드가 무엇을 받고 무엇을 돌려주는지 가려집니다. 디스크립터는 본체와 떨어져 따로 보관되는 경우가 많습니다.
「정해진 형식」이라는 대목이 뜻을 집니다. 사람이 읽으려고 적은 설명이 아니라 기계가 읽으려고 적은 설명입니다. 형식이 미리 정해져 있으니 읽는 쪽은 뜻을 물어볼 것 없이 바로 해석합니다.
이 절은 먼저 디스크립터가 분야를 가리지 않고 갖는 성질을 봅니다. 이어서 이 말이 나오는 분야를 표로 훑습니다. 그다음 클래스 파일과 그래픽스를 차례로 봅니다. 끝으로 이름은 같지만 뜻이 어긋나는 파일 디스크립터를 가르고, 이 방식을 고르는 때로 마칩니다.
디스크립터가 공통으로 갖는 성질
분야가 달라도 디스크립터라 부르는 것들은 아래 셋을 함께 갖습니다.
| 성질 | 무엇을 뜻하나 |
|---|---|
| 본체보다 작다 | 건네고 복사하는 비용이 적다 |
| 형식이 미리 정해져 있다 | 읽는 쪽이 해석 방법을 이미 안다 |
| 본체 대신 건네진다 | 본체를 열어 보지 않고도 대상을 다룰 수 있다 |
셋 중 하나라도 빠지면 그것은 디스크립터가 아니라 대상 그 자체이거나 사람이 읽는 설명서입니다.
디스크립터라는 말이 나오는 분야
| 분야 | 디스크립터가 담는 것 | 가리키는 본체 |
|---|---|---|
| 클래스 파일 | 타입을 적은 짧은 문자열 | 필드나 메서드 |
| 그래픽스 | 자원의 주소와 종류 | 화면에 쓸 그림이나 값 묶음 |
| 컨테이너 이미지 | 종류와 크기, 내용을 요약한 값인 다이제스트 | 이미지를 이루는 조각 |
| 주변 장치 연결 | 장치가 밝히는 자기 정체와 기능 | 연결된 장치 |
| 운영체제 | 번호 하나 | 열어 둔 파일 |
앞의 넷은 디스크립터 자신이 설명을 담습니다. 마지막 줄만 다릅니다. 번호는 대상에 대해 아무것도 설명하지 않고, 설명은 운영체제가 따로 들고 있습니다. 이 어긋남은 아래에서 소절 하나를 따로 두어 다룹니다.
클래스 파일의 디스크립터
자바 소스를 컴파일하면 클래스 파일이 나옵니다. 이 파일은 사람이 아니라 자바 가상 머신이 읽습니다. 그래서 타입 이름을 사람이 쓰는 대로 적지 않고 정해진 글자로 줄여 적습니다. 그 글자 묶음이 디스크립터입니다.
메서드의 디스크립터는 괄호 안에 받는 타입을 차례로 적고 괄호 뒤에 돌려주는 타입을 적습니다.
int add(int a, int b) // (II)I
boolean isEmpty() // ()Z
long size(double d) // (D)J
오른쪽 주석이 그 메서드의 디스크립터입니다. int 가 I 로, boolean 이 Z 로, long 이 J 로 줄어든 것입니다. 기본 타입은 이렇게 글자 하나씩을 나눠 갖습니다.
기본 타입이 아닌 것은 글자 하나로 안 끝납니다. 클래스와 배열이 그렇습니다.
| 적는 것 | 디스크립터 |
|---|---|
| 정수 | I |
| 긴 정수 | J |
| 실수 | D |
| 참거짓 | Z |
| 돌려주는 값이 없음 | V |
| 클래스 | L 다음에 이진 이름, 끝에 ; |
| 배열 | 차원마다 [ 를 앞에 붙임 |
이진 이름은 패키지 구분을 점 대신 빗금으로 적은 클래스 이름입니다. 그래서 문자열 하나를 받고 아무것도 돌려주지 않는 메서드는 (Ljava/lang/String;)V 가 되고, 정수 배열 하나는 [I 가 됩니다.
디스크립터가 없으면 곤란해지는 대목은 이름이 겹칠 때 드러납니다. 자바는 이름이 같고 받는 타입만 다른 메서드를 여럿 둘 수 있습니다. 클래스 파일은 이름과 디스크립터를 한 쌍으로 묶어 이 메서드들을 가릅니다. 쌍이 다르면 다른 메서드입니다.
이 쌍은 파일 앞쪽의 상수 풀에 한 번만 적히고, 바이트코드는 그 항목의 번호만 부릅니다. 같은 메서드를 백 번 불러도 디스크립터 문자열은 파일에 하나만 있습니다.
그래픽스의 디스크립터
화면을 그리는 계산은 GPU(Graphics Processing Unit, 그래픽 처리 장치) 안에서 도는 작은 프로그램이 맡습니다. 이 프로그램을 셰이더라고 부릅니다. 셰이더는 그림 데이터인 텍스처나 값을 모아 둔 버퍼를 읽어 화면에 낼 색을 계산합니다.
셰이더는 이 자원들을 직접 들고 있지 않습니다. 자원은 그래픽 메모리에 따로 올라가 있고, 셰이더 코드에는 몇 번째 묶음의 몇 번째 칸을 읽으라는 표시만 적힙니다. 그 칸에 꽂아 두는 항목이 디스크립터입니다. 디스크립터에는 자원이 그래픽 메모리 어디에 있고 어떤 종류인지가 담깁니다.
칸 여러 개를 한 덩이로 묶은 것이 디스크립터 세트입니다. 그리기 명령 앞에서 이 세트를 넘겨주면 셰이더가 쓸 자원이 한 번에 정해집니다. 어떤 칸에 어떤 종류가 오는지는 디스크립터 세트 레이아웃이 미리 정해 둡니다. 칸마다 정해지는 그 종류가 디스크립터 타입입니다.
flowchart TD
S["셰이더 · 0번 묶음 1번 칸을 읽는다"]
subgraph SET["디스크립터 세트 · 0번 묶음"]
D0["0번 칸 · 값 묶음 디스크립터"]
D1["1번 칸 · 그림 디스크립터"]
end
S --> D1
D1 --> R["텍스처 본체 · 그래픽 메모리"]
셰이더 코드는 칸 번호만 알고 자원 이름은 모릅니다. 그래서 같은 셰이더로 그림만 갈아 끼워 여러 물체를 그릴 수 있습니다. 바뀌는 것은 칸에 꽂힌 디스크립터뿐입니다.
이름은 같지만 뜻이 다른 파일 디스크립터
파일 디스크립터는 열어 둔 파일에 운영체제가 매기는 작은 정수입니다. 이 번호 자체는 파일에 대해 아무것도 설명하지 않습니다. 파일을 어디까지 읽었고 어떤 모드로 열었는지는 운영체제의 핵심 부분인 커널이 따로 들고 있습니다. 번호는 그 기록을 찾아가는 표의 칸 번호일 뿐입니다.
그래서 이 이름은 두 갈래로 쓰입니다. 하나는 설명을 담은 데이터이고, 다른 하나는 설명을 들고 있는 기록을 부르는 번호표입니다. 뒤쪽은 핸들이라 부르는 것과 성격이 같습니다.
글을 읽다가 어느 쪽인지 가리려면 이렇게 물으면 됩니다. 이 디스크립터를 열어 보면 대상의 타입이나 주소가 나오나, 아니면 다른 표를 한 번 더 거쳐야 하나.
디스크립터를 두는 때와 두지 않는 때
본체를 옮길 수 없을 때 둡니다. 그래픽 메모리에 올라간 텍스처와 운영체제가 들고 있는 열린 파일이 그런 대상입니다. 이런 것들은 복사해 건네는 선택지가 없습니다.
읽는 쪽이 기계일 때 둡니다. 형식이 정해져 있으면 해석이 단순해집니다. 클래스 파일이 타입 이름을 글자로 줄여 적는 까닭도 같습니다.
본체가 작고 그대로 건네도 되면 두지 않습니다. 사람이 읽고 고쳐야 하는 값도 마찬가지입니다. 설정 파일에 파일을 적을 때 번호가 아니라 경로를 그대로 적는 것이 그런 경우입니다.
대가는 본체와 디스크립터가 따로 산다는 것입니다. 본체를 버린 뒤에도 디스크립터가 남아 있으면 그 디스크립터는 없는 대상을 가리킵니다. 파일 쪽에서는 닫은 번호를 다시 쓰다가 엉뚱한 파일을 읽고, 그래픽 쪽에서는 화면이 깨집니다. 그래서 디스크립터를 쓰는 곳은 대개 언제 버릴지를 규칙으로 못박아 둡니다.
관련 항목
디스크립터라는 이름이 붙는 데이터
파일 디스크립터 · 메서드 디스크립터 · 필드 디스크립터 · 콘텐츠 디스크립터 · 세그먼트 디스크립터 · USB 디스크립터
클래스 파일에서 디스크립터를 담고 쓰는 구조
클래스 파일 · 상수 풀 · 바이트코드 · JVM · 이진 이름 · 메서드 오버로딩 · 클래스 로더 · 타입 소거
그래픽스에서 디스크립터를 묶고 물려주는 단위
디스크립터 세트 · 디스크립터 세트 레이아웃 · 디스크립터 타입 · 디스크립터 풀 · 파이프라인 레이아웃 · 바인딩 · 셰이더
디스크립터가 가리키는 대상
텍스처 · 버퍼 · 샘플러 · 이미지 뷰 · 유니폼 버퍼
디스크립터와 같은 역할을 맡는 다른 수단
핸들 · 포인터 · 참조 · 식별자 · 메타데이터 · 스키마
디스크립터를 만들어 나눠 주는 실행 환경
다른 이름: descriptor · 서술자 · 기술자