Minecraft Bedrock Edition과 Java Edition을 지원합니다. Vanilla, Paper, Spigot, Purpur, Folia, Fabric, Forge, NeoForge, Mohist, Sponge, Bedrock Dedicated Server, PocketMine-MP, Nukkit, PowerNukkitX, Cloudburst, Dragonfly, Endstone, LeviLamina 등 유명하거나 잘 알려지지 않은 양쪽 에디션의 모든 서버 코어를 지원합니다. 전체 목록
NBT(Named Binary Tag)는 Minecraft의 바이너리 트리 형식입니다. 태그는 1바이트 유형, 길이 접두사가 붙은 이름, 페이로드로 구성되며 compound는 TAG_End 바이트가 닫을 때까지 중첩됩니다. Java와 Bedrock에서 사용되는 태그 유형은 13개, 인코딩은 5개입니다. 이 페이지에서 모두 설명하며 위 편집기로 실제 파일을 열어 각 내용을 확인할 수 있습니다.
파일은 하나의 루트 TAG_Compound입니다. 유형 byte 0x0A 하나, 이름, compound 내용 순서로 구성됩니다. 이름 있는 태그는 compound 안에서만 나옵니다. list 요소에는 페이로드만 들어가므로 list의 모든 요소는 같은 유형입니다.
실제로 쓰이는 다섯 가지 인코딩
인코딩
정수
문자열 길이
루트
사용처
Java(클래식)
고정 폭 빅 엔디언
2바이트 빅 엔디언
이름 있음
Java 월드, 구조물, schematic
Java 네트워크(1.20.2+)
고정 폭 빅 엔디언
2바이트 빅 엔디언
이름 없음
Java 프로토콜
Bedrock
고정 폭 리틀 엔디언
2바이트 리틀 엔디언
이름 있음
Bedrock 월드, .mcstructure, LevelDB 값
Bedrock level.dat
고정 폭 리틀 엔디언
2바이트 리틀 엔디언
8바이트 헤더 뒤에 이름 있음
Bedrock 월드 메타데이터
Bedrock 네트워크
int와 long에 zigzag varint
unsigned varint
이름 있음
Bedrock 프로토콜
varint 인코딩에서도 TAG_Short, TAG_Float, TAG_Double은 고정 폭 리틀 엔디언을 유지합니다. TAG_Int와 TAG_Long만 zigzag varint가 되며 배열과 list 길이는 TAG_Int의 방식을 따릅니다. 문자열 길이는 unsigned varint라서 고정 폭 인코딩의 65535바이트 제한도 사라집니다.
문자열: 수정된 UTF-8과 UTF-8
Java는 DataOutputStream.writeUTF로 문자열을 직렬화합니다. 이는 수정된 UTF-8입니다. NUL 문자는 C0 80 대신 00으로 기록하고, 기본 다국어 평면 밖 문자는 하나의 4바이트 시퀀스 대신 두 개의 3바이트 surrogate 절반(CESU-8)으로 기록합니다. Bedrock은 표준 UTF-8을 사용합니다. 두 형식에 같은 인코딩을 적용하는 도구는 저장할 때 이모지와 일부 CJK 텍스트를 손상합니다. 이 편집기는 형식별로 올바르게 인코딩하므로 이모지가 들어간 월드 이름도 왕복 과정에서 유지됩니다.
압축
NBT 자체는 압축되지 않으며 컨테이너가 방식을 정합니다. Java 파일은 보통 gzip(magic 1F 8B), 리전 파일 안의 청크 페이로드는 zlib(magic 78 01, 78 9C 또는 78 DA)을 사용합니다. Bedrock의 level.dat와 구조물 파일은 압축하지 않습니다. magic byte로 감지하므로 같은 파서가 세 방식을 모두 처리합니다. 잘못된 압축으로 저장하는 일은 수동 편집한 월드가 열리지 않는 가장 흔한 원인입니다.
최소 파일을 바이트별로 보기
표준 예제 hello_world.nbt입니다. hello world라는 루트 compound에 값이 name인 string 태그 Bananrama 하나가 들어 있습니다. Java 빅 엔디언 인코딩은 다음과 같습니다.
0A TAG_Compound
00 0B 68 65 6C 6C 6F 20 77 6F 72 6C 64 name length 11, "hello world"
08 TAG_String
00 04 6E 61 6D 65 name length 4, "name"
00 09 42 61 6E 61 6E 72 61 6D 61 value length 9, "Bananrama"
00 TAG_End
같은 문서를 Bedrock 리틀 엔디언으로 인코딩하면 두 길이 필드의 바이트 순서만 달라집니다. 0B 00 대신 00 0B입니다. Bedrock 네트워크 NBT에서는 길이가 패딩 없는 단일 varint byte 0B와 04가 됩니다. 셋 중 어떤 파일이든 위 편집기에 놓으면 받은 형식을 알려줍니다.
SNBT
SNBT는 NBT를 텍스트로 기록한 형식이며 명령어가 사용합니다. 예: /data merge entity @s {Invulnerable:1b}. 유형 접미사 덕분에 정보를 잃지 않습니다. b는 byte, s는 short, L은 long, f는 float, d는 double이고 int에는 접미사가 없습니다. 유형 배열 리터럴은 [B;…], [I;…], [L;…]로 씁니다. 편집기는 불러온 모든 파일을 SNBT로 내보내므로 일반 텍스트 비교 도구에서 두 월드 버전을 비교할 수 있습니다.
자주 묻는 질문
공식 NBT 명세가 있나요?
Mojang이 발표한 정식 명세는 없습니다. Notch가 2010년에 형식을 문서화한 뒤 커뮤니티에서 유지해 왔습니다. 이 페이지의 태그 ID와 구조는 현재 게임이 읽고 쓰는 방식과 일치합니다.
Bedrock이 리틀 엔디언을 사용하는 이유는 무엇인가요?
Bedrock 엔진은 C++로 작성되었고 리틀 엔디언 하드웨어를 대상으로 하므로 값을 기본 바이트 순서로 저장합니다. Java 직렬화는 Java DataOutput 계약에 따라 빅 엔디언을 사용합니다.
zigzag varint 인코딩이 무엇인가요?
음수를 짧게 유지하면서 정수를 가능한 적은 바이트로 기록하는 방식입니다. 부호를 최하위 비트에 접어 넣으므로 −1은 1로, 1은 2로 인코딩됩니다. Bedrock 프로토콜은 int와 long에 이 방식을 씁니다.
TAG_List에 서로 다른 유형을 넣을 수 있나요?
아니요. list는 요소 유형 하나를 선언하고 모든 항목이 그 유형과 일치해야 합니다. 서로 다른 데이터를 넣으려면 compound list를 사용하세요.
문자열 최대 길이는 얼마인가요?
길이 필드가 unsigned short인 고정 폭 인코딩에서는 65535바이트입니다. varint 네트워크 인코딩에는 실질적인 제한이 없습니다.