어떤 프로젝트는 설정에 .json 파일을 쓰고 다른 프로젝트는
.yaml이나 .yml을 쓴다는 걸 눈치채셨을 겁니다. 두 포맷 모두 구조화된 데이터를 표현하고,
둘 다 사람이 읽을 수 있습니다. 그렇다면 실제 차이는 무엇이고, 언제 어떤 것을 선택해야 할까요?
저는 둘 다 광범위하게 사용해 왔습니다 — JSON은 API와 데이터 교환에 일상적으로 쓰고, YAML은 Kubernetes 매니페스트, GitHub Actions, Docker Compose에 즐겨 사용합니다. 비슷한 문제를 해결하지만 성격이 매우 다릅니다.
나란히 비교: 동일한 설정을 두 포맷으로
JSON으로 작성한 데이터베이스 설정 객체입니다:
{
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp",
"ssl": true,
"pool": {
"min": 2,
"max": 10
},
"replicas": ["replica1.db", "replica2.db"]
}
}동일한 설정을 YAML로 작성하면 이렇습니다:
database:
host: localhost
port: 5432
name: myapp
ssl: true
pool:
min: 2
max: 10
replicas:
- replica1.db
- replica2.dbYAML이 눈에 띄게 덜 복잡합니다. 대부분의 문자열에 따옴표가 없고, 중괄호도 없으며, 쉼표도 없습니다. 사람이 자주 편집하는 설정 파일에서 이런 명확함이 쌓입니다. 하지만 YAML은 내부적으로 훨씬 더 복잡합니다.
YAML이 빛나는 부분
- 사람이 편집하는 설정 파일. CI/CD 파이프라인(GitHub Actions, GitLab CI), Kubernetes 매니페스트, Docker Compose, Ansible 플레이북. 모두 YAML입니다. 우연이 아닙니다 — 사람이 직접 작성하는 파일들입니다.
- 주석. YAML은
#으로 주석을 지원합니다. 설정 파일에서 설정값이 존재하는 이유를 설명하고 싶을 때 매우 중요합니다. JSON은 주석을 전혀 지원하지 않습니다. - 멀티라인 문자열. YAML은 자연스럽게 읽히는 블록 스칼라로 멀티라인 콘텐츠를 표현합니다. JSON은
\n이스케이프 시퀀스가 필요합니다. - 시각적 노이즈 감소. 대부분의 문자열에 따옴표가 필요 없고, 닫는 중괄호도 없으며, 후행 쉼표도 신경 쓸 필요가 없습니다.
- 앵커와 앨리어스. YAML은
&anchor와*alias로 값을 한 번 정의하고 다른 곳에서 참조할 수 있습니다 — DRY 설정 파일에 유용합니다.
JSON이 앞서는 부분
- 엄격함. JSON은 주어진 데이터 구조에 대해 하나의 유효한 표현만 있습니다. YAML은 같은 것을 열두 가지 방법으로 쓸 수 있어 팀 내에서 일관성 문제가 생깁니다.
- 들여쓰기 함정 없음. JSON은 중괄호와 대괄호를 사용합니다. YAML은 들여쓰기를 사용하므로 잘못 놓인 공백 하나가 전체 설정을 조용히 망가뜨릴 수 있습니다.
- 파싱 성능. JSON 파서는 빠르고 단순합니다. YAML 파서는 복잡합니다 — YAML 1.1에는 악명 높은 까다로운 암묵적 타입 강제 규칙이 있습니다.
- 범용 라이브러리 지원. 모든 언어에 전투 검증된 제로 의존성 JSON 파서가 있습니다. YAML 라이브러리는 품질과 스펙 준수도가 다양합니다.
- 툴링. 린터, 포매터, 스키마 검증기 — JSON 툴링이 더 성숙하고 널리 사용 가능합니다.
- API 페이로드. JSON은 웹 API의 공용어입니다. HTTP로 YAML을 보내는 것은 관례에 어긋나고 마찰을 일으킵니다.
당신을 태울 YAML의 함정들
YAML에는 실제 프로덕션 사고를 일으킨 진정으로 놀라운 동작들이 있습니다. 대부분은 YAML 1.1의 암묵적 타입 규칙에서 비롯되는데, YAML 1.2에서 개선되었습니다. 중요한 용도로 YAML을 사용하기 전에 이것들을 알아두세요:
NO가
불리언 false로 파싱됩니다. NO(노르웨이) 같은 국가 코드가
조용히 불리언으로 변환됩니다. YAML 1.2에서 수정되었지만 모든 파서가 따라오지 못했습니다.# YAML 1.1 implicit type coercion — all of these become booleans:
enabled: yes # → true
disabled: no # → false
country: NO # → false (!) ← the Norway Problem
# Safe practice: quote strings that look like booleans
country: "NO"
enabled: "yes"- 8진수 정수. YAML 1.1에서
010은10이 아닌8(8진수)로 파싱됩니다. 파일 권한 같은 것에 영향을 줍니다. - 탭 vs 공백. YAML은 들여쓰기에 탭을 금지합니다. 코드 에디터에서 탭 하나가 섞이면 파일이 조용히 또는 불가사의한 오류와 함께 깨집니다.
- 암묵적 null. YAML에서 빈 값은 null이 됩니다. 직접 편집할 때 놓치기 쉽습니다.
- 문자열 vs 숫자 모호성.
port: 8080은 정수를 줍니다.version: 1.0은 float을 줄 수 있습니다. 때로는 문자열"1.0"이 필요합니다. 중요할 때는 항상 따옴표를 사용하세요.
실용적인 결정 가이드
YAML을 선택하세요:
- 사람이 직접 편집하는 설정 파일 작성 시: CI/CD, Kubernetes, Docker Compose, Ansible
- 설정값을 설명하는 주석이 파일에 필요할 때
- 멀티라인 문자열 값이 많을 때
- 이미 YAML을 사용하는 에코시스템에서 작업할 때 (관례에 맞서지 마세요)
JSON을 선택하세요:
- API로 데이터를 보내거나 받을 때
- 데이터가 프로그래밍 방식으로 생성되고 소비될 때 (사람이 편집하지 않음)
- 다양한 도구와 언어에서 일관된 파싱을 보장해야 할 때
- JSON을 표준으로 사용하는 에코시스템에서 작업할 때: npm(package.json), VS Code(settings.json), Angular, TypeScript
두 포맷 사이 변환하기
YAML 설정을 YAML을 지원하지 않는 도구를 위해 JSON으로 변환해야 하나요? YAML to JSON 변환기를 사용하세요. 반대 방향이라면? JSON to YAML 변환기가 처리해 드립니다. YAML 포매터는 정렬이 흐트러진 YAML을 붙여넣을 때도 유용합니다. YAML이 파싱되지 않는다면 YAML 검증기가 문제가 있는 정확한 위치를 알려줄 것입니다.
결론
JSON과 YAML은 경쟁 관계가 아니라 상호 보완적입니다. 데이터 교환에는 JSON을 — API, 프로그래밍 방식
데이터 저장, 직렬화. 사람이 읽고 편집하는 설정 파일에는 YAML을. 성숙한 대부분의 프로젝트는
둘 다 사용합니다: 의존성에는 package.json, CI에는 .github/workflows/*.yml.
각 포맷이 무엇에 최적화되어 있는지 이해하면 선택이 자연스럽게 명확해집니다.