YAML Diff 비교기는 사실 YAML을 이해하지 못한다
웹에서 무료로 제공되는 "YAML Diff" 도구 대부분은 이름과 달리 진짜 YAML 파서를 내장하고 있지 않습니다. 실제 코드를 열어보면 YAML 문법(들여쓰기 기반 중첩, 앵커·별칭, 블록 스칼라 등)을 해석하는 파서 대신, 한 줄씩 정규식으로 "키: 값" 패턴만 훑는 텍스트 비교 로직이 들어있는 경우가 많습니다. 모두의 툴의 YAML Diff 비교기도 마찬가지입니다. 이 가이드는 그 구조를 그대로 밝히고, 그 구조 때문에 실무에서 자주 겪게 되는 오탐 상황을 정리했습니다.
1. 실제 동작: YAML 파서가 아니라 한 줄짜리 정규식
이 도구의 파서는 ^(\s*)([\w.\-]+)\s*:\s*(.*)$라는 정규식으로 입력 텍스트를 한 줄씩 훑습니다. 그룹 1번은 줄 앞의 들여쓰기 공백을, 2번은 키 이름을, 3번은 콜론 뒤의 값을 캡처합니다. 문제는 1번 그룹(들여쓰기)이 캡처만 될 뿐 어디에도 사용되지 않는다는 점입니다. 그 결과 database: 아래 들여쓰기로 중첩된 host:와 최상위의 host:가 파서 입장에서는 완전히 동일하게 취급되어, 모든 키가 하나의 평면(flat) 객체에 담깁니다.
2. 들여쓰기가 무시되면 생기는 키 충돌
같은 파일 안에 database: host: a.com과 cache: host: b.com이 각각 다른 섹션에 들여쓰기로 중첩되어 있다고 해봅시다. 사람이 보기엔 명백히 다른 두 값이지만, 파서는 들여쓰기를 무시하므로 두 host 키가 같은 최상위 이름 공간에서 충돌합니다. 나중에 파싱된 값이 앞의 값을 덮어써 버리기 때문에, 실제로는 두 값이 모두 존재하는데도 비교 결과에는 하나만 반영되는 사고가 발생할 수 있습니다.
3. 주석만 바꿨는데 "변경됨"으로 표시되는 이유
값 뒤에 붙은 인라인 주석(debug: true # 임시로 꺼둠)은 정규식의 3번 그룹, 즉 값 캡처 범위 안에 통째로 포함됩니다. 다시 말해 true # 임시로 꺼둠 전체가 하나의 문자열 값으로 저장됩니다. 그래서 실제 값(true)은 그대로인데 주석 텍스트만 바꿔도 파서 입장에서는 값 자체가 바뀐 것으로 판정해 diff에 "변경됨"으로 표시합니다. 반대로 콜론이 없는 순수 주석 줄(# 이 섹션은 검토 중)은 정규식에 아예 매칭되지 않아 완전히 무시됩니다.
4. 배열은 비교 대상에서 통째로 빠진다
YAML의 블록 스타일 목록(하이픈으로 시작하는 - item 형태)은 콜론이 없으므로 이 정규식에 애초에 매칭되지 않아 비교에서 완전히 제외됩니다. 인라인 배열(tags: [a, b, c])은 매칭은 되지만 실제 배열로 파싱되지 않고 "[a, b, c]"라는 문자열 그대로 저장되어, 원소 하나만 바뀌어도 전체가 통으로 "변경됨"이 되거나, 순서만 바뀌어도 다른 값으로 오인됩니다.
debug: true, YAML B에 debug: true # 임시만 있어도 diff는 ~ debug: true → true # 임시로 "변경됨" 1건을 표시합니다. 실제 설정값은 동일한데도 리뷰어가 "값이 바뀌었다"고 오해할 수 있는 대표적인 오탐 케이스입니다.
| 입력 | 사람이 보는 의미 | 파서 결과 |
|---|---|---|
| database.host / cache.host (같은 이름, 다른 섹션) | 서로 다른 두 값 | 하나가 다른 하나를 덮어씀 |
| debug: true → debug: true # 주석 추가 | 값 변화 없음 | diff-chg(변경됨)으로 오탐 |
| - a\n- b (블록 배열) | 비교 대상 | 매칭 자체가 안 되어 무시됨 |
5. 그래서 언제 써도 되고, 언제 위험한가
키 이름이 파일 전체에서 겹치지 않고, 들여쓰기가 1단계뿐이며, 배열이나 주석이 거의 없는 단순한 설정 파일이라면 이런 줄 단위 diff로도 충분히 실용적입니다. 반대로 Kubernetes 매니페스트, CI 파이프라인 설정처럼 중첩이 깊고 같은 키 이름이 여러 섹션에 반복되는 YAML이라면, 이 도구의 결과만 믿지 말고 원본 파일을 직접 대조하거나 YAML 검증기로 구조 자체를 먼저 확인하는 것이 안전합니다. 구조까지 정확히 비교하고 싶다면 YAML을 JSON으로 변환한 뒤 JSON Diff 비교기로 비교하는 우회 방법도 있습니다.
자주 묻는 질문
Q. 그럼 이 도구는 쓸모가 없나요?
아닙니다. 단순한 평면 설정 파일이나, 키 이름이 파일 전체에서 유일하고 배열이 없는 YAML이라면 빠르게 변경점을 훑는 용도로 충분히 유용합니다. 다만 중첩이 깊거나 반복되는 키 이름이 있는 파일에는 부적합합니다.
Q. 구조까지 정확히 비교하려면 어떻게 해야 하나요?
YAML을 JSON ↔ YAML 변환기로 JSON으로 바꾼 뒤, 실제 객체 구조를 인식하는 JSON Diff 도구로 비교하면 들여쓰기·중첩 문제를 우회할 수 있습니다.
Q. 앵커(&)나 별칭(*) 같은 고급 YAML 문법도 지원되나요?
지원되지 않습니다. 정규식은 단순한 한 줄짜리 "키: 값" 패턴만 인식하므로 앵커, 별칭, 블록 스칼라(|, >) 등은 매칭되지 않거나 값의 일부로 잘못 흡수될 수 있습니다.
Q. 대용량 YAML 파일도 처리되나요?
모든 처리가 브라우저 안에서 줄 단위 정규식 매칭으로 이루어지므로 아주 큰 파일은 느려질 수 있습니다. 실무에서 중요한 설정 비교라면 결과만 신뢰하지 말고 원본 파일도 함께 대조하세요.