it-box

YAML 값이 바뀌는 이유와 no·yes·1.10 함정 정리

YAML 파서가 no, yes, 1.10, 0123 같은 값을 어떻게 해석하는지, YAML 1.1과 1.2의 차이, 들여쓰기와 앵커 규칙을 실제 출력과 함께 정리합니다.

에러 없이 값만 틀리는 설정 파일

배포 설정 파일에서 가장 찾기 어려운 오류는 파싱이 실패하는 경우가 아닙니다. 파싱은 성공하지만 값의 타입이 바뀌어서 뒤쪽 로직이 조용히 틀어지는 경우입니다. 국가별 배포 여부를 적은 파일이 대표적인 예입니다.

regions:
  kr: yes
  jp: no
  us: no

사람은 이 파일을 "한국만 배포"로 읽습니다. 하지만 YAML 파서가 어떤 버전의 규칙을 따르는지에 따라 yes와 no는 문자열이 될 수도 있고, 불리언이 될 수도 있습니다. 이 사이트의 YAML → JSON 변환기가 사용하는 yaml 패키지(2.x)는 기본값으로 YAML 1.2를 따릅니다. 이 규칙으로 읽으면 결과는 다음과 같습니다.

{ "regions": { "kr": "yes", "jp": "no", "us": "no" } }

값이 문자열로 남아 있으므로 "yes" === true 같은 비교가 실패합니다. 같은 파일을 YAML 1.1 규칙으로 읽으면 결과가 달라집니다. 1.1에서는 yes와 no가 불리언이므로 kr은 true, jp와 us는 false가 됩니다. 배포 스크립트가 어느 쪽 규칙을 기대하는지 모르면 이 차이는 운영 환경에서야 드러납니다.

YAML 1.1과 1.2는 같은 텍스트를 다르게 읽는다

YAML은 하나의 고정된 규칙이 아니라 버전이 나뉘어 있습니다. 1.1은 오랫동안 널리 쓰였고, 지금도 여러 라이브러리가 이 규칙을 기본으로 삼습니다. Python의 PyYAML이 대표적으로 YAML 1.1을 따릅니다. 1.2는 JSON과 더 가까운 core 스키마를 기본으로 두고, 불리언은 true와 false만 인정합니다. 그래서 yes, no, on, off는 1.2에서 평범한 문자열입니다.

아래 표는 같은 입력을 yaml 패키지의 두 버전으로 각각 파싱한 결과입니다.

입력 YAML 1.2 결과 YAML 1.1 결과
no, yes, on 문자열 불리언 (false, true, true)
1.10 숫자 1.1 숫자 1.1
0123 숫자 123 숫자 83 (8진수로 해석)
12:30 문자열 숫자 750 (60진수로 해석)
2026-11-10 문자열 날짜 객체

표에서 1.10은 두 버전 모두 숫자 1.1이 됩니다. 버전 번호를 실수처럼 쓰면 뒤의 0은 어느 규칙에서도 살아남지 않습니다. 파서를 바꾸는 것으로 해결되지 않으므로 따옴표로 문자열임을 명시해야 합니다.

버전 번호와 앞자리 0

버전 번호는 가장 자주 깨지는 값입니다. 다음 설정은 version이 실수 1.1이 됩니다.

version: 1.10
{ "version": 1.1 }

앞자리 0도 같은 문제를 일으킵니다. 파일 권한을 mode: 0644로 적은 파일을 두 버전으로 읽으면 결과가 갈립니다.

YAML 1.2: {"mode":644}
YAML 1.1: {"mode":420}

두 결과 모두 원래 의도한 문자열 0644가 아닙니다. 1.1에서는 8진수로 계산된 10진수 420이 되고, 1.2에서는 앞의 0이 버려진 644가 됩니다. 값이 문자열이어야 한다면 따옴표를 붙여 "0644"로 적습니다. 따옴표가 있는 값은 어떤 버전에서도 문자열로 읽힙니다.

날짜와 시간처럼 보이는 값

날짜 형식은 파서마다 결과가 가장 크게 다릅니다. deployed: 2026-11-10은 1.2에서 문자열 "2026-11-10"으로 남지만, 1.1에서는 날짜 객체가 됩니다. 날짜 객체를 JSON으로 내보내면 "2026-11-10T00:00:00.000Z"처럼 시간과 시간대가 붙은 문자열이 되고, 시간대에 따라 표시되는 날짜도 달라질 수 있습니다. 날짜를 날짜 그대로 비교하거나 파일 이름에 넣는 설정이라면 문자열로 명시하는 편이 안전합니다.

들여쓰기와 탭

YAML은 들여쓰기로 구조를 표현합니다. 들여쓰기에 탭 문자를 쓰면 파서는 이를 허용하지 않고 오류를 냅니다.

service:
	name: billing-api
