Depth는 실행 중인 Minecraft 서버를 중계하는 화면이 아닙니다. 특정 시점의 오프라인 월드 백업을 읽어 블록, 조명, 재질과 카메라 표현을 자기완결형 정적 웹 아카이브로 발행합니다. 서버가 멈추거나 원본 월드가 바뀌어도 같은 자산과 같은 주소로 당시 도시를 다시 열 수 있습니다.
먼저 알아둘 결론
이번 사례의 원본은 2026년 7월 1일 03시 전체 월간 백업입니다. X 13,444~14,673, Z -7,414~-6,780의 범위를 잘라 3,198개 청크로 읽었고 누락은 없었습니다. 3,041개 block state와 3,001개 재질 연결을 하나의 palette와 atlas로 정리해 브라우저가 반복해서 해석할 일을 발행 단계로 옮겼습니다.
| 원본 | 2026-07-01 03:00 KST 오프라인 전체 월간 백업 |
|---|---|
| 공간 범위 | 1,230 × 635블록 · Y -64~320 |
| 청크 | 3,198 / 3,198 · 누락 0 |
| 비공기 블록 | 85,765,828 |
| 현재 정적 탑재량 | 3,258파일 · 22,597,463바이트 · 21.551 MiB |
월드에서 웹까지 무엇이 바뀌는가
핵심은 원본을 복사하는 것이 아니라 브라우저가 바로 그릴 수 있는 표현으로 바꾸는 일입니다. 먼저 전체 백업으로 시점을 고정하고 좌표 범위를 청크 경계로 확장합니다. 각 청크의 block state는 전역 palette의 정수로, 조명은 block light와 sky light로 저장합니다. 리소스 팩과 client JAR에서 찾은 텍스처와 모델 면은 atlas와 사전 계산된 quad가 됩니다.
표현 변환 파이프라인
운영 월드와 분리된 발행물을 만듭니다
무거운 파싱과 재질 해석은 오프라인에서 끝냅니다. 공개 서버는 완성된 파일을 전달하고, 브라우저는 그 파일을 풀어 화면에 그립니다.
- 01시점 고정실행 중인 서버 대신 완결된 월간 백업을 읽어 모든 청크의 기준 시점을 맞춥니다.
- 02영역 절단요청 좌표를 포함하는 78 × 41개 청크를 선택하고 누락 여부를 검사합니다.
- 03상태 정규화반복되는 block state를 전역 palette 번호로 치환하고 조명 배열을 보존합니다.
- 04재질 사전 계산texture atlas를 만들고 block model의 보이는 면을 브라우저용 quad로 준비합니다.
- 05정적 계약 발행DEPTHSNAP에 공간 데이터를, DEPTHSITE에 제목·시작 화면·투어를 기록합니다.
- 06브라우저 재생WebGL2가 필요한 청크를 메시로 만들고 카메라·조명·후처리를 적용합니다.
| 계약 | 담는 것 | 변경 단위 |
|---|---|---|
| DEPTHSNAP v1 | bounds, 청크 목록, palette, 블록·조명 데이터, atlas | 월드 스냅샷을 다시 만들 때 |
| DEPTHROWPACK v1 | 같은 Z행 청크를 묶은 전송용 gzip archive와 hash | 청크 전송 구조를 다시 만들 때 |
| DEPTHSITE v1 | 프로젝트 이름, 시작 모드·시각, 카메라 투어 | 보여 주는 방식만 바꿀 때 |
3,198개 청크를 41개 행으로 전달합니다
Minecraft 청크 한 변은 16블록입니다. 좌표의 양 끝을 포함하도록 청크 번호를 구하면 X방향 78개, Z방향 41개가 되고 둘을 곱한 3,198개가 캡처 대상입니다. 이 계산 결과는 manifest의 청크 목록과 실제 파일 수가 모두 같아야 통과합니다.
chunks_x = floor(14,673 / 16) - floor(13,444 / 16) + 1 = 78
chunks_z = floor(-6,780 / 16) - floor(-7,414 / 16) + 1 = 41
total_chunks = 78 × 41 = 3,198
파일을 청크마다 요청하면 공간을 열기 위해 최대 3,198회의 개별 요청이 필요합니다. Depth는 같은 Z행의 78개 청크를 하나의 행 팩으로 묶습니다. 색인 1개와 행 팩 41개, 모두 42개 요청으로 같은 청크를 전달할 수 있어 요청 수가 98.7% 줄어듭니다. 행 팩이 없거나 해제에 실패하면 남겨 둔 개별 파일로 돌아갑니다.
전송 요청 비교
행 팩은 저장량보다 요청 수를 줄이는 장치입니다
막대는 개별 청크 방식 3,198회를 100으로 둔 상대값입니다. 실제 전송은 카메라와 투어 순서에 따라 점진적으로 일어납니다.
개별 청크 파일
행 팩 색인 + 41개 행
| 항목 | 값 | 해석 |
|---|---|---|
| 행 팩 압축 데이터 | 6,315,792바이트 | 41개 행 파일의 gzip 크기 합 |
| 전체 행 해제 크기 | 271,684,790바이트 | 모든 행을 동시에 유지하지 않음 |
| 최대 3행 원시 창 | 25,136,002바이트 · 9.3% | 앞·현재·뒤 행만 원시 상태로 유지 |
| 초기 준비 청크 | 최대 15개 | 첫 화면 또는 투어 진행축 주변부터 메시 생성 |
큰 도시를 안정적으로 그리는 방법
월드 좌표를 그대로 GPU 정점에 반복해서 넣으면 원점에서 멀수록 부동소수점 정밀도 문제가 커집니다. Depth는 정점을 청크 안의 작은 좌표로 두고 청크 원점을 별도로 전달합니다. 카메라 계산은 월드 위치를 유지하면서 실제 정점 버퍼는 작은 수를 사용합니다.
position_world = position_chunk_local + origin_chunk
visible(mesh) = sphereVisible(camera_frustum, mesh.center, mesh.radius)
draw = visible opaque meshes → visible blended meshes
| 문제 | 선택 | 효과 |
|---|---|---|
| 큰 월드 좌표 | 청크 로컬 정점 + 별도 origin | 정점 수치를 작게 유지해 화면 떨림 위험을 낮춤 |
| 화면 밖 청크 | 청크 구체와 카메라 절두체 비교 | 보이지 않는 mesh의 draw call을 생략 |
| 투명 재질 | opaque와 blended mesh 분리 | 불투명 장면 뒤에 투명 장면을 별도로 합성 |
| 넓은 그림자 범위 | 2,048² shadow map 3단계 | 카메라 거리별로 그림자 해상도를 나눔 |
| 낮과 밤의 대비 | HDR RGBA16F, bloom, FXAA, ACES 근사 | 하늘빛과 block light를 분리하고 최종 화면 범위로 변환 |
모바일에서는 백그라운드 메시 생성 중 해상도와 그림자·bloom을 잠시 줄이고, 각 작업 묶음 뒤 입력과 렌더링 기회를 돌려줍니다. 숨겨진 탭에서는 행 해제와 메시 생성을 멈춥니다. 이는 최종 화질을 고정하는 설정이 아니라, 첫 화면과 조작 응답을 먼저 확보하기 위한 진행 순서입니다.
자동 순회 대신 60초 도시 서사를 기록합니다
스냅샷이 같아도 어디서 시작해 무엇을 보여 줄지는 별개의 문제입니다. 초기 자동 경로는 184.1초 동안 남북 경계를 오가며 내아거리의 주 도로와 무관한 회전·상승을 포함했습니다. 현재 `site.json`에는 10개 경유점을 두어 서측 진입, 간선도로 저공 이동, 중심부 상승, 전체 전경의 순서로 60.2초 경로를 고정했습니다.
투어 길이와 구성
짧아진 시간보다 경로의 목적이 중요합니다
내아거리 편집 경로는 자동 경로의 약 32.7% 길이입니다. 비교의 목적은 속도가 아니라 건물 내부와 빈 월드를 피하며 거리의 구조를 순서대로 보여 주는 것입니다.
내아거리 일반 자동 경로
황룡사 참고 경로
내아거리 10개 경유점
투어가 코드가 아니라 데이터인 덕분에 viewer와 스냅샷을 다시 만들지 않고도 경로만 검토할 수 있습니다. 발행 검사는 site id, 경유점 수, 카메라·주시점·FOV·시각의 유한값, 카메라 X/Z가 snapshot bounds 안에 있는지를 확인합니다.
재현 가능한 것과 아직 말할 수 없는 것
보고서 작성 시점에 운영 파일과 공개 응답을 다시 내려받아 `site.json`, manifest와 행 팩 색인의 SHA-256을 비교했습니다. 세 파일은 각각 일치했고 공개 프로젝트와 viewer는 HTTP 200을 반환했습니다. 운영 스냅샷은 3,198개 청크, 누락 0, 3,041개 palette, 85,765,828개 비공기 블록에 합의합니다.
| 파일 | SHA-256 |
|---|---|
| site.json | 3ba7e768b96731d96e9546d54e7f20057a476d53f2abfd2fcec5df5417f60cc7 |
| manifest.json | ca3c7ad08740e405ec228d8c445676acfd9e1975f42a93ae8ee0857824e361f2 |
| 행 팩 index.json | cce35979c03e267673b15dde8c64f168dfb6187c77b08dc052dba43b4aea23ea |
이 검증이 보장하지 않는 범위도 분명합니다.
- 스냅샷은 2026년 7월 1일의 도시입니다. 이후 건축 변경이나 이용자 활동을 실시간으로 반영하지 않습니다.
- 22.60 MB는 정적 탑재량입니다. 최초 화면의 네트워크 전송량이나 원본 월드 대비 압축률이 아닙니다.
- block entity, biome와 애니메이션 등 원본 표현의 보존률은 이번 보고서에서 완전성을 검증하지 않았습니다.
- WebGL 결과는 Minecraft 게임 렌더러의 픽셀 단위 복제가 아닙니다. atlas, 조명과 후처리로 다시 구성한 브라우저 표현입니다.
- 실제 로딩 시간과 프레임률은 네트워크, 브라우저와 GPU에 따라 달라집니다. 소프트웨어 WebGL 측정값을 사용자 성능으로 일반화하지 않습니다.
- hash는 이번 검증 시점의 근거입니다. 자산이 갱신되면 manifest 수치와 함께 다시 측정해야 합니다.