Python에서 YAML 다루기 완벽 가이드: 설정 파일 관리부터 고급 커스텀 태그까지

1. YAML이란?

YAML의 개요

YAML(YAML Ain’t Markup Language)는 데이터 직렬화 형식 중 하나로, 구조화된 데이터를 표현하기 위해 널리 사용됩니다。JSON이나 XML과 유사하지만, YAML의 특징은 그 단순함과 높은 가독성입니다。특히 들여쓰기로 계층 구조를 표현할 수 있어 사람이 읽기 쉬운 형식이라는 점이 큰 장점입니다。

JSON 및 XML과의 차이

JSON과 XML도 마찬가지로 데이터를 기술하는 형식이지만, YAML은 이에 비해 장황한 기호가 적고 단순하며 이해하기 쉽다는 점이 특징입니다。예를 들어, JSON은 중괄호 {} 와 쉼표 , 를 많이 사용하므로, 특히 대규모 데이터를 다룰 때는 가시성이 떨어질 수 있습니다。한편, YAML에서는 들여쓰기로 구조를 표시하기 때문에 시각적으로 데이터의 계층을 이해하기 쉽다는 장점이 있습니다.

Python과의 높은 친화성

Python의 문법은 들여쓰기로 블록을 표시하는 구조가 특징이며, 이 점에서 YAML 포맷과 친화성이 있습니다。또한 Python에서 YAML을 다루기 위한 라이브러리 PyYAML을 사용하면 YAML 파일을 쉽게 읽고 쓸 수 있으며, 설정 파일로 활용되는 경우가 많습니다.

2. Python에서 YAML 파일을 읽고 쓰는 방법

YAML 파일 읽기

YAML 파일을 Python에서 읽으려면 먼저 PyYAML 라이브러리를 설치하고, yaml.safe_load() 함수를 사용합니다. 이 함수는 안전한 방식으로 YAML 데이터를 Python의 딕셔너리나 리스트로 변환합니다. 다음은 기본적인 읽기 예시입니다.
import yaml

# YAML 파일을 열어 내용을 읽어오기
with open('config.yaml', 'r') as file:
    data = yaml.safe_load(file)

print(data)
이 코드는 YAML 파일에서 데이터를 읽어와 이를 Python의 딕셔너리로 취급합니다. 예를 들어, 다음과 같은 YAML 파일을 읽는다고 가정해 봅시다.
database:
  host: localhost
  port: 3306
이 경우 Python에서는 다음과 같은 딕셔너리를 얻게 됩니다.
{'database': {'host': 'localhost', 'port': 3306}}

YAML 파일 쓰기

Python 데이터를 YAML 형식으로 기록하려면 yaml.dump() 함수를 사용합니다. 다음 예제에서는 Python 딕셔너리를 YAML 파일에 씁니다.
import yaml

data = {
    'name': 'John Doe',
    'age': 30,
    'city': 'New York'
}

with open('output.yaml', 'w') as file:
    yaml.dump(data, file)
이 코드는 딕셔너리 dataoutput.yaml이라는 파일에 저장합니다. 결과적으로 다음과 같은 YAML 형식의 데이터가 출력됩니다.
age: 30
city: New York
name: John Doe

일본어 처리

YAML에서 일본어를 다룰 때는, 특히 문자 깨짐을 방지하기 위해 allow_unicode=True 옵션을 지정하는 것이 중요합니다. 이렇게 하면 YAML 파일 내에서 일본어가 올바르게 표시되는 것이 보장됩니다.
yaml.dump(data, file, allow_unicode=True)
侍エンジニア塾

3. 고급 YAML 작업

사용자 지정 태그 만들기

YAML은 기본적인 데이터 형식(리스트, 딕셔너리 등)뿐만 아니라 Python 객체를 직렬화·역직렬화하는 것도 가능합니다. 이 경우 사용자 지정 태그를 사용합니다. 아래는 Python 클래스 객체를 YAML 형식으로 저장하는 예입니다。
import yaml

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

def person_representer(dumper, data):
    return dumper.represent_mapping('!Person', {'name': data.name, 'age': data.age})

def person_constructor(loader, node):
    values = loader.construct_mapping(node)
    return Person(values['name'], values['age'])

yaml.add_representer(Person, person_representer)
yaml.add_constructor('!Person', person_constructor)

# 객체를 YAML로 변환하여 저장
person = Person('Alice', 25)
with open('person.yaml', 'w') as file:
    yaml.dump(person, file)

# YAML 파일에서 객체를 재구성
with open('person.yaml', 'r') as file:
    loaded_person = yaml.load(file, Loader=yaml.FullLoader)
이와 같은 방식으로 Python 객체를 사용자 지정 형식으로 YAML에 저장해 두고, 나중에 재사용할 수 있습니다。

순서 유지

PyYAML에서는 기본적으로 딕셔너리의 순서가 유지되지 않기 때문에, 순서가 중요한 경우에는ruamel.yaml을 사용하는 것이 권장됩니다。ruamel.yaml에서는 딕셔너리 키의 순서가 유지되므로, 순서가 중요한 설정 파일을 다룰 때 유용합니다。

