Kubernetes 는 YAML, Cargo (Rust) 는 TOML, package.json 은 JSON, legacy 데스크탑 앱은 INI, Maven 은 XML. 같은 "설정" 인데 왜 이렇게 다양할까? 각 포맷의 강점·약점·함정·언제 무엇을 고르는지 정리한다.
5 가지 포맷 — 첫 인상
JSON
{
"name": "yutils",
"version": "0.1.0",
"tools": 66
}YAML
name: yutils
version: 0.1.0
tools: 66TOML
name = "yutils"
version = "0.1.0"
tools = 66XML
<project>
<name>yutils</name>
<version>0.1.0</version>
<tools>66</tools>
</project>INI
[project]
name = yutils
version = 0.1.0
tools = 66JSON — 기계 친화, 사람 적당
장점:
- RFC 8259 표준 (2017), 모든 언어 기본 지원
- JavaScript 와 직접 호환 (이름의 J)
- 구조 명확 — object / array / string / number / boolean / null
- 파서 단순 (100 라인 안)
단점:
- 주석 X — Crockford 의 의도 "config 가 아닌 data 교환용" 명시. 그러나 실제로는 config 로 자주 사용 → 주석 못 다는 불편
- trailing comma 금지 — diff 가 깨짐
- 중복 키 정의 X (파서마다 동작 다름)
- IEEE 754 한계 — 큰 정수 정밀도 손실 (
how-json-parsing-works가이드 참조)
파생 — JSON5 / JSONC:
- JSON5 (Mike Bostock) — 주석 + trailing comma + hex 숫자 허용
- JSONC (Microsoft) — 주석 + trailing comma만 (
tsconfig.json)
용도 — API 응답 (네트워크 직렬화), npm package.json, JSON Schema
YAML — 사람 친화, 함정 다수
장점:
- 들여쓰기로 구조 표현 → 시각적 가독성 ↑
- 주석 (
#) 지원 - JSON 의 superset — JSON 도 valid YAML
- 다중 문서 (
---) — Kubernetes 의 multi-resource 사용 - anchor + alias (DRY)
유명한 함정 — Norway 버그
countries:
- GB
- NO ← Norway? 아니다, NO 는 false!
- SE
# YAML 1.1: NO 가 boolean false 로 파싱YAML 1.1 의 7 가지 boolean 표기:
true: yes, Yes, YES, true, True, TRUE, on, On, ON
false: no, No, NO, false, False, FALSE, off, Off, OFFNorway, Sweden 의 ISO 코드 NO/SE 가 boolean 으로 잘못 해석. 명시적 quote 필요 ("NO"). YAML 1.2 (2009) 에서 true/false 만 boolean 으로 줄였지만 많은 파서가 여전히 1.1 모드.
더 함정
# 16 진수 같은 8-digit string 이 number 로 해석
version: 1.10 ← float 1.1 ("0" 손실)
mac: 00:01:02 ← sexagesimal (base-60) 으로 해석
# 들여쓰기 mix
items:
- one
- two ← 3 space, 다른 list 로 인식
# null 의 함정
key: ← value 가 null (의도: 빈 string?)
key: "" ← 명시 빈 stringYAML 의 "사람 친화" 가 묘하게 "사람을 함정에 빠뜨림". Kubernetes / Docker / Ansible 사용자라면 익숙.
용도 — Kubernetes manifest, GitHub Actions, Ansible playbook, Docker Compose
디버깅 — YAML ↔ JSON 변환 로 JSON 변환 해 확인. boolean / number 으로 잘못 파싱된 값이 즉시 보임.
TOML — Tom 의 양심적 설정
Tom Preston-Werner (GitHub 공동창업자) 가 2013 년 발표. "YAML 의 함정 없이 INI 보다 강한 타입 시스템".
title = "My Project"
[database]
server = "192.168.1.1"
ports = [8001, 8001, 8002]
connection_max = 5000
enabled = true
[servers]
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"장점:
- 명시적 타입 — string은
""강제, boolean 만true/false, datetime 은 RFC 3339 - 주석 (
#) 지원 - 섹션 (
[section]) — INI 호환 느낌 - nested table (
[a.b.c]) — 깊은 구조 가능 - YAML 의 함정 0
단점:
- 깊은 중첩이 길어짐 (XML 만큼)
- JSON / YAML 만큼 ubiquitous X
용도 — Cargo (Rust), Poetry (Python), Hugo, Caddy. TOML ↔ JSON 로 JSON 변환 가능.
XML — 강력하지만 verbose
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>장점:
- XML Schema (XSD) 으로 strict validation
- namespace — 다른 schema 의 element 혼합 가능
- attribute vs element 구분 (메타데이터 vs 콘텐츠)
- XSLT / XPath 같은 강력한 변환·query 언어
- self-describing — 태그가 의미 표현
단점:
- 매우 verbose — 같은 데이터에 JSON 의 3-5 배 크기
- attribute vs child 선택의 모호함 (
<port>8080</port>vs<server port="8080"/>?) - XXE attack (XML External Entity) — 외부 entity 참조로 파일 시스템 노출 가능
- 주석은 있지만 attribute 안엔 못 박음
XXE 예시:
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root>&xxe;</root>
<!-- 파서가 entity expand → /etc/passwd 노출 -->파서마다 external entity 기본 disable 여부 다름. Spring / Jackson XML 의 옛 버전이 자주 취약했음.
용도 — Maven (pom.xml), Android resource, RSS / Atom feed, SOAP, SVG, MS Office (docx 의 내부도 XML). XML 포매터 / XML ↔ JSON.
INI — 90 년대 표준, 비표준
[Database]
Server=192.168.1.1
Port=5432
Enabled=true
# 주석 (또는 ; 사용)
[Logging]
Level=info
File=/var/log/app.log장점:
- 단순 — 30 분 안에 파서 만들 수 있음
- 섹션으로 그룹화
- Windows 의 INI 파일 / .gitconfig / php.ini / systemd unit
단점:
- 표준 없음 — 파서마다 quote 처리, escape, nested section 동작 다름
- nested 구조 X (또는
.또는:으로 편법) - array 표현 X
- type 인식 X — 모두 string, 사용자가 변환
용도 — legacy Windows config, .gitconfig, php.ini, systemd unit files, MySQL my.cnf. INI ↔ JSON.
매트릭스 비교
| JSON | YAML | TOML | XML | INI | |
|---|---|---|---|---|---|
| 주석 | ❌ | ✅ (#) | ✅ (#) | ✅ (<!---->) | ✅ |
| 중첩 | ✅ 무제한 | ✅ 무제한 | ✅ 무제한 | ✅ 무제한 | 1 단계 (편법으로 더) |
| 배열 | ✅ | ✅ | ✅ | 반복 element | ❌ |
| 타입 | 5 종 | 유동적 (함정) | 명시 7 종 + datetime | 모두 string + XSD | 모두 string |
| 표준 | RFC 8259 | YAML 1.2 | TOML 1.0 | W3C XML 1.0 | 비표준 |
| 크기 (같은 데이터) | 1.0× | 0.7× | 0.8× | 3.0× | 0.6× |
| schema | JSON Schema | JSON Schema 호환 | X | XSD / Relax NG | X |
| 다중 문서 | X | ✅ (---) | X | X | X |
언제 어떤 포맷
- API 응답 / 네트워크 직렬화 — JSON. 모든 언어 기본 지원, 작은 크기.
- Kubernetes / GitHub Actions / Ansible — YAML. ecosystem 표준. 함정 조심.
- Rust Cargo / Python Poetry / Hugo — TOML. 개발자 도구의 깔끔한 default.
- Maven / Android resource / RSS / SOAP — XML. legacy + schema validation 강한 곳.
- Windows config / systemd / .gitconfig — INI. 단순.
- 새 프로젝트 default:
- 구조 깊고 사용자 편집 자주 — TOML
- YAML 생태계 (k8s/ansible) — YAML
- API/저장 — JSON
- 주석이 절대 필요한 config — JSON 피하고 YAML 또는 TOML
흔한 함정
1. YAML 의 들여쓰기 mix
tab vs space 혼용 — 일부 파서가 silently 다른 트리 만듦. tab 금지가 spec.
2. JSON 주석 박기
// 이거 안 됨
{
"name": "x",
// 설명
"value": 1
}tsconfig.json 의 주석은 VS Code 의 JSONC 모드. 표준 JSON 파서는 에러.
3. TOML 의 datetime 타입 오해
# Offset datetime (UTC 정보 있음)
date1 = 1979-05-27T07:32:00Z
# Local datetime (offset 없음)
date2 = 1979-05-27T07:32:00
# Local date
date3 = 1979-05-27TOML 의 datetime 4 type 이 명시. JSON 으로 변환하면 string 으로 flat 됨 — 정보 손실 가능.
4. XML 의 entity 폭탄
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
]>
<root>&lol3;</root>
<!-- 1억 글자로 expand → DoS -->"billion laughs" attack. 모던 파서 default 로 entity 제한.
5. INI 의 escape 가정
파서 A: key=value with = sign → value = "value with = sign". 파서 B: 첫 = 만 인식 → 같은 결과. 파서 C: escape 없으면 에러. quote 필요한가? 표준 없으므로 라이브러리별 다름.
참고 자료
- JSON RFC 8259 — datatracker
- YAML 1.2 spec — yaml.org
- TOML spec — toml.io
- The Norway Problem — bram.us
- XXE attack — OWASP
요약
- JSON = data 교환 표준. 주석 / trailing comma X. 가장 ubiquitous.
- YAML = 사람 친화 + 함정 다수 (Norway 버그, 들여쓰기, type coerce). k8s/CI 표준.
- TOML = YAML 의 함정 없이 명시적 타입. Rust/Python 도구 default.
- XML = verbose + 강한 schema (XSD). XXE attack 주의.
- INI = 단순 + 비표준. legacy 시스템.
- 포맷 선택 = ecosystem (어떤 도구가 read?) + 사용자 (사람 vs 기계) + 복잡도 (nested vs flat).
- 변환 — YAML ↔ JSON 변환 / TOML ↔ JSON / XML ↔ JSON 로 JSON 으로 통일해 디버깅. INI ↔ JSON / XML 포매터 / JSON 포매터 / 검증기.