FormatArc의 한국어 YAML to JSON 변환기 화면에서 줄 번호와 함께 구문 오류가 표시된 화면FormatArc의 한국어 YAML to JSON 변환기 화면에서 줄 번호와 함께 구문 오류가 표시된 화면
저자: FormatArc 편집부게시일: 2026-04-13갱신일: 2026-08-22

YAML 문법 가이드 - 기본 작성법과 'Forbidden Block Composed Value' 오류 해결

1분 요약 — YAML 작성법

  • 들여쓰기는 스페이스만 사용합니다 (탭은 허용되지 않습니다). 2칸 스페이스가 사실상의 표준입니다.
  • key: value에서 콜론 뒤에는 반드시 공백이 필요합니다. key:value는 하나의 문자열로 취급됩니다.
  • 리스트는 - (하이픈+공백), 매핑은 key: value로 작성합니다.
  • 숫자, 불리언, 날짜 등으로 오인될 수 있는 값은 따옴표로 감쌉니다: version: "1.0".
  • 오류를 빠르게 확인하고 싶다면 FormatArc YAML to JSON 변환기에 붙여넣으면 줄 번호가 포함된 오류 메시지로 문제 위치를 바로 확인할 수 있습니다.

YAML이란 무엇이며 어디에 쓰이는가

