청킹
고친 사람 github-actions[bot]
청킹은 큰 데이터를 따로 다룰 수 있는 덩어리 여러 개로 나누는 일입니다. 게임 개발에서는 게임 한 벌을 덩어리로 갈라 필요한 덩어리부터 받게 합니다. 그래서 플레이어는 게임을 다 받기 전에 놀기 시작할 수 있습니다. 검색 시스템에서는 같은 이름이 긴 글을 조각으로 자르는 일을 가리킵니다.
쉽고 빠른 이해
청킹은 게임 데이터를 여러 덩어리에 나눠 담는 일입니다. 메뉴 화면과 첫 지역만 든 덩어리를 따로 만들어 두면, 그것만 받고 게임을 시작할 수 있습니다.
파일 하나로 묶으면 수십 기가바이트를 다 받을 때까지 아무것도 못 합니다. 한국어 음성만 듣는 사람도 모든 언어의 음성을 받아야 합니다. 나눠 두면 먼저 필요한 것부터, 필요한 사람에게만 보낼 수 있습니다.
- 그림이나 소리 같은 데이터 파일마다 어느 덩어리에 넣을지 정합니다
- 게임을 묶을 때 덩어리마다 큰 파일을 하나씩 만듭니다
- 기기는 앞 덩어리부터 받습니다. 게임은 데이터를 쓰기 전에 그 덩어리가 왔는지 확인합니다
대가도 있습니다. 여러 지역이 함께 쓰는 데이터는 어느 덩어리에 둘지 따로 정해야 합니다. 그런 데이터를 앞 덩어리에 몰아 두면 처음 받을 양이 다시 늘어납니다. 게임이 작아서 금방 다 받는다면 나눌 이유가 적습니다.
상세
스무 권짜리 백과사전은 한 권으로 제본하지 않습니다. 권마다 나눠 두면 지금 필요한 권만 꺼내 읽을 수 있습니다. 개정판이 나와도 바뀐 권만 새로 사면 됩니다.
청킹은 게임 데이터에 이 일을 해 줍니다. 게임에 들어가는 데이터를 덩어리 여러 개에 나눠 담습니다. 이 덩어리 하나를 청크라고 부릅니다. 청크는 따로 받고, 따로 설치하고, 따로 바꿀 수 있는 단위입니다.
이 절은 게임 개발의 청킹을 따라갑니다. 끝에서는 같은 이름을 쓰는 다른 분야의 청킹과 견줍니다.
패키징 안의 청킹
청킹은 패키징 안에서 일어납니다. 패키징은 플레이어에게 보낼 게임 한 벌을 만드는 일입니다.
패키징은 먼저 실행 파일을 만듭니다. 게임이 쓸 데이터는 출시용 꼴로 바꿔 함께 담습니다. 편집할 때 쓰던 원본 그림을 기기가 바로 읽는 압축 형식으로 바꾸는 식입니다.
게임이 쓰는 데이터 파일을 에셋이라고 부릅니다. 그림, 3D 모델, 소리, 지도 데이터가 다 에셋입니다. 큰 게임에는 에셋이 수만 개 들어 있습니다.
에셋 수만 개를 낱개 파일로 두면 찾고 여는 비용이 쌓입니다. 그래서 패키징은 에셋을 큰 아카이브 파일에 이어 붙입니다. 아카이브 앞머리에는 목차가 있어서, 원하는 에셋이 몇 번째 바이트에서 시작하는지 찾을 수 있습니다.
청킹은 이 아카이브를 하나가 아니라 여럿으로 만드는 일입니다. 에셋마다 들어갈 청크 번호를 정해 두면, 패키징이 청크마다 아카이브를 하나씩 따로 만듭니다. 아래 그림은 에셋이 청크 번호에 따라 아카이브 여럿으로 갈리는 모습입니다.
flowchart TD
A["에셋 수만 개"] --> B["에셋마다 청크 번호를 정한다"]
B --> C0["청크 0 아카이브 · 메뉴와 첫 지역"]
B --> C1["청크 1 아카이브 · 두 번째 지역"]
B --> C2["청크 2 아카이브 · 언어별 음성"]
하나로 묶었을 때의 문제
청크 없이 아카이브 하나에 다 담는다고 해 봅니다. 게임이 수십 기가바이트면 플레이어는 마지막 바이트를 받을 때까지 기다려야 합니다. 첫 장면에 필요한 데이터는 그중 일부인데도 그렇습니다.
모든 플레이어가 모든 데이터를 받게 되는 문제도 있습니다. 음성을 열 개 언어로 녹음했다면 한국어로만 듣는 사람도 열 벌을 다 받습니다. 기기 저장 공간과 내려받는 시간이 그만큼 듭니다.
게임을 고쳐 내놓는 패치에서도 부담이 생깁니다. 아카이브가 하나면 고친 에셋이 몇 개뿐이어도 그 큰 파일 전체가 바뀐 것이 됩니다. 청크로 나눠 두면 바뀐 에셋이 든 청크만 새로 보내는 방법을 쓸 수 있습니다.
반대로 게임이 작아서 금방 다 받는다면 나눌 이유가 적습니다. 청크를 나누면 에셋마다 청크를 정하는 일과, 쓰기 전에 청크가 왔는지 확인하는 일이 새로 생기기 때문입니다.
청크를 나누는 기준
무엇을 한 청크에 묶을지는 「누가, 언제 그 에셋을 쓰나」로 정합니다. 흔한 기준은 셋입니다.
| 기준 | 예 | 얻는 것 |
|---|---|---|
| 진행 순서 | 메뉴 · 튜토리얼 · 첫 지역은 청크 0, 뒤 지역은 청크 1 · 2 | 앞 청크만 받고 게임을 시작한다 |
| 고르는 콘텐츠 | 언어별 음성 · 고해상도 그림 | 고른 사람만 받는다 |
| 따로 파는 콘텐츠 | 출시 뒤에 파는 새 지역이나 의상 | 산 사람만 받는다 |
셋째 줄 같은 콘텐츠를 추가 다운로드 콘텐츠라고 부릅니다. 흔히 DLC(Downloadable Content, 내려받는 콘텐츠)라고 줄여 씁니다. 이런 콘텐츠를 청크 하나로 떼어 두면 산 사람의 기기에만 그 청크를 보내면 됩니다.
받으면서 플레이하는 흐름
진행 순서로 나눈 청크는 받는 순서를 정할 수 있습니다. 청크는 게임을 내려받게 해 주는 배포 서버에 올려 둡니다. 받은 청크는 기기 저장소에 쌓입니다.
기기는 청크 0부터 받습니다. 청크 0이 다 오면 게임을 켤 수 있습니다. 나머지 청크는 플레이하는 동안 뒤에서 받습니다.
sequenceDiagram
participant 게임
participant 기기 저장소
participant 배포 서버
배포 서버->>기기 저장소: 청크 0
Note over 게임,기기 저장소: 청크 0이 다 오면 게임을 켤 수 있다
배포 서버->>기기 저장소: 청크 1 · 청크 2를 뒤에서 보낸다
게임->>기기 저장소: 두 번째 지역의 청크 1이 다 왔나
Note over 게임: 아직이면 받는 중 화면을 띄우고 기다린다
기기 저장소-->>게임: 청크 1이 다 있다
게임->>기기 저장소: 청크 1에서 에셋을 읽는다
그림 가운데의 확인이 이 방식의 요점입니다. 게임은 두 번째 지역으로 넘어가기 전에 그 지역의 청크가 다 왔는지 묻습니다. 이 확인이 빠지면 게임이 아직 없는 파일을 열려다 멈춥니다.
이렇게 받으면서 플레이하게 하는 방식을 스트리밍 설치라고 부릅니다. 청킹이 없으면 이 방식도 쓸 수 없습니다. 먼저 받을 덩어리와 나중에 받을 덩어리가 갈라져 있어야 하기 때문입니다.
청크 사이의 의존
에셋은 다른 에셋을 씁니다. 두 번째 지역의 지도는 주인공 3D 모델을 씁니다. 그 모델은 겉에 입힐 그림을 씁니다. 이렇게 한 에셋이 돌아가려면 함께 있어야 하는 다른 에셋을 그 에셋의 의존성이라고 부릅니다.
청킹에서는 의존이 향하는 방향이 중요합니다. 청크 1의 에셋이 청크 0의 에셋을 쓰는 것은 괜찮습니다. 청크 0은 언제나 먼저 와 있기 때문입니다. 거꾸로 청크 0의 에셋이 청크 1의 에셋을 쓰면, 청크 1이 오기 전에는 그 에셋을 열 수 없습니다.
flowchart TD
subgraph c1["청크 1"]
M["두 번째 지역 지도"]
end
subgraph c2["청크 2"]
N["세 번째 지역 지도"]
end
subgraph c0["청크 0"]
H["주인공 모델"]
end
M -->|쓴다| H
N -->|쓴다| H
여러 청크가 함께 쓰는 에셋은 그래서 청크 0으로 끌어올립니다. 위 그림의 주인공 모델이 그렇습니다. 두 번째 지역과 세 번째 지역이 다 쓰는 에셋입니다.
청크 1에 두면 안 되는 까닭은 받는 순서에 있습니다. 청크 1과 청크 2는 둘 다 뒤에서 받으므로 어느 쪽이 먼저 다 올지 정해져 있지 않습니다. 언제나 먼저 와 있다고 믿을 수 있는 청크는 청크 0뿐입니다.
대가는 앞 청크가 무거워진다는 것입니다. 공용 에셋을 계속 끌어올리면 청크 0이 커지고 처음 받을 양이 다시 늘어납니다. 반대로 한 에셋을 두 청크에 한 벌씩 넣으면 의존은 풀립니다. 대신 같은 데이터를 두 번 받게 됩니다.
같은 이름을 쓰는 다른 분야
「청킹」은 게임 밖에서도 흔히 쓰는 이름입니다. 큰 것을 다루기 쉬운 단위로 나눈다는 생각은 같습니다. 나누는 대상과 목적이 분야마다 다릅니다.
| 분야 | 무엇을 나누나 | 왜 나누나 |
|---|---|---|
| 게임 패키징 | 게임 데이터 | 필요한 청크부터, 필요한 사람에게만 보내려고 |
| 웹 프론트엔드 | [[JavaScript | 자바스크립트]] 묶음 |
| 검색 시스템 | 긴 글 | 조각마다 뜻을 담은 숫자 목록을 하나씩 만들려고 |
| HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜) | 응답 본문 | 전체 길이를 모르는 채로 보내기 시작하려고 |
웹 프론트엔드의 코드 분할은 게임 청킹과 목적이 같습니다. 브라우저가 받을 자바스크립트를 파일 여러 개로 나눕니다. 첫 화면에 필요한 파일만 먼저 받습니다. 나머지는 그 화면으로 갈 때 받습니다.
검색 시스템의 청킹은 긴 글을 조각으로 자르는 일입니다. 여기서 쓰는 임베딩은 글의 뜻을 담은 숫자 목록입니다. 뜻이 비슷한 글끼리는 목록도 비슷하게 나옵니다.
시맨틱 검색은 그 목록으로 뜻이 가까운 글을 찾는 검색입니다. 글 하나를 목록 하나로 만들면 여러 주제가 섞여 뜻이 흐려집니다. 그래서 글을 문단 몇 개 크기로 먼저 자릅니다. 목록은 조각마다 하나씩 만듭니다.
이렇게 찾은 조각을 언어 모델에게 건네 답을 쓰게 하는 방식이 검색 증강 생성입니다. 흔히 RAG(Retrieval-Augmented Generation, 검색 증강 생성)라고 줄여 부릅니다. 조각을 어떤 크기로 자르느냐가 찾아지는 조각을 바꿉니다. 그래서 답에도 영향을 줍니다.
HTTP/1.1 에는 청크 전송 인코딩이 있습니다. 서버가 응답 본문을 조각으로 나눕니다. 조각마다 길이를 앞에 붙여 보냅니다. 길이가 0인 조각이 끝을 알립니다.
이 방식은 전체 길이를 몰라도 보내기 시작할 수 있습니다. 그래서 결과를 만들어 가며 바로 흘려보낼 때 씁니다.
대화에서 「청킹」이 나오면 옆에 붙은 말로 뜻을 가릅니다. 에셋이나 설치 이야기면 게임 쪽입니다. 임베딩이나 검색 이야기면 글을 자르는 쪽입니다.
관련 항목
청킹이 들어 있는 게임 빌드 단계
게임 개발 · 에셋 파이프라인 · 쿠킹 · 패키징 · 텍스처 압축 · 빌드 프로파일
청킹이 만드는 파일과 그 구성 요소
청크 · 아카이브 · 에셋 · 매니페스트 · 의존성 · 의존성 그래프
청크를 나눠 보내는 배포 방식
스트리밍 설치 · 추가 다운로드 콘텐츠 · 패치 · 델타 업데이트 · CDN
받은 청크를 실행 중에 읽는 기술
에셋 매니저 · 텍스처 스트리밍 · 레벨 스트리밍 · 지연 로딩 · 비동기 로딩
청킹처럼 큰 데이터를 나눠 다루는 기법
청킹과 이름이 겹치는 다른 분야의 기법
다른 이름: chunking