Tabs are not allowed as indentation at line 2, column 1

에디터가 Tab 키를 탭 문자로 입력하도록 설정되어 있으면 이 오류를 자주 만나게 됩니다. 프로젝트 안에서는 공백 두 칸 또는 네 칸 중 하나로 통일하고, 에디터 설정에서 탭을 공백으로 바꾸도록 맞춰 두는 것이 좋습니다. 같은 수준의 키는 같은 칸 수로 맞춰야 하며, 들여쓰기가 한 칸이라도 어긋나면 의도와 다른 구조가 되거나 파싱이 실패합니다.

앵커와 병합 키

반복되는 설정은 앵커(&)와 별칭(*)으로 한 번만 적을 수 있습니다. 병합 키 <<는 별칭이 가리키는 내용을 현재 객체에 넣고, 같은 객체에 직접 적은 키는 그 값을 덮어씁니다.

defaults: &defaults
  timeout: 30
  retries: 2
prod:
  <<: *defaults
  timeout: 60

이 입력을 YAML → JSON 변환기에 넣으면 prod에는 defaults의 retries가 들어가고, timeout만 60으로 덮어씁니다.

{
  "defaults": {
    "timeout": 30,
    "retries": 2
  },
  "prod": {
    "timeout": 60,
    "retries": 2
  }
}

주의할 점은 병합 키를 해석하지 않는 파서입니다. 이 경우 <<는 일반 키로 남고 prod는 {"<<": {"timeout": 30, "retries": 2}, "timeout": 60}이 되어 기대한 값과 달라집니다. 이 도구는 병합 키를 해석하도록 설정되어 있지만, 배포 시스템이 쓰는 파서가 같은 설정을 쓰는지는 따로 확인해야 합니다.

따옴표를 언제 붙일까

따옴표는 "이 값은 문자열이다"라는 의도를 파서에 알리는 가장 간단한 수단입니다. 다음과 같은 값은 따옴표를 붙이는 쪽이 안전합니다.

  • 버전 번호처럼 점이 여러 개이거나 뒤에 0이 의미를 가지는 값
  • 앞자리 0이 있는 코드나 우편번호
  • 국가 코드 NO(노르웨이)처럼 yes, no, on, off와 같은 글자로 이루어진 값
  • 콜론(:)이나 #이 들어 있어 주석이나 구분자로 오해될 수 있는 값
country: 'NO'
version: '1.10'
zip: '0123'

이 입력은 1.2와 1.1 모두에서 {"country":"NO","version":"1.10","zip":"0123"}으로 읽힙니다. 반대로 포트 번호나 개수처럼 숫자로 쓰려는 값에는 따옴표를 붙이지 않습니다. 모든 값에 따옴표를 붙이면 나중에 숫자 비교가 필요할 때 다시 고쳐야 합니다.

JSON으로 변환해서 확인하는 습관

설정을 고친 뒤에는 파서가 실제로 어떤 값을 만들었는지 JSON으로 한 번 확인하는 습관이 도움이 됩니다. YAML → JSON 변환기에 파일을 붙여 넣으면 병합 키를 해석한 최종 값을 3칸 들여쓰기 JSON으로 보여 줍니다. 입력이 YAML 문법에 맞지 않으면 "Provided YAML is not valid." 메시지가 나옵니다.

반대 방향 변환이 필요하면 JSON → YAML 변환기를 씁니다. 이 도구는 JSON5 형식의 입력을 받아 yaml 패키지로 다시 씁니다. 출력된 enabled: yes는 1.2 기준으로 문자열이므로, 이 파일을 1.1 파서가 읽는다면 그 파서에서 다시 확인해야 합니다.

YAML 포맷터는 YAML을 파싱한 뒤 들여쓰기 크기와 키 정렬 옵션을 적용해 다시 씁니다. 편집자마다 들여쓰기가 다른 파일을 정리할 때 유용합니다. 다만 파싱 과정에서 주석이 사라지므로, 주석이 설정의 의미를 설명하는 파일에는 사용하지 않는 편이 낫습니다.

점검 목록

  • yes, no, on, off와 국가 코드 값에 따옴표가 있는지 확인합니다.
  • 버전 번호와 0으로 시작하는 값이 문자열로 남아야 하는지 확인합니다.
  • 날짜와 시간 값을 어떤 버전의 규칙으로 읽는지 소비자 쪽 파서를 확인합니다.
  • 들여쓰기에 탭 문자가 섞이지 않았는지 확인합니다.
  • 앵커와 병합 키를 쓴 경우, 같은 입력을 실제 파서에 넣어 결과를 확인합니다.
  • 주석이 중요한 파일을 포맷터로 다시 쓰지 않았는지 확인합니다.
  • 변경 후에는 JSON 결과와 기대한 값을 한 줄씩 대조합니다.

관련 도구