Skip to content

가이드

YAML 1.1과 1.2

가장 비싼 대가를 치른 YAML 버그의 중심에는 국가 코드가 있습니다.

작성 yamltojsonfree · 게시일 · 수정일

Norway 문제란

YAML 1.1에서 따옴표 없는 y, yes, on, n, no, off는 불리언입니다 — 대문자든 소문자든 첫 글자만 대문자든. 그래서 노르웨이(NO)가 포함된 국가 코드 목록은 조용히 false가 됩니다. 아무 오류도 나지 않습니다. 문서는 파싱되고, 배포는 성공하며, 어딘가 하류에서 "불리언은 딕셔너리 키가 될 수 없고 문자열 비교에도 맞지 않는다"는 이유로 목록에서 나라 하나가 사라집니다.

2009년에 발표된 YAML 1.2는 이를 없앴습니다. 불리언은 true와 false뿐이고, 저 여섯 단어는 일반 문자열입니다. YAML 1.1의 다른 암시적 변환도 버렸습니다 — 022는 더 이상 18을 뜻하는 8진수가 아니고, 12:30은 더 이상 750을 뜻하는 60진수가 아닙니다.

문제는 15년이 넘게 지난 지금도 두 버전이 널리 쓰인다는 것입니다. 같은 파일이 여는 도구에 따라 두 가지 다른 의미를 가질 수 있습니다 — 바로 그래서 이 사이트의 YAML → JSON 변환기는 기본적으로 YAML 1.2를 사용하고, 1.1에서 다르게 읽힐 문서 내 모든 값을 표시합니다.

의미가 바뀌는 모든 값

같은 원본을 명세의 각 버전으로 읽은 결과.

YAML 원본YAML 1.2 해석YAML 1.1 해석안전한 형태
country: NO"NO"falsecountry: "NO"
enabled: yes"yes"trueenabled: true
debug: off"off"falsedebug: false
mode: 0222218mode: "022"
start: 12:30"12:30"750start: "12:30"
version: 1.101.11.1version: "1.10"

마지막 줄에 주목하세요. 1.10은 숫자로 파싱되기 때문에 두 버전 모두에서 끝의 0을 잃습니다. 버전 문자열은 항상 따옴표로 감싸야 합니다.

어떤 파서가 어떤 버전을 읽는가

YAML 버전을 직접 고르는 일은 거의 없습니다 — 사용하는 도구가 의존하는 라이브러리에서 물려받습니다. 생태계는 대략 다음과 같이 나뉩니다:

파서버전비고
PyYAML (Python)YAML 1.1Ansible을 포함한 대부분의 Python 도구의 기본값.
ruamel.yaml (Python)YAML 1.2유지 관리되는 PyYAML의 후속. 옵션으로 1.1 가능.
js-yaml v5 (JavaScript)YAML 1.2이 사이트가 사용하는 엔진. 이전 버전은 1.1을 읽었음.
go-yaml / sigs.k8s.io (Go)대부분 1.2Kubernetes가 사용. 호환성을 위해 일부 1.1 동작 유지.
SnakeYAML (Java)YAML 1.1Spring Boot 설정 로딩의 기본값.
libyaml (C bindings)YAML 1.1PyYAML을 포함한 많은 언어 바인딩의 기반.

실무적인 결과: 이 표의 한쪽에서 작성되고 다른 쪽에서 읽히는 파일은 값이 조용히 바뀔 수 있습니다. YAML을 Python으로 생성하고 Kubernetes가 소비한다면 — 아주 흔한 파이프라인입니다 — 버전 경계를 넘는 것입니다. 코드 수준의 자세한 내용은 코드로 YAML을 JSON으로 변환하기 가이드에 있습니다.

두 버전 모두에서 안전한 YAML 작성법

세 가지 습관이 이런 종류의 버그를 통째로 없앱니다. 다른 것으로 오해될 수 있는 모든 문자열을 따옴표로 감싸세요 — 국가 코드, 버전 번호, 앞에 0이 붙는 값, 콜론이 들어간 모든 것. 불리언은 true와 false로만 쓰고 yes, on이나 그 유사어는 절대 쓰지 마세요. 그리고 파일이 도구 사이를 오가기 전에 버전에 따라 달라지는 값을 보고하는 변환기나 검증기를 거치게 하세요 — YAML을 명시적인 JSON으로 보는 것이 의도하지 않은 타입을 잡아내는 가장 빠른 방법입니다.

참고 자료

내 YAML 확인하기

위 표의 모든 값은 이 사이트의 변환기와 검증기가 각 버전의 해석 결과와 함께 표시합니다. 어떤 것도 업로드되지 않습니다.