YAML(YAML Ain't Markup Language)은 사람이 읽고 쓰기 쉬운 텍스트 기반의 구조화 데이터 포맷입니다. 문자열, 숫자, 불리언, null, 리스트, 매핑이라는 JSON과 동일한 데이터 모델을 다루지만, 괄호 대신 들여쓰기(Indentation)로 계층 구조를 표현합니다.

현대 클라우드 네이티브 환경이나 DevOps 도구를 다루다 보면 이미 YAML을 접해보셨을 것입니다.

  • Kubernetes 매니페스트, Helm 차트
  • Docker Compose 설정 파일
  • GitHub Actions, GitLab CI, CircleCI 워크플로
  • Ansible 플레이북
  • OpenAPI 사양
  • 정적 사이트 생성기(Hugo, Jekyll, Eleventy 등)

이 글에서는 실무에서 사용하는 모든 YAML 문법을 구체적인 예제와 초보자가 자주 겪는 실수 목록과 함께 설명합니다. YAML의 기본 개념과 전반적인 개요는 YAML이란?을, YAML과 JSON의 차이를 직접 비교하고 싶다면 YAML과 JSON의 차이점, 변환 절차는 YAML을 JSON으로 변환하는 방법을 참고하세요.

YAML을 구성하는 3가지 기본 요소

YAML 파일에 나타나는 모든 데이터는 다음 세 가지 중 하나입니다.

  • 스칼라(Scalar) — 문자열, 숫자, 불리언, null 등 단일 값
  • 시퀀스(Sequence) — 순서가 있는 리스트
  • 매핑(Mapping) — 키와 값의 쌍(객체 또는 딕셔너리)

이 세 가지 요소는 자유롭게 중첩할 수 있습니다. 매핑 안에 리스트가 들어갈 수도 있고, 리스트 안에 매핑이 들어갈 수도 있습니다. 이 구조만으로 JSON과 호환되는 모든 데이터를 표현할 수 있습니다. JSON 형식의 상세한 작성법은 JSON 작성법 가이드를 참고하세요.

들여쓰기(Indentation) 규칙

YAML의 계층 구조는 들여쓰기로 표현합니다. 반드시 기억해야 할 규칙은 다음과 같습니다.

  • 스페이스(공백)만 사용해야 합니다. 탭(Tab) 문자는 대부분의 파서에서 구문 오류를 발생시킵니다.
  • 들여쓰기 폭을 정했다면 파일 전체에서 일관되게 유지합니다(일반적으로 2스페이스).
  • 같은 계층의 요소는 동일한 들여쓰기 깊이로 맞춥니다.
  • 닫는 괄호가 없으며 오직 들여쓰기만으로 구조가 결정됩니다.

올바른 작성 예시입니다.

database:
  host: localhost
  port: 5432
  credentials:
    user: admin
    password: secret

database는 매핑이며 host, port, credentials를 포함합니다. credentials는 다시 내포된 매핑입니다. 2칸의 들여쓰기로 전체 구조를 한눈에 파악할 수 있습니다.

키-값 쌍(매핑) 작성법

매핑은 key: value 형식으로 작성합니다. 콜론(:) 뒤에는 반드시 반각 공백이 필요합니다. key:value처럼 공백을 생략하면 매핑이 아니라 하나의 문자열로 인식됩니다.

name: Alice
age: 30
is_admin: true
bio: null

키는 보통 단순한 문자열이지만, 따옴표로 감싸면 공백을 포함할 수도 있습니다.

"full name": Alice Cooper

값에는 스칼라, 시퀀스, 매핑 등 YAML에서 지원하는 모든 데이터 타입을 둘 수 있습니다.

리스트(시퀀스) 작성법

시퀀스는 줄 맨 앞에 - (하이픈 + 반각 공백)을 붙여 작성합니다.

fruits:
  - apple
  - banana
  - cherry

리스트 안에는 매핑을 중첩해서 넣을 수도 있습니다.

users:
  - name: Alice
    role: admin
  - name: Bob
    role: editor

각 하이픈이 새로운 리스트 항목의 시작을 나타내며, 다음 하이픈이 나오기 전까지의 내용이 해당 항목에 속합니다.

블록 스타일과 플로우 스타일

지금까지 살펴본 방식은 모두 블록 스타일(Block style)입니다. 한 줄에 한 항목씩 적고 들여쓰기로 중첩을 나타냅니다. 반면 YAML은 JSON과 유사한 인라인 플로우 스타일(Flow style)도 지원합니다.

fruits: [apple, banana, cherry]
users: [{name: Alice, role: admin}, {name: Bob, role: editor}]

플로우 스타일은 짧은 리스트를 간단히 작성할 때는 편리하지만, 데이터가 커지면 가독성이 급격히 떨어집니다. 실무 파일에서는 블록 스타일을 기본으로 사용하는 것이 안전합니다. 플로우 스타일에서 대괄호 [를 닫지 않으면 파서마다 다른 오류를 출력합니다(자세한 내용은 뒤의 파서별 오류 표를 참고하세요).

문자열과 따옴표: 언제 감싸야 하는가

YAML에서 문자열은 대부분 따옴표 없이 그대로 쓸 수 있습니다.

greeting: Hello, world

따옴표가 반드시 필요한 경우는 다음과 같습니다.

  • 다른 데이터 타입으로 잘못 해석될 여지가 있는 경우: version: "1.0", country: "NO", postal_code: "07030"
  • 값이 YAML 구조 문자로 시작하는 경우: [, ], {, }, ,, *, |, >, %, @, `, ", ', #, &, !. 맨 앞의 -, :, ?는 바로 뒤에 공백이 이어질 때만 문제가 됩니다.
  • 값 안에 콜론 + 공백(: )이 포함된 경우(매핑으로 오인될 수 있음)
  • \n이나 \t 같은 이스케이프 시퀀스를 사용하고 싶은 경우

작은따옴표(')와 큰따옴표(")를 모두 쓸 수 있습니다. 큰따옴표는 이스케이프 시퀀스를 해석하지만, 작은따옴표는 작성된 그대로의 리터럴 문자열로 다룹니다.

escaped: "line1\nline2"
literal: 'line1\nline2'

실제 문제가 되는 문자들은 두 그룹으로 나뉘며, 그 그룹이 따옴표의 필요 여부를 결정합니다. 다음 표는 본 사이트의 변환 도구가 사용하는 파서(yaml (eemeli) 2.8.3, YAML.parse 기본 설정)의 동작 방식입니다(2026-08-15 실측, 재현 스크립트는 저장소 내 scripts/benchmarks/yaml-quote-requirements/). 가운데 열이 "안전"이라면 해당 문자가 맨 앞에 오지 않는 한 따옴표 없이 쓸 수 있습니다.

문자값의 맨 앞에 둘 때값의 중간에 둘 때작은따옴표로 충분한가큰따옴표 사용
[ ] { } ,파싱 오류안전충분함사용 가능
*파싱 오류(별칭으로 해석)안전충분함사용 가능
&오류 없이 앵커로 처리되어 값이 사라짐안전충분함사용 가능
!오류 없이 태그로 처리됨안전충분함사용 가능
#오류 없이 값 전체가 주석 처리되어 null이 됨바로 앞에 공백이 없으면 안전충분함사용 가능
| >파싱 오류(블록 스칼라로 해석)안전충분함사용 가능
% @ `파싱 오류(예약 문자)안전충분함사용 가능
- ?단독은 안전, 직후 공백 시 파싱 오류안전충분함사용 가능
:단독은 안전, 직후 공백 시 파싱 오류직후 공백이 오면 위치 불문 파싱 오류충분함사용 가능
"파싱 오류안전충분함\" 이스케이프 필요
'파싱 오류안전부족함. ''로 중복 표기이쪽을 사용하는 편이 무난

이 결과에서 두 가지 중요한 사실을 알 수 있습니다. 값의 중간에서 위험한 것은 : #뿐이므로 url: http://example.com/a,b는 따옴표 없이 그대로 적어도 안전합니다. 그 외에는 모두 맨 앞 글자에서만 발생하는 문제입니다. 또 하나는 작은따옴표가 작은따옴표 문자 자체를 제외한 거의 모든 경우를 안전하게 감쌀 수 있다는 점입니다. Windows 경로 문자열이나 정규식을 적을 때 작은따옴표가 더 안전한 이유이며, \n이나 \t를 실제 줄바꿈과 탭으로 해석시키고 싶을 때만 큰따옴표를 사용하세요.

템플릿 문법 {{ }}을 값의 맨 앞에 쓰면 깨지는 이유

Helm 템플릿이나 Ansible의 변수 전개를 렌더링되지 않은 상태 그대로 YAML 파서에 넘기면 { 문자가 특수 문자로 인식되는 함정에 빠집니다.

# 렌더링 전의 Helm 템플릿
image: {{ .Values.image }}

{{는 플로우 매핑이 2번 중첩되어 시작된 형태로 해석됩니다. 게다가 실패하는 방식도 파서마다 다릅니다. 실측 조사(2026-07-12, 재현 스크립트는 저장소 내 scripts/benchmarks/yaml-syntax-errors/)에 따르면 PyYAML과 ruamel.yaml은 found unhashable key 오류로 중단되지만, js-yaml과 eemeli/yaml은 오류를 내지 않고 {"image": {"[object Object]": null}}과 같이 깨진 객체를 조용히 반환합니다. 오류가 발생하지 않기 때문에 파이프라인 후반부에 가서야 문제를 발견하게 되는 골치 아픈 패턴입니다.

해결 방법은 두 가지입니다. 값 전체를 따옴표로 감싸 문자열로 만들거나(image: "{{ .Values.image }}"), 템플릿이 렌더링된 이후의 완성된 YAML만을 검증 대상으로 삼는 것입니다. 참고로 GitHub Actions의 ${{ }}$ 문자로 시작하므로 플로우 매핑으로 해석되지 않아 이 문제가 발생하지 않습니다.

여러 줄 문자열(멀티라인)

긴 텍스트 블록을 표현할 때는 두 가지 연산자를 사용합니다.

리터럴 블록 |는 소스 코드의 줄바꿈을 그대로 유지합니다.

description: |
  이것이 첫 번째 줄입니다.
  이것이 두 번째 줄입니다.

  빈 줄 뒤의 네 번째 줄입니다.

폴디드 스칼라(Folded scalar) >는 줄바꿈을 하나의 공백으로 접어 주므로, 소스 코드에서 길게 줄바꿈해 적은 문장을 한 줄로 묶을 때 유용합니다.

paragraph: >
  이 긴 문장은 소스 코드 안에서
  여러 줄로 나뉘어 작성되었지만,
  YAML은 이를 한 줄로 합쳐서 처리합니다.

촘프(Chomp) 지시자: 줄바꿈 제거(strip), 유지(clip), 보존(keep)

YAML의 블록 스칼라에는 텍스트 끝의 줄바꿈을 어떻게 다룰지 결정하는 촘프(Chomp) 지시자가 있습니다. 지시자는 | 또는 > 바로 뒤에 붙여 적습니다.

지시자동작 방식예시
(없음) — clip마지막 줄바꿈 1개만 남김. 기본값.|
- — strip마지막 줄바꿈을 모두 제거함.|- >-
+ — keep마지막 빈 줄을 모두 그대로 보존함.|+ >+
clip: |
  line one
  line two
strip: |-
  line one
  line two
keep: |+
  line one
  line two

접기 형식(>, >-, >+)에도 동일한 3가지 모드가 적용됩니다. |-는 YAML을 JSON이나 환경 변수에 삽입할 때 마지막 줄바꿈이 불필요한 경우에 사용합니다. |+는 셸 스크립트를 생성할 때처럼 파일 끝의 빈 줄이 의미를 가질 때 사용합니다.

타입과 파서의 타입 추론

YAML은 따옴표가 없는 값에서 데이터 타입을 자동으로 추론합니다. 동일한 표기라도 파서가 구현한 YAML 버전과 스키마에 따라 정수, 부동소수점, 날짜, 문자열 중 하나로 다르게 처리될 수 있습니다.

integer: 42
hex: 0xFF              # 255 (정수, 16진수)
octal: 0o17            # 15 (정수, 8진수, YAML 1.2)
octal_legacy: 0644     # 420 (정수, 8진수, YAML 1.1) — 파일 권한 모드 함정
float: 3.14
negative: -7
exponential: 1e3       # 1000.0 (부동소수점, 지수 표기법)
infinity: .inf         # +Infinity (부동소수점)
negative_infinity: -.inf
not_a_number: .nan     # NaN (부동소수점)
boolean_true: true
boolean_false: false
null_value: null
tilde_null: ~
date: 2026-04-13
timestamp: 2026-04-13T09:30:00Z

이 값들은 모두 따옴표로 감싸면 문자열로 고정할 수 있습니다.

version_string: "1.0"    # 숫자 1.0이 아닌 문자열
zip_code: "07030"        # 숫자 7030이 아닌 문자열
file_mode: "0644"        # 8진수 정수가 아닌 문자열

다음 표는 따옴표 없는 리터럴이 최신 YAML 1.2 Core 스키마 로더(PyYAML, js-yaml, SnakeYAML 기본값)와 YAML 1.1 로더(구형 PyYAML, Symfony YAML)에서 각각 무엇으로 변환되는지 정리한 것입니다. 대부분의 예상치 못한 버그는 이 두 열의 차이에서 발생합니다.

리터럴YAML 1.2 CoreYAML 1.1주의점
42integer (42)integer (42)
0xFFinteger (255)integer (255)16진수 파싱은 사양에 정의된 동작
0o17integer (15)(인식되지 않음)YAML 1.2 전용
0644integer (644)integer (420, 8진수)파일 모드 해석이 버전에 따라 달라짐
1e3float (1000.0)float (1000.0)일부 도구는 표시 시 .0을 생략
.inf / -.inffloat (±Infinity)float (±Infinity)JSON으로 직렬화 불가능
.nanfloat (NaN)float (NaN)JSON으로 직렬화 불가능
2026-04-13stringdate (날짜 객체)JSON ↔ YAML 왕복 시 타입 변경
2026-04-13T09:30Zstringtimestamp동일한 문제 발생
true / falsebooleanboolean
yes / no / on / offstringboolean"Norway problem"
NOstringboolean (false)다음 절에서 상세 설명
~ / null / Null / NULLnullnull대소문자 표기 무관하게 null
1.0float (1.0)float (1.0)일부 도구에서 1로 재직렬화됨

실무 환경에서 파서를 다룬다면 가장 오른쪽 열에 있는 항목들을 잠재적 버그 요인으로 취급해야 합니다. 현재 사용 중인 로더가 어떤 버전을 사용하는지 확인하는 가장 빠른 방법은 대표 파일을 FormatArc YAML to JSON 변환기에 붙여넣어 JSON 출력을 확인하는 것입니다. "NO"인지 false인지, "2026-04-13"인지 ISO 날짜 문자열인지 바로 판별할 수 있습니다.

이 두 열의 차이가 생기는 원인은 YAML 1.1과 YAML 1.2의 타입 추론 정의가 다르기 때문입니다. YAML 1.1은 타임스탬프, 60진수(base-60), Norway problem을 일으키는 광범위한 불리언 어휘를 암묵적 타입 태그로 포함하고 있었습니다. YAML 1.2는 이를 보다 엄격한 Core 스키마새 탭에서 열립니다로 교체했습니다. Core 스키마는 불리언을 truefalse로 제한하고(사양의 Core 정규식은 첫 글자 대문자나 전체 대문자 True/TRUE/False/FALSE도 허용하지만 yes/no/on/off는 더 이상 불리언으로 받지 않습니다), 암묵적 타임스탬프 및 60진수 태그를 폐지하여 JSON의 값 타입을 그대로 따르도록 정리했습니다. 구체적인 규칙은 YAML 1.2.2 사양새 탭에서 열립니다에 공개되어 있습니다. 두 도구가 따옴표 없는 값의 해석에서 충돌한다면, 한쪽은 1.1 규칙을, 다른 쪽은 1.2 Core 스키마를 구현하고 있을 가능성이 높습니다.

Norway problem — NO가 false로 바뀌는 함정

YAML에서 가장 유명한 함정이 바로 "Norway problem"입니다. YAML 1.1 파서(PyYAML, Symfony YAML, 구형 SnakeYAML 등 현재도 널리 쓰임)는 따옴표 없는 NO를 불리언 false로 해석합니다. 국가 코드 목록을 다음과 같이 작성하면:

countries:
  - DE
  - FR
  - NO
  - SE

파싱되는 순간 ["DE", "FR", false, "SE"]로 변환되어 버립니다. YES, ON, OFF, Y, N 및 대소문자 변형에 대해서도 파서에 따라 동일한 문제가 발생합니다.

해결 방법은 오인될 수 있는 값을 항상 따옴표로 감싸는 것입니다.

countries:
  - "DE"
  - "FR"
  - "NO"
  - "SE"

YAML 1.2에서는 불리언이 true / false로 한정되었지만, 실무 도구 상당수는 여전히 1.1 기반 로더를 내장하고 있습니다. 국가 코드, 언어 코드, 버전 문자열, 짧은 식별자는 모두 따옴표로 감싸 두는 것이 안전합니다. 파서 호환성을 확인하고 싶다면 FormatArc YAML to JSON 변환기에 붙여넣어 JSON 결과에서 "NO"가 문자열로 남아 있는지 즉시 검증할 수 있습니다.

엄격한 최신 불리언 집합은 YAML 1.2.2 사양새 탭에서 열립니다에, 레거시 도구가 구현 중인 규칙은 YAML 1.1 사양새 탭에서 열립니다에 정의되어 있습니다.

주석

주석은 #부터 줄 끝까지 작성합니다. 단독 줄에도 쓸 수 있고 값 뒤에 덧붙일 수도 있습니다.

# 업스트림 요청의 최대 재시도 횟수
retries: 3  # 이 이상 늘리면 업스트림 타임아웃을 초과함

주석은 설정 파일에서 YAML이 JSON 대비 갖는 가장 큰 장점 중 하나입니다. "무엇을 하고 있는지"보다는 "왜 이 값을 설정했는지"를 설명하는 데 활용하세요. JSON으로 변환하면 주석이 모두 사라지므로 YAML을 원본 파일로 관리하는 것이 좋습니다. JSON에서 주석을 작성해야 하는 상황이라면 JSON 주석 작성 방법에서 JSONC 및 JSON5 우회 방법을 확인할 수 있습니다.

앵커와 별칭으로 재사용하기

YAML은 &로 앵커(Anchor)를 지정하고 *로 별칭(Alias)을 참조할 수 있습니다. 또한 <<: 병합 키(Merge key)를 사용하여 매핑을 기본값으로 가져올 수 있습니다.

defaults: &defaults
  adapter: postgres
  host: db.internal
  pool: 5

development:
  <<: *defaults
  database: myapp_dev

production:
  <<: *defaults
  database: myapp_prod
  pool: 20

productiondefaults의 설정을 물려받으면서 pool 값만 덮어쓰고 있습니다. 환경별 설정을 복사-붙여넣기하지 않고 공통화할 수 있는 깔끔한 작성법입니다.

병합 키(<<:)로 설정 공유하기

<<: 병합 키는 앵커와 함께 쓰일 때 가장 강력합니다. 특정 매핑의 키들을 다른 매핑으로 가져올 수 있으므로 "기본 설정과 같지만 특정 항목만 오버라이드"하는 구조를 중복 없이 표현할 수 있습니다. Docker Compose, GitLab CI, Rails의 database.yml 등 다양한 설정 파일에서 빈번하게 등장합니다.

base: &base
  image: node:20
  restart: unless-stopped
  environment:
    NODE_ENV: production

services:
  api:
    <<: *base
    command: npm run start:api
  worker:
    <<: *base
    command: npm run start:worker
    environment:
      NODE_ENV: production
      WORKER_QUEUE: high

사용 시 주의할 점이 2가지 있습니다.

  • 병합 키는 1단계(얕은 병합)로만 합성됩니다. 중첩된 매핑(위 예제의 environment 등)은 깊은 병합(Deep merge)되지 않고 통째로 덮어씌워집니다.
  • 병합 키는 YAML 1.1 사양의 기능입니다. 엄격한 YAML 1.2 전용 파서는 이를 무시할 수 있으나, Docker Compose나 GitLab CI는 여전히 1.1 세맨틱을 지원하므로 문제없이 동작합니다.

스키마와 태그: YAML이 타입을 결정하는 방식

YAML 1.2는 따옴표 없는 리터럴의 해석 방식을 제어하는 3가지 스키마를 정의합니다.

  • FailSafe — 문자열, 매핑, 시퀀스만 지원합니다. 가장 안전한 스키마로 다른 모든 리터럴은 문자열이 됩니다. 기본값으로 쓰이는 경우는 거의 없습니다.
  • JSON — JSON 호환 타입(문자열, 정수, 부동소수점, 불리언, null, 매핑, 시퀀스)을 지원하며 JSON.parse가 생성하는 결과와 일치합니다.
  • Core — 일반적인 기본값입니다. 앞서 살펴본 타입 추론 규칙(16진수, 8진수, .inf, .nan, ~)을 추가로 지원합니다.

대부분의 파서는 Core를 기본 탑재합니다(PyYAML의 safe_load, js-yaml의 기본값, SnakeYAML의 SafeConstructor). 반면 Symfony YAML은 여전히 YAML 1.1 세맨틱을 기본값으로 사용합니다.

원하는 타입과 다르게 추론되는 경우 — 예를 들어 문자열로 다루고 싶은데 version: 1.0이 부동소수점으로 파싱되는 경우 — 명시적 태그를 붙여 타입을 강제할 수 있습니다.

version: !!str 1.0       # 문자열 "1.0"으로 강제
count: !!int "42"        # 따옴표가 있어도 정수 42로 강제
empty: !!null ""         # 빈 문자열 대신 명시적 null로 처리

!! 접두사는 기본 태그 라이브러리의 표준 태그를 쓴다는 의미입니다. 단일 !로 시작하는 커스텀 태그(예: AWS CloudFormation의 !Ref)는 파서가 해당 태그를 별도로 인식하도록 구현되어 있어야 합니다. 일반 애플리케이션 수준의 YAML 파일에서는 타입 혼동을 방지하기 위해 !!str 정도만 알아두면 충분합니다.

멀티 다큐먼트(여러 문서 한 파일에 작성)

하나의 YAML 파일 안에 여러 개의 독립된 문서를 넣을 수 있습니다. 구분자는 --- 단독 줄입니다.

---
kind: Service
name: web
---
kind: Deployment
name: web
replicas: 3

Kubernetes에서 여러 매니페스트를 한 파일로 묶어 관리할 때 자주 사용하는 형태입니다. JSON에는 이에 대응하는 표준 구조가 없으므로 변환 시 특정 문서를 선택하거나 바깥을 배열로 감싸야 합니다. 정적 사이트 생성기(SSG)의 마크다운 프론트매터 YAML을 JSON으로 변환하는 방법은 마크다운 프론트매터 YAML을 JSON으로 변환하기를 참고하세요.

앵커·병합 키·멀티 다큐먼트 호환성 비교 (실측)

앵커, 병합 키, 멀티 다큐먼트는 YAML 문법상 유효하지만 실행 환경과 파서에 따라 지원 여부가 갈리는 대표적인 기능들입니다. 파서 4종과 Docker Compose는 직접 실측하였고(2026-07-12 실측, 재현 스크립트는 저장소 내 scripts/benchmarks/yaml-tool-acceptance/), 호스팅 서비스는 공식 문서를 확인했습니다.

환경앵커 & *병합 키 <<:멀티 다큐먼트 ---
js-yaml지원(실측)지원(실측)load는 오류. loadAll로 지원(실측)
PyYAML지원(실측)지원(실측)safe_load는 오류. safe_load_all로 지원(실측)
yaml (eemeli) (FormatArc 변환기가 사용하는 파서)지원(실측)기본 설정에서는 전개되지 않고 <<가 문자 그대로의 키로 남음(실측)parse는 오류. parseAllDocuments로 지원(실측)
Docker Compose v5.3.0지원(실측)지원(실측)여러 문서를 하나의 구성으로 병합하여 수용(실측)
GitHub Actions2025-09-18부터 지원새 탭에서 열립니다미지원 — 사용 시 구문 오류새 탭에서 열립니다공식 문서에 언급 없음
GitLab CI지원새 탭에서 열립니다지원새 탭에서 열립니다공식 문서에 언급 없음
Kubernetes (kubectl)공식 문서에 명시 없음공식 문서에 명시 없음지원새 탭에서 열립니다

이 표에서 주목해야 할 핵심은 3가지입니다.

  • GitHub Actions는 앵커는 지원하지만 병합 키는 지원하지 않습니다. 2025년 9월 앵커 지원이 추가된 이후에도 <<:는 구문 오류가 발생하므로, GitLab CI의 워크플로를 그대로 복사해 올 수 없습니다.
  • eemeli/yaml은 기본적으로 YAML 1.2를 준수하므로 YAML 1.1 사양인 병합 키를 자동으로 전개하지 않습니다. 파싱 오류 없이 {"<<": {...}} 키가 그대로 남아 의도치 않은 버그가 될 수 있습니다.
  • 멀티 다큐먼트는 사용하는 API 함수에 따라 다릅니다. 4가지 파서 모두 단일 문서 로드 API에서는 오류를 내며, 다중 문서 전용 API로 전환해야 정상 처리됩니다.

실무에서 YAML을 작성하는 3가지 대표 사례

몇 줄짜리 설정 파일이든 대규모 배포 매니페스트든 적용되는 문법 규칙은 동일합니다. 2026년 실무 개발에서 YAML을 가장 빈번하게 다루는 3가지 대표적인 환경을 살펴봅니다.

Kubernetes Deployment 매니페스트

최소 구성의 Deployment에서도 매핑, 시퀀스, 멀티라인 문자열, 불리언 값이 모두 등장합니다. spec.template.spec.containers 부근의 들여쓰기 실수가 대표적인 오류 유형입니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
          env:
            - name: FEATURE_FLAG_NEW_HEADER
              value: "true"      # 의도적인 따옴표 — 따옴표가 없으면 불리언으로 처리됨
          resources:
            limits:
              cpu: "500m"
              memory: 256Mi

value: "true"를 따옴표로 감싸는 것이 중요합니다. 따옴표를 생략하면 Kubernetes가 불리언 값으로 인식하여 환경 변수에 True(Python 스타일)가 전달되거나 컨테이너 실행에 실패할 수 있습니다.

GitHub Actions 워크플로

GitHub Actions 워크플로는 깊게 중첩된 매핑과 run 블록의 멀티라인 셸 스크립트가 자주 등장합니다. |(리테럴)과 >(폴디드)의 구분이 유용하게 쓰이는 곳입니다.

name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"      # 뒤의 0을 유지하기 위해 따옴표 처리
      - name: Install
        run: npm ci
      - name: Test
        run: |
          npm run lint
          npm run build
          npm test -- --run

여기서 가장 잦은 실수는 node-version: "20"의 따옴표를 지우는 것입니다. YAML이 정수 20으로 강제 변환하여 setup-node 버전에 따라 파싱 오류가 발생할 수 있습니다. 숫자처럼 보이지만 문자열이어야 하는 값은 반드시 따옴표로 감싸세요.

Docker Compose 서비스 정의

Docker Compose 파일은 매핑, 시퀀스, 환경 변수 사전, 바인드 마운트 문자열이 혼합된 간결한 YAML입니다. 들여쓰기 감각을 익히기에 적합합니다.

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"               # 60진수로 해석되지 않도록 따옴표 처리
    environment:
      NGINX_HOST: example.com
      NGINX_PORT: "80"          # 따옴표 필수: 환경 변수 값은 문자열이어야 함
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api
  api:
    build: ./api
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 5s
      retries: 3

주의할 함정은 2가지입니다. "8080:80"의 따옴표를 빼면 YAML 1.1 파서가 60진수로 파싱할 수 있다는 점과, environment: 하위 항목은 최종적으로 문자열로 전달되므로 따옴표를 붙이는 것이 안전하다는 점입니다.

자주 발생하는 실수와 파서별 오류 메시지 비교 (실측)

많은 개발자가 겪는 대표적인 YAML 오류 유형입니다.

  • 탭 문자로 들여쓰기한 경우 — 눈에 보이지 않는 탭이 섞여 원인 파악이 어려움
  • 콜론 뒤에 공백이 없는 경우 — key:value가 하나의 문자열로 취급됨
  • 들여쓰기 너비가 불일치하는 경우 — 같은 계층의 요소는 동일한 깊이여야 함
  • 따옴표 없는 NO, OFF, YES, ON이 불리언으로 변환되는 경우 (Norway problem)
  • 따옴표 없는 값 안에 콜론이 포함된 경우 — time: 10:30이 60진수로 해석될 수 있음
  • 블록 스타일과 플로우 스타일이 잘못 혼합된 경우
  • 동일 매핑 내에서 중복 키를 사용한 경우 — 구현체에 따라 동작이 달라짐

오류 메시지로 검색할 때 가장 난감한 점은 동일한 실수라도 파서마다 완전히 다른 메시지를 출력한다는 사실입니다. 대표적인 6가지 오류를 js-yaml, yaml (eemeli), PyYAML에 입력하여 실제 출력된 오류 메시지를 기록했습니다(2026-07-12 실측, ruamel.yaml을 포함한 4종 파서의 원본 로그와 재현 스크립트는 저장소 내 scripts/benchmarks/yaml-syntax-errors/).

실수 내용js-yaml 오류 메시지yaml (eemeli) 오류 메시지PyYAML 오류 메시지
탭 문자로 들여쓰기tab characters must not be used in indentation (2행)Tabs are not allowed as indentation (2행)found character '\t' that cannot start any token (2행)
들여쓰기 불일치(2칸과 3칸 혼용)bad indentation of a mapping entry (3행)Nested mappings are not allowed in compact mappings (2행)mapping values are not allowed here (3행)
값 내부의 따옴표 없는 : (url: http://x.com: 8080)bad indentation of a mapping entry (1행 24열)Nested mappings are not allowed in compact mappings (1행 6열)mapping values are not allowed here (1행 24열)
큰따옴표 닫기 누락unexpected end of the stream within a double quoted scalar (마지막 행)Missing closing "quote (2행 8열)while scanning a quoted scalar ... found unexpected end of stream (시작 따옴표 위치 지목)
정의되지 않은 앵커로의 *aliasunidentified alias "missing"Unresolved alias (the anchor must be set before the alias): missing (줄 번호 미표시)found undefined alias 'missing'
플로우 [ 닫기 누락missed comma between flow collection entries (다음 행)Flow sequence in block collection must be sufficiently indented and end with a ] (2행)while parsing a flow sequence ... expected ',' or ']'

오류를 해석하는 3가지 팁입니다. 첫째, PyYAML의 mapping values are not allowed here와 js-yaml의 bad indentation of a mapping entry는 서로 다른 오류처럼 보이지만 모두 "매핑이 올 수 없는 위치에 : 가 있다"는 동일한 원인을 가리킵니다. eemeli의 Nested mappings are not allowed in compact mappings 역시 같은 원인에 대한 다른 표현입니다. 둘째, 파서마다 보고하는 오류 줄 번호가 다릅니다. 따옴표를 닫지 않은 경우 js-yaml은 파일 끝을, PyYAML은 시작 따옴표 위치를 가리키므로 오류 줄의 앞뒤 1줄과 따옴표 시작 위치를 함께 확인해야 합니다. 셋째, eemeli는 js-yaml보다 1줄 앞을 가리킬 수 있는데, 이는 오류가 터진 위치가 아니라 콤팩트 매핑이 시작된 위치를 보고하기 때문입니다.

이러한 실수를 가장 빠르게 찾아내는 방법은 도구에 검증을 맡기는 것입니다. 설치 없이 확인하려면 FormatArc YAML to JSON 변환기에 붙여넣으면 됩니다. 올바른 YAML이라면 즉시 JSON이 표시되고, 문법 오류가 있다면 오류 내용과 함께 확인해야 할 줄 번호가 표시됩니다.

"It is forbidden to specify block composed value at the same line as key" 오류 해결

이 오류는 JetBrains/IntelliJ 계열 IDE(IntelliJ IDEA, PyCharm, GoLand, Rider, DataGrip)의 YAML 검사기(Inspection)가 출력하는 메시지입니다. 문구 자체는 YAMLBundle.properties새 탭에서 열립니다annotator.same.line.composed.value.message로 정의되어 있습니다.

의미는 단 하나, 블록 컬렉션이 키와 같은 줄에서 시작되었다는 뜻입니다. 검사기 소스 코드새 탭에서 열립니다를 확인하면 검사 대상은 정확히 두 가지 형태뿐입니다. 블록 시퀀스의 첫 번째 요소가 키와 같은 줄에 있거나, 블록 매핑의 첫 번째 키-값이 키와 같은 줄에 있는 경우입니다.

형태 1: 블록 시퀀스가 키 줄에서 시작되는 경우

# Inspection 오류가 발생하는 형태
key: - item1
     - item2

해결 방법: 첫 번째 항목을 다음 줄로 내립니다.

key:
  - item1
  - item2

형태 2: 블록 매핑이 키 줄에서 시작되는 경우

# Inspection 오류가 발생하는 형태
key: sub: value
     sub2: value2

해결 방법: 콜론 뒤에서 줄바꿈을 합니다.

key:
  sub: value
  sub2: value2

두 형태 모두 IDE의 단순한 취향 문제가 아니라 YAML 사양상 잘못된 문법입니다. 파서들 역시 거부하며, yaml 패키지의 경우 형태 1에 Unexpected block-seq-ind on same line with key, 형태 2에 Nested mappings are not allowed in compact mappings를 반환합니다.

중복 키 검사와는 다른 오류입니다. 매핑 내 키가 중복된 경우에는 Key 'x' is duplicated라는 별도 메시지가 나옵니다(YAMLDuplicatedKeysInspection.duplicated.key). 키가 중복되었다는 알림이 떴다면 키 이름을 바꾸거나 상위 노드를 분리해야 하며, 블록 컬렉션의 위치와는 무관합니다.

Helm이나 Jinja 템플릿에서 오류가 뜨는 경우: 검사기는 템플릿 언어 요소가 포함되어 있으면 검사를 조기 종료하도록 설계되어 있어 올바른 템플릿은 원래 플래그되지 않아야 합니다. 그럼에도 오류가 뜬다면 알려진 거짓 양성(False positive, 예: IJPL-64437새 탭에서 열립니다)이므로 파일 자체를 수정할 필요는 없습니다.

수정 후에는 YAML to JSON에 붙여넣어 블록 컬렉션이 정상적으로 처리되는지 확인할 수 있습니다. 모든 변환은 브라우저 내에서만 이루어지며 입력한 데이터는 외부로 전송되지 않습니다.

FormatArc로 브라우저에서 YAML 검증하기

FormatArc의 브라우저 전용 도구는 간이 YAML 린터 및 검증기로 바로 활용할 수 있습니다.

FormatArc YAML to JSON 변환기 화면에서 줄 번호와 함께 구문 오류가 표시된 화면FormatArc YAML to JSON 변환기 화면에서 줄 번호와 함께 구문 오류가 표시된 화면

  • YAML to JSON — YAML을 붙여넣어 JSON으로 변환하고, 오류 시 줄 번호와 함께 진단 결과 확인
  • JSON to YAML — JSON을 바탕으로 이에 대응하는 YAML 구조를 학습하고 변환
  • JSON Formatter — 변환된 JSON 데이터를 보기 좋게 정렬하고 포맷팅

모든 처리가 브라우저 로컬 환경에서 완료됩니다. 사내 내부 설정 파일이나 시크릿 값이 포함된 데이터라도 외부 유출 걱정 없이 안전하게 검증할 수 있습니다.

자주 묻는 질문

YAML 들여쓰기에 탭(Tab)을 사용할 수 있나요?

사용할 수 없습니다. YAML 사양은 오직 스페이스만을 허용하며 탭 문자가 섞이면 대부분의 파서에서 구문 오류가 발생합니다. .yml이나 .yaml 파일을 편집할 때는 Tab 키를 눌렀을 때 2칸 스페이스가 입력되도록 에디터를 설정하세요.

.yml.yaml의 차이는 무엇인가요?

차이가 없습니다. 두 확장자 모두 모든 YAML 파서에서 동일하게 처리됩니다. 공식 사양에서는 .yaml을 권장하지만 실무에서는 .yml도 널리 쓰이고 있습니다.

문자열은 항상 따옴표로 감싸야 하나요?

아닙니다. YAML에서는 기본적으로 따옴표 없이 문자열을 작성할 수 있습니다. 다른 타입(불리언, 숫자 등)으로 오인될 수 있는 값이나 -, :, [, {, |, > 등 특수 문자로 시작하는 값에만 따옴표를 붙이면 됩니다.

version: 1.0이라고 적었는데 1로 바뀌는 이유는 무엇인가요?

YAML이 1.0을 부동소수점 숫자로 파싱하고, 일부 직렬화 도구가 이를 정수 1로 다시 출력하기 때문입니다. 문자열 형태로 유지하고 싶다면 version: "1.0"과 같이 따옴표로 감싸야 합니다.

들여쓰기 공백 수는 몇 칸이 적절한가요?

2칸(2스페이스)이 표준적인 관례입니다. Kubernetes, Docker Compose, GitHub Actions 등 대부분의 공식 예제가 2칸을 사용합니다. 4칸으로 작성해도 문법상 유효하지만 파일 내에서는 일관된 너비를 유지해야 합니다.

프로그램을 설치하지 않고 YAML을 검증하는 방법은 무엇인가요?

FormatArc YAML to JSON 변환기에 붙여넣기만 하면 바로 검증할 수 있습니다. 유효한 YAML이면 JSON 출력이 즉시 생성되고, 오류가 있다면 문제 위치의 줄 번호가 함께 표시됩니다.

하나의 파일에 여러 개의 YAML 문서를 넣을 수 있나요?

가능합니다. --- 단독 줄을 구분자로 사용하면 됩니다. Kubernetes에서 여러 개의 매니페스트를 하나의 파일로 묶어 배포할 때 사용하는 표준적인 방식입니다.

정리

  • YAML은 괄호 대신 들여쓰기로 구조를 표현합니다.
  • 들여쓰기는 스페이스만 사용해야 하며 일관성이 필수입니다.
  • 문자열은 잘못 해석될 우려가 있는 경우에만 따옴표로 감쌉니다.
  • 주석, 멀티라인 텍스트, 앵커를 활용하면 설정 파일의 가독성과 재사용성을 크게 높일 수 있습니다.
  • 작성한 YAML의 구문 검증은 FormatArc YAML to JSON 도구에 붙여넣어 빠르게 확인할 수 있습니다.