YAML '노르웨이 문제', 스펙이 아니라 구현의 책임이다

Lobsters2026. 9. 11.조회 4

YAML을 둘러싼 비판이 다시 수면 위로 올라왔다. 흔히 '노르웨이 문제'로 불리는, `no`라는 값이 불리언 false로 해석되는 현상을 두고 YAML 스펙 자체가 잘못됐다는 주장이 반복되는데, 한 개발자가 스펙 문서를 직접 확인한 끝에 이는 스펙의 요구 사항이 아니라 라이브러리 구현의 선택이라는 결론에 도달했다.

YAML은 동적 언어의 기본 데이터 타입을 염두에 두고 설계된, 사람이 읽기 쉬운 크로스랭귀지 데이터 직렬화 언어다. 설정 파일부터 인터넷 메시징, 객체 영속화, 데이터 감사와 시각화까지 폭넓게 쓰이면서 인기를 얻었지만 그만큼 비판도 많다. 대표적으로 세 가지가 꼽힌다. 스펙이 지나치게 방대하다는 점, 라이브러리별 구현이 제각각이라는 점, 그리고 암시적 타입 추론이다. 이 셋은 서로 얽혀서 문제를 키운다.

글쓴이는 스펙 문서를 직접 파고든다. YAML 스펙은 1.0(2004년 1월), 1.1(2005년 1월), 1.2(2009년 7월)로 개정됐다. 1.0의 2.4절은 인용되지 않은 플레인 스칼라에 대해 "애플리케이션에 따라" 암시적 타입이 부여된다고 설명한다. seq, map, str 태그는 필수지만 정수·불리언·타임스탬프 같은 범용 태그는 필수가 아니며, 애플리케이션이 적절히 활용하도록 권장될 뿐이다.

정수 타입 정의를 보면 2진수, 8진수, 10진수, 16진수는 물론 60진수(base 60)까지 정규식으로 명시돼 있다. 3.3.2절은 프로세서가 플레인 스칼라를 정규식 집합과 대조해 타입을 자동 해석할 "수 있다(may)"고 서술한다. RFC 2119의 "may"와 "애플리케이션에 따라" 같은 표현이 반복되는 대목이다.

1.1도 크게 다르지 않다. 같은 3.3.2절에서 태그 해석은 애플리케이션에 특화된 것이므로 프로세서가 애플리케이션의 해석 규칙을 지정할 메커니즘을 제공해야 한다고 밝힌다. 언어가 좀 더 명확해지는 건 1.2에 이르러서다. 이때 '스키마' 개념이 도입되고, JSON 스키마를 확장한 'Core Schema'가 권장 기본값으로 제시된다. 중요한 건 1.2 스키마에는 60진수도, yes/no 불리언도 없다는 점이다. 즉 노르웨이 문제는 1.2 권장 사항에서 비롯된 것이 아니다.

글쓴이의 실무 경험도 이를 뒷받침한다. 9년 전 파이썬 디스코드 봇 설정 파일에 YAML을 썼고, 게임 프로젝트 'Space Station 14'에서는 원래 XML로 관리하던 엔티티·레시피 등 수백 종의 프로토타입 정의를 YAML로 전환했다. 이 과정에서 겪은 가장 큰 문제는 신규 기여자가 공백 민감성을 인지하지 못해 문법 오류를 내는 정도였다.

핵심은 역직렬화를 라이브러리에 맡기지 않는다는 것이다. 이들은 YamlMappingNode, YamlScalarNode 같은 그래프 객체를 받아 직접 파싱하고, 불리언이 필요한 필드를 읽을 때만 불리언 변환을 수행한다. 모델이 코드에 정의돼 있으니 `no`가 엉뚱하게 불리언이 될 일이 없다. 글쓴이는 이를 두고 동적 타입 언어의 스킬 이슈라고 표현한다.

개발자 입장에서 얻을 교훈은 분명하다. YAML을 쓸 때는 스키마를 명시하거나, 최소한 역직렬화 단계에서 타입을 통제해야 한다. PyYAML의 safe_load처럼 안전한 로더를 쓰는 것도 기본이다. 라이브러리가 제공하는 암시적 타입 추론에 설정 파일의 의미를 맡기면, 스펙이 아니라 구현이 만든 함정에 빠질 수 있다.

다만 이 글은 어디까지나 한 개발자의 스펙 해석과 실무 경험에 기반한다. 스펙 문서의 표현이 모호하다는 점 자체는 인정하면서도, 그것이 곧 YAML 자체가 나쁘다는 결론으로 이어지지는 않는다는 입장이다. 어떤 라이브러리를 쓰고 어떤 스키마를 적용하느냐에 따라 체감하는 문제는 달라질 수 있다.