
3줄 요약
- YAML은 Sequence라는 파이썬의 리스트와 Mapping이라는 Python의 Dict와 비슷한 형식으로 파일을 구성한다.
- YAML은 Indentation(들여쓰기)로 문단을 구분한다.
- YAML의 주석은 "#"을 사용하며, 그 외에 문단 구분은 "---"을 사용한다.
0. 들어가며
2023년에 CKA를 딴 뒤, 3년이 지나가는 지금 CKA의 유효기간이 만료를 향해 달려가고 있다. 그래서 생각난 김에 유효기간이 만료되기 전에 CKAD를 따보자 하는 생각으로 오랜 만에 UDEMY(유데미)에서 CKAD강의를 들으면서 YAML파일을 자주 만지게 되었다. YAML의 경우 계륵 같은 느낌이 강한 것 같다. 공부하기에는 "이걸 굳이 해야하나"하는 생각이 들고, 그렇다고 공부를 안하자니 막상 사용할 때 "이거 문법이 살짝 틀려서 에러를 뱉네"하는 상황이 많았다.
그래서 이 참에 YAML을 간단하게 정리하면서 위와 같은 애매한 상황에서 벗어나기 위한 정리 글을 작성하는 것도 도움이 될 것 같아서 한 번 이렇게 글을 작성하게 되었다. 이 글을 보시는 독자 분들께서 간단하게 정리하며 Recap을 할 수 있는 시간이 되었으면 하는 마음에서 한 번 오늘 주제인 YAML에 대해서 이야기 해보겠다.
1. 소개
Red Hat에서는 다음과 같이 YAML에 대해 이야기하고 있다.
YAML is a human-readable data serialization language that is often used for writing configuration files. Depending on whom you ask, YAML stands for yet another markup language or YAML ain’t markup language (a recursive acronym), which emphasizes that YAML is for data, not documents.
YAML은 사람이 읽을 수 있는 데이터 직렬화 언어로 설정 파일을 작성할 때 자주 사용됩니다. 누군가 당신에게 YAML에 대해 질문을 할 때, 어느 부분을 강조하느냐에 따라 데이터를 강조하고 문서가 아니라고 한다면 YAML이 마크업 언어가 아니라고 할 수 있고 혹은 YAML은 또다른 마크업 언어가 될 수 있습니다.
Red Hat 소개 페에지 : https://www.redhat.com/en/topics/automation/what-is-yaml
YAML이 어떤 문장의 약자인지 혹은 어떤 뜻에서 유래했는지 궁금하신 분이 있을 텐데, "YAML Ain't Markup Language(YAML은 마크업 언어가 아니다)"의 약자이다. 즉 YAML자체가 이미 재귀적인 구조를 가지고 있는 언어유희이다.
YAML은 현재 1.2.2버전까지 나왔으며 2004년 YAML 1.0을 시작으로 "Oren Ben-Kiki", "Clark Evans" 그리고 "Brian Ingerson"을 통해 배포되었다. 당시 YAML을 만들 때 7가지 목표가 있었다. 이는 다음과 같다.
- YAML documents are easily readable by humans. (YAML 문서는 사람이 쉽게 읽을 수 있어야 한다.)
- YAML uses the native data structures of agile languages. (YAML은 애자일(Agile) 언어의 기본 자료 구조를 사용해야 한다.)
- YAML data is portable between programming languages. (YAML의 데이터는 프로그래밍 언어와 서로 호환되어야 한다.)
- YAML has a consistent model to support generic tools. (YAML은 일반적인 도구를 지원하기 위해 일관성을 가진 모델이다.)
- YAML enables stream-based processing. (YAML은 스트림 기반 처리를 지원해야 한다.)
- YAML is expressive and extensible. (YAML은 표현 가능하면서 확장 가능해야 한다.)
- YAML is easy to implement and use. (YAML은 쉽게 실행하고 사용할 수 있어야 한다.)
아무튼 이러한 역사를 가진 YAML은 굉장히 직관적이면서도 처음 쓰는 사람들도 쉽게 접할 수 있다. 하지만 YAML만의 고유한 문법이 어느정도 존재하기 때문에 이를 짚고 넘어가야 한다.
2. YAML 예제
#Comment: This is a supermarket list using YAML
#Note that - character represents the list
---
food:
- vegetables: tomatoes #first list item
- fruits: #second list item
citrics: oranges
tropical: bananas
nuts: peanuts
sweets: raisins
위는 YAML의 대부분의 문법이 들어간 예제다. 여기에 YAML에 대한 문법이 다 들어가 있다고 볼 수 있다. 일단, YAML에서 기본적으로 지켜야 하는 법칙 혹은 룰같은 것이 있는데 다음과 같다. YAML은 들여쓰기(indentation)로 범위를 구분하며 각 항목은 한 줄에 하나씩 시작한다. Python(파이썬)을 생각하면 편하다. 파이썬의 들여쓰기처럼 YAML도 문단을 구분할 때 들여쓰기로 구분한다. 그렇다면 위의 예제에서 나온 요소들을 하나하나 살펴보겠다.
2-1. 주석과 구분선
YAML에서는 주석을 "#"으로 사용한다. 그리고 YAML에서 “---”을 통해 문서의 문맥을 나눈다. 즉 위에서는 주석 부분과 실제 코드가 돌아가는 부분을 나눈 곳이 "food: " 윗 칸의 “---”이 되는 것이다. 만약 문단이 두개라면 어떻게 할까? 다음과 같이 써주면 된다.
# Ranking of 1998 home runs
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# Team ranking
---
- Chicago Cubs
- St Louis Cardinals
2-2. 데이터의 종류
YAML은 두가지 방식으로 데이터를 나눈다. 하나는 Sequence이며 하나는 Mapping이다. 쉽게 말해, 파이썬으로 비유하자면 List와 Dict가 될 것이다.
- Sequence : 특정한 순서로 나열된 값들의 목록이다. Sequence는 대시와 공백(- )으로 시작합니다. 시퀀스는 Python의 리스트(list)나 Bash 또는 Perl의 배열(array)로 생각하면 됩니다.
- Mapping : 키-값 쌍이다. 각 키는 반드시 고유해야 하며, 순서는 중요하지 않다. Python의 Dict나 Bash 스크립트에서의 변수 할당으로 생각하면 된다.
위의 Sequence, Mapping말고도 Scalar라는 것이 존재하는데, 단순하게 말해 Python에서 변수에 들어갈 값이라 생각하면 편한다. String, Integer, Date 등등이 있다. 그리고 Object도 있는데, 단순하게 생각해서 Key-Value가 갖춰진 파이썬의 Dict이라고 봐도 괜찮다. 아무튼 위의 Sequence와 Mapping을 조합하여 다양한 형식의 YAML 파일을 구성할 수 있다.
3. Mapping 블록
YAML 파일을 매핑으로 시작하면, YAML은 매핑들이 계속 나올 것처럼 기대한다. YAML에서 매핑은 끝나고 새로운 매핑 블록이 명시적으로 생성되기 전까지는 닫히지 않는다. 새 블록은 두 가지 경우에만 만들 수 있다. 첫째, 들여쓰기 수준을 더 깊게 늘리는 경우(이때 새 블록은 이전 블록 내부에 존재합니다). 둘째, 이전 매핑을 끝낸 뒤 이와 나란히 위치하는 새 매핑 블록을 시작하는 경우이다. 한 번 예시를 봐보자.
---
Store: Bakery
- Sourdough loaf
- Bagels
위의 단순한 Mapping으로만 이루어진 YAML파일이 있다. 위 파일의 문제는 Mapping 블록을 열었지만 닫지 않았다는 것이다. 위의 경우에서 Bakery로 Key-Value를 지정해주고 그 다음에 단순히 Sequence를 넣어주었다. 근데 이러면 YAML은 단순히 인식하기에 Mapping이 끝나지 않고 갑자기 튀어나온 Sequence에 당황하게 되는 것이다. 그렇다면 이 Mapping 블록을 닫고서 새로운 형식을 넣으려면 어떻게 해야할까? 단순하다. 새로운 Mapping 블록을 넣어야 한다. 이 때 Mapping의 Key-Value에서 Value는 Sequence가 될 수 있지만 무조건 Key가 존재해야 한다.
---
Store:
Bakery:
- ‘Sourdough loaf’
- ‘Bagels’
Cheesemonger:
- ‘Blue cheese’
- ‘Feta’
위의 YAML파일을 고치면 위의 코드처럼 된다. 이를 JSON으로 바꾸면 "{“Store”: {“Bakery”: [“Sourdough loaf”, “Bagels”], “Cheesemonger”: [“Blue cheese”, “Feta”]}}"와 같이 표현할 수 있다.
4. Sequence 블록
앞에서 말했듯이 Sequence는 파이썬의 List로 생각하면 편하다. 그렇다면 [“Flour”, “Water”, “Salt”]와 같은 List를 YAML로 표시하면 어떻게 될까? 간단하다.
---
- Flour
- Water
- Salt
위와 같이 대쉬(-)를 사용한 뒤 한칸 뛰어주고 값을 적어주면 된다. 물론 List처럼 콤마(,)로 구분하는 것이 아닌 한 줄에 하나씩 대시(-)로 구분해 줘야 한다.
5. Mapping과 Sequence를 혼합해서 쓰기
#Comment: This is a supermarket list using YAML
#Note that - character represents the list
---
food:
- vegetables: tomatoes #first list item
- fruits: #second list item
citrics: oranges
tropical: bananas
nuts: peanuts
sweets: raisins
그렇다면 위의 예제를 다시 살펴보겠다. 위의 예제는 Mapping과 Sequence를 혼합해서 사용한 좋은 예시이다. 그렇다면 이를 파이썬으로 표현하면 어떻게 될까? 혹은 TypedDict처럼 Type Annotation을 해주면 어떻게 될까? 아마 다음과 같이 될 것이다.
Dict[ Key: Value ], Dict[ Key : List[ Dict[ Key : Value ]]]
이렇게 타입을 간단하게 표현해 줄 수 있을 것이다. 물론 역시나 주의해야할 점은 YAML에서 Indentation을 통해 이 단락안에 포함되어 있다는 것을 명시해 줘야 한다는 것이다. 위의 YAML을 JSON으로 바꾸면 다음과 같을 것이다.
{"food": ["vegetables": "tomatoes", "fruits" : [{"citrics": "oranges", "tropical": "bananas", "nuts": "peanuts", "sweets": "raisins"}]]
크게 어려운 부분은 없다. - vegetables: tomatoes는 List의 첫번째 값으로 쓰이면서 Dict 형태라고 생각하면 되며, - fruits: 이후의 부분은 fruits를 Key값으로 가지고 4개의 Key-Value를 가진 Dict이 List에 하나 들어 있다고 생각하면 된다. 다른 예시를 한 번 봐보겠다.
list:
- color: red
direction: left
- color: blue
datetime:
time: '11:14:11'
date: '2012-04-11'
위의 필드를 파이썬으로 대입해서 생각해보면 list라는 변수가 있고 거기 안에는 {"color": "red", "direction": "left"}, {"color": "blue", "datetime" : {"time": "11:14:11", "date": "2012-04-11"}}이 들어있는 것이다. 최종적으로 보면 List에는 두 개의 요소(element)가 있으며 그 element는 중첩된 파이썬 Dict로 구성되어 있다고 생각하면 편하다. 그리고 이 값을 담는 변수는 list가 되는 것이다.
아무튼 이렇게 간단하게 Python 문법에 비유해서 YAML파일을 읽는 법과 이를 사용하는 방버을 알아보았다. 이 글이 많은 사람들에게 도움이 되기를 바란다.
