YAML이 값을 마음대로 바꿀 때
country에 NO를 적으면 false가 됩니다. 같은 파일을 파서마다 다르게 읽는 이유와 따옴표를 붙여야 할 자리를 정리했습니다.
국가 코드 목록에 노르웨이를 넣었더니 그 항목만 값이 사라지는 경우가 있습니다. NO가 문자열이 아니라 불리언 false로 읽혔기 때문입니다. YAML에서는 따옴표 없이 적은 값의 타입을 파서가 추론하는데, 그 규칙이 생각보다 넓습니다.
같은 파일이 파서마다 다르게 읽힌다
문제를 키우는 것은 이 추론 규칙이 YAML 1.1과 1.2에서 다르다는 점입니다. 다음 파일을 두 버전으로 읽어 보면 결과가 이렇게 갈립니다.
country: NO
enabled: no
answer: yes
version: 1.10
port: 022
time: 12:30
sha: 0x1f
| 적은 값 | YAML 1.1 | YAML 1.2 |
|---|---|---|
NO |
false |
"NO" |
no |
false |
"no" |
yes |
true |
"yes" |
1.10 |
1.1 |
1.1 |
022 |
18 (8진수) |
22 |
12:30 |
750 (60진수) |
"12:30" |
0x1f |
31 |
31 |
1.1에서 12:30이 750이 되는 것은 시분초를 60진수로 해석하기 때문입니다. 12×60+30입니다. 022는 8진수로 읽혀 18이 됩니다.
1.2에서 yes/no 계열이 문자열로 남게 바뀌었지만, 여전히 1.1을 구현한 파서가 널리 쓰입니다.
- PyYAML — YAML 1.1입니다. 파이썬으로 설정을 읽는 도구 상당수가 여기에 해당합니다
- js-yaml, yaml (JS) — 기본이 1.2입니다
그래서 같은 설정 파일을 파이썬 스크립트와 노드 도구가 서로 다르게 읽는 상황이 생깁니다. 어느 쪽도 오류를 내지 않습니다. 값만 다릅니다.
대응은 따옴표
규칙을 외우는 것보다 확실합니다. 문자열로 다뤄야 하는 값에는 따옴표를 붙입니다.
country: "NO"
version: "1.10"
port: "022"
time: "12:30"
특히 다음은 따옴표를 기본으로 두는 편이 안전합니다.
- 국가·언어 코드 (
NO,ON) - 버전 번호 (
1.10은 따옴표가 없으면1.1이 됩니다) - 앞에 0이 붙는 값 — 우편번호, 계좌번호, 전화번호
- 시각 표기 (
12:30) - 커밋 해시처럼
0x나0b로 시작할 수 있는 값 - 아주 긴 숫자 — 부동소수점 정밀도 문제가 그대로 적용됩니다
작은따옴표와 큰따옴표는 이스케이프 처리가 다릅니다. 큰따옴표 안에서는 \n이 줄바꿈으로 해석되고, 작은따옴표 안에서는 글자 그대로 남습니다. 정규식이나 윈도 경로를 적을 때는 작은따옴표가 편합니다.
그 외에 걸리는 것들
탭은 들여쓰기에 쓸 수 없습니다. 공백만 허용됩니다. 편집기가 탭을 넣으면 파싱이 실패합니다.
여러 줄 문자열은 세 가지가 다릅니다.
literal: |
줄바꿈이 그대로 유지됩니다
이 줄도 별도 줄입니다
folded: >
줄바꿈이 공백으로 합쳐집니다
한 줄이 됩니다
strip: |-
마지막 줄바꿈을 제거합니다
|는 개행을 보존하고 >는 공백으로 접습니다. 뒤에 붙는 -는 끝의 개행을 지우고, +는 남깁니다. 스크립트나 인증서를 넣을 때는 |를 씁니다.
빈 값은 null입니다. key:만 적으면 값은 null이 됩니다. ~도 null이고, ""는 빈 문자열입니다. 셋이 다릅니다.
중복 키의 동작은 정해져 있지 않습니다. 대부분 뒤의 값이 이기지만 오류를 내는 파서도 있습니다. 긴 파일에서는 눈에 띄지 않으므로 린터로 잡는 편이 낫습니다.
앵커와 별칭으로 반복을 줄일 수 있습니다.
defaults: &defaults
timeout: 30
retries: 3
production:
<<: *defaults
timeout: 60
&로 이름을 붙이고 *로 참조합니다. <<는 병합 키입니다. 다만 병합 키는 YAML 1.1의 확장이라 1.2 파서에서 지원되지 않는 경우가 있습니다.
확인 순서
- 값이 이상하면 그 항목에 따옴표를 붙여 다시 읽어 봅니다
- 도구가 파이썬 기반인지 자바스크립트 기반인지 확인합니다. 1.1과 1.2 차이일 수 있습니다
- 파싱 결과를 JSON으로 출력해 타입을 봅니다.
"NO"와false는 눈으로 바로 구분됩니다 - 들여쓰기가 깨졌다면 탭이 섞였는지 봅니다
tools.onuel.dev의 YAML 포매터에 설정을 넣으면 구조가 의도한 대로 잡혔는지 확인할 수 있고, JSON을 YAML로 변환하면 두 형식을 나란히 놓고 어떤 값이 따옴표 없이 남는지 볼 수 있습니다.
- #YAML
- #설정
- #파싱