파이썬 YAML 파싱 오류가 나면 오류 줄만 고치기보다 그 줄과 바로 앞 구조의 들여쓰기, 탭, 콜론, 따옴표를 함께 확인해야 합니다. 문법을 수정한 뒤에는 신뢰할 수 없는 설정 파일을 yaml.safe_load로 읽고 YAMLError를 기록하는 흐름을 적용할 수 있습니다.
먼저 오류 위치와 앞 구조를 같이 봅니다
yaml.scanner.ScannerError나 mapping values are not allowed here는 파서가 현재 위치에서 YAML 구조를 해석하지 못했다는 신호입니다. 메시지의 line·column은 출발점이지, 항상 원인이 적힌 정확한 문자라는 뜻은 아닙니다. 바로 앞 줄에서 매핑이나 목록을 열어 놓고 들여쓰기를 어긋나게 했는지도 확인해야 합니다.
운영 중인 자동화라면 다음 순서가 효율적입니다.
- 오류 메시지의 줄과 열을 확인합니다.
- 해당 줄의 앞뒤에서 탭과 공백이 섞였는지 봅니다.
- 같은 레벨의 형제 키와 목록 항목이 동일한 구조인지 비교합니다.
- 콜론이 매핑 구분자인지 문자열의 일부인지 판단합니다.
- 수정 후 같은 입력을 다시 읽어 문법 오류가 사라졌는지 확인합니다.
들여쓰기와 탭부터 확인합니다
YAML 블록 구조는 들여쓰기로 표현됩니다. 같은 부모 아래에 있는 키는 같은 수준에 있어야 하며, 목록 항목 아래의 값은 목록 표시와 일관된 구조를 가져야 합니다. 들여쓰기에는 탭을 사용할 수 없으므로, 겉보기에는 정렬된 것처럼 보여도 탭 문자가 섞이면 파싱이 실패할 수 있습니다.
예를 들어 다음처럼 키의 깊이가 어긋나면 오류 위치가 실제 원인보다 뒤에서 표시될 수 있습니다.
job:
name: daily
retries: 3
retries를 name과 같은 수준으로 맞출지, 더 깊은 하위 구조로 만들지 먼저 결정해야 합니다. 공백 개수를 기계적으로 맞추는 것보다 YAML에서 표현하려는 부모-자식 관계를 기준으로 고치는 편이 안전합니다.
콜론과 따옴표를 구분합니다
콜론은 YAML에서 매핑의 키와 값을 나누는 문법이지만, 문자열 안에 들어갈 수도 있습니다. URL, 시간처럼 보이는 값, 메시지에 콜론이 포함된 경우에는 값 전체를 따옴표로 감싸 문법과 값을 구분하는 방법을 고려합니다.
endpoint: "https://example.com/api"
message: "실패 원인: 입력 파일을 확인하세요"
반대로 모든 값에 따옴표를 붙이는 것이 해결책은 아닙니다. 따옴표 자체가 닫히지 않았거나 문자열 안의 따옴표가 규칙에 맞지 않으면 또 다른 파싱 오류가 생길 수 있습니다. 문제가 난 줄만 보지 말고 같은 문자열이 시작된 위치와 닫힌 위치를 함께 확인하십시오.
safe_load는 입력을 읽는 경계에서 사용합니다
PyYAML의 yaml.safe_load는 첫 YAML 문서를 Python 객체로 변환하면서 표준 YAML 태그만 인식합니다. 설정 파일처럼 애플리케이션이 읽어야 하는 입력에는 우선 safe_load를 사용하고, 파싱 오류는 YAMLError로 받아 파일명과 오류 위치를 기록하는 방식이 적절합니다.
from pathlib import Path
import yaml
def load_settings(path: str) -> dict:
try:
with Path(path).open(encoding="utf-8") as stream:
data = yaml.safe_load(stream)
except yaml.YAMLError as exc:
mark = getattr(exc, "problem_mark", None)
location = f"{mark.line + 1}:{mark.column + 1}" if mark else "unknown"
raise ValueError(f"YAML 문법 오류 위치: {location}") from exc
if data is None:
return {}
if not isinstance(data, dict):
raise ValueError("최상위 YAML 값은 매핑이어야 합니다.")
return data
여기서 최상위 자료형을 확인하는 부분은 YAML 문법 검사와 별개의 애플리케이션 판단입니다. YAML이 문법적으로 맞아도 프로그램이 기대하는 키나 자료형이 없을 수 있으므로, 필수 키 검사는 이 함수 다음 단계에서 별도로 두는 편이 원인을 구분하기 쉽습니다.
신뢰할 수 없는 입력에 yaml.load를 그대로 적용하는 것은 피해야 합니다. PyYAML 문서는 안전하지 않은 로딩이 임의의 Python 객체 생성이나 함수 호출로 이어질 수 있다고 설명하므로, 특별한 이유와 통제된 입력이 없는 한 safe_load를 기본값으로 두는 것이 안전합니다.
문법 수정과 스키마 검증을 나눕니다
ScannerError가 남아 있다면 먼저 들여쓰기, 탭, 콜론, 따옴표처럼 YAML 문법을 고칩니다. 파싱이 성공한 뒤 특정 키가 없거나 값의 자료형이 다르다는 문제가 나오면 그때는 별도의 스키마 검증 문제로 분류합니다. 두 단계를 한 번에 고치려 하면 로그가 가리키는 원인을 놓치기 쉽습니다.
마지막으로 수정한 파일을 동일한 실행 경로에서 다시 읽고, 오류 위치가 사라졌는지와 프로그램이 기대하는 자료 구조를 얻었는지를 각각 확인하십시오. 문법 오류가 해결됐다는 사실만으로 업무 자동화에 필요한 설정이 모두 갖춰졌다고 판단해서는 안 됩니다.
정리
파이썬 YAML 파싱 오류는 오류 줄 주변의 구조를 함께 보는 것에서 시작합니다. 탭을 제거하고 형제 노드의 들여쓰기를 맞춘 다음, 콜론이 문법인지 문자열인지와 따옴표의 짝을 확인하면 원인을 좁힐 수 있습니다. 입력을 읽는 경계에서는 yaml.safe_load와 YAMLError 처리를 사용하고, 파싱 이후의 필수 키·자료형 검증은 별도 단계로 분리하면 운영 중 문제를 더 정확히 판단할 수 있습니다.
YAML 문법은 맞는데 필수 키가 없을 때의 검증 방법이나 여러 YAML 문서를 읽는 방법은 이 글의 다음 주제로 이어집니다.