4. YAML 사용 예: 설정 파일 관리

설정 파일로서의 YAML의 편의성

YAML은 설정 파일로서 널리 사용됩니다. 특히 Python 애플리케이션에서는 설정 데이터를 관리하기 위한 최적의 형식으로 쓰입니다. 이는 YAML이 사람도 읽기 쉽고, 계층 구조를 시각적으로 이해하기 쉽기 때문입니다. 예를 들어 데이터베이스의 연결 정보나 애플리케이션의 로그 설정 등 복잡한 설정을 일괄적으로 관리하는 데 적합합니다.
database:
  host: localhost
  port: 3306
  username: user
  password: pass

logging:
  level: DEBUG
  file: /var/log/app.log
위와 같이 여러 설정을 간결하게 기술할 수 있고, 시각적으로도 이해하기 쉬운 것이 특징입니다.

실제 프로젝트에서의 YAML 사용 예

YAML은 Python 프레임워크인 Django와 Flask, CI 도구인 CircleCI, 컨테이너 오케스트레이션 도구인 Kubernetes 등 다양한 프로젝트에서 사용됩니다. 이러한 프로젝트에서는 주로 구성 관리와 환경 변수 정의에 쓰입니다. Django에서의 YAML 사용 예: Django 프로젝트에서는 YAML을 사용해 외부 설정 파일을 불러와 배포와 환경 구축을 간소화할 수 있습니다. 설정 파일로 YAML을 사용하면 개발 환경과 운영 환경에 따라 다른 설정을 유연하게 관리할 수 있습니다.
import yaml

with open('config.yaml', 'r') as file:
    config = yaml.safe_load(file)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': config['database']['name'],
        'USER': config['database']['username'],
        'PASSWORD': config['database']['password'],
        'HOST': config['database']['host'],
        'PORT': config['database']['port'],
    }
}

JSON 및 XML과의 비교

YAML은 JSON이나 XML에 비해 설정 파일로서의 사용 편의성이 두드러집니다. JSON은 중괄호와 쉼표로 구분되어 파일이 길어지면 가독성이 떨어질 수 있습니다. 또한 XML은 시작 태그와 종료 태그가 필요해 장황해지기 쉽습니다. 반면 YAML은 들여쓰기로 계층 구조를 표현하므로 설정 파일의 내용을 직관적으로 파악할 수 있습니다. JSON과 YAML의 비교:
{
  "database": {
    "host": "localhost",
    "port": 3306,
    "username": "user",
    "password": "pass"
  },
  "logging": {
    "level": "DEBUG",
    "file": "/var/log/app.log"
  }
}
database:
  host: localhost
  port: 3306
  username: user
  password: pass

logging:
  level: DEBUG
  file: /var/log/app.log
YAML이 JSON에 비해 더 단순하고 읽기 쉽다는 것이 분명합니다。
年収訴求

5. 문제 해결 및 오류 처리

자주 발생하는 오류와 그 대처법

YAML 파일을 다룰 때 발생하는 일반적인 오류 중 하나는 ‘파일이 존재하지 않음’ 또는 ‘파일이 올바른 형식이 아님’과 같은 문제입니다. 이러한 오류는 적절한 오류 처리를 구현하면 예방할 수 있습니다. 예를 들어, YAML 파일의 파싱 오류가 발생한 경우, yaml.YAMLError로 예외를 잡을 수 있습니다. 또한, 파일이 존재하지 않는 경우에는 FileNotFoundError를 처리하여 사용자에게 적절한 메시지를 표시할 수 있습니다.
import yaml

def load_yaml(file_path):
    try:
        with open(file_path, 'r') as file:
            data = yaml.safe_load(file)
    except FileNotFoundError:
        print(f"Error: The file {file_path} does not exist.")
        return None
    except yaml.YAMLError as e:
        print(f"Error: Failed to parse YAML file. {e}")
        return None
    return data

config = load_yaml('config.yaml')
if config:
    print(config)

오류 처리 모범 사례

  1. 파일 존재 여부 확인: 파일이 존재하는지 확인하고, 존재하지 않으면 오류 메시지를 표시합니다.
  2. 파싱 오류 처리: YAML 구문이 올바르지 않은 경우 오류를 잡아 상세한 메시지를 제공합니다.
  3. 로그 출력: 문제가 발생했을 때 오류 메시지를 로그 파일에 기록하여 나중에 문제를 해결할 수 있도록 합니다。

6. 정리

YAML은 단순하고 사람이 읽기 쉬운 데이터 직렬화 형식입니다. Python에서 YAML을 읽고 쓰는 작업은 매우 간단하며, 설정 파일 관리에서 많은 이점을 제공합니다. 커스텀 태그나 클래스의 직렬화, 순서 유지와 같은 고급 작업도 가능하며, 이를 활용하면 보다 유연하고 강력한 애플리케이션 설정 관리를 구현할 수 있습니다. YAML의 활용은 설정 파일 관리에 그치지 않고, 데이터 저장 형식으로도 널리 사용되고 있으며, 앞으로도 다양한 프로젝트에서의 사용이 기대됩니다.
年収訴求