체인지로그 파일 형식, JSON인가 YAML인가 그냥 Markdown인가
4분 분량
대부분의 팀은 체인지로그를 Markdown 파일로 시작한다, 그것이 저항이 가장 적은 길이기 때문이다: pull request의 diff에서 읽을 수 있고, 아무것도 렌더링하지 않고 GitHub에서 읽을 수 있으며, README를 써본 적 있는 누구에게나 친숙하다. 그 선택은 사람이 아닌 무언가, 페이지, 위젯, 이메일 다이제스트가 파일을 읽어야 할 때까지는 잘 작동하고, 그때 형식은 공짜이기를 멈춘다. 체인지로그 자동화는 구조적 요구사항을 일반적으로 다룬다, 타입, 날짜, 본문, 링크. 이것은 어떤 파일 형식이 실제로 그 구조를 전달하는지, 그리고 각각 그곳에 도달하는 데 무엇이 드는지에 관한 것이다.
단순한 Markdown 체인지로그의 문제는 무엇인가
없다, 무언가 그것을 다시 필드로 파싱해야 할 때까지는. 제목, 날짜, 그 아래 글머리 목록은 사람이 읽기에는 사소하지만 신뢰성 있게 파싱하기는 진짜 어렵다, Markdown에는 스키마가 없기 때문이다: 날짜는 제목에 있을 수도, 첫 줄에 굵게 있을 수도, 오래된 항목에서는 아예 빠져 있을 수도 있으며, 그 변형들 각각은 사람은 정확히 읽고 파서는 그렇지 못하는 유효한 Markdown이다. Markdown 체인지로그를 자동화하는 팀은 대개 항목의 포맷이 조금이라도 벗어나는 순간 깨지는, 정규식 기반의 자체 제작 파서를 쓰는 것으로 끝난다, 이는 흔히 일어난다, 쓸 때 일관성을 강제하는 것이 아무것도 없기 때문이다.
구조화된 형식이 실제로 주는 것은 무엇인가
모든 항목이 같은 형태를 가진다는 보장이며, 읽힐 때 추측되는 대신 쓰일 때 검증된다. 정의된 스키마를 가진 JSON이나 YAML 파일, 타입, 날짜, 버전, 대상, 본문, 링크는, 엄격한 API 응답이 그러하듯이 필수 필드가 빠지면 시끄럽게 실패한다. Markdown 파일은 그저 거기 있는 것을 렌더링할 뿐이다, 맞든 틀리든. 그 차이는 스크립트가 피드를 정렬하기 위해 각 항목의 날짜를 필요로 하고 항목의 절반이 그것을 다른 곳에 가지고 있는 날까지 보이지 않는다.
# CHANGELOG.yml
- date: 2026-09-05
type: breaking
version: v2
audience: api
body: "POST /invoices now rejects a currency mismatch instead of silently converting."
link: /blog/api-changelog/
그것은 사람이 읽을 수 있는 파일이 사라져야 한다는 뜻인가
아니다, 그리고 YAML이나 JSON 파일이 사람이 pull request에서 읽는 것 역할까지 겸하게 만들려는 시도는 대개 반대 방향의 실수다: 중첩된 JSON의 diff를 검토하는 것은 산문 한 문장을 검토하는 것보다 나쁘며, 표현 오류를 잡기 위해 데이터 구조를 머릿속으로 파싱해야 하는 검토자는 결국 표현 오류 잡기를 멈추는 검토자다. 두 형식은 공존할 수 있다: 구조화된 데이터는 자동화 파이프라인이 읽는 진실의 원천이고, 생성된 Markdown이나 HTML 렌더링은 사람이 실제로 검토하고 읽는 것이며, 손으로 옆에 유지되는 대신 구조화된 파일로부터 만들어진다.
| 형식 | 있는 그대로 사람이 읽을 수 있는가 | 커스텀 코드 없이 기계가 파싱할 수 있는가 | 흔한 실패 모드 |
|---|---|---|---|
| Markdown | 예 | 아니오 | 일관되지 않은 항목 형태가 단순한 파서를 깬다 |
| JSON | 나쁨 | 예 | 장황함; 손으로 편집하면 유효하지 않은 JSON이 되기 쉬움 |
| YAML | 그럭저럭 | 예 | 공백에 민감함; 잘못된 들여쓰기는 시끄럽지 않고 조용한 파싱 오류다 |
어느 구조화된 형식이 실제로 손으로 편집하기 더 쉬운가, JSON인가 YAML인가
YAML이다, 생성기 대신 손으로 항목을 쓰는 누구에게나. JSON이 모든 문자열과 중첩된 객체에 요구하는 따옴표 붙이기와 괄호 맞추기를 없애기 때문이다. 트레이드오프는 YAML의 공백 민감성이 JSON의 괄호 불일치가 보통 그러지 않는 방식으로 조용히 실패한다는 것이다: JSON 파서는 잘못된 형식의 입력을 곧바로 거부하는 반면, YAML 파서는 잘못 들여쓰인 파일을 받아들여 그냥 잘못된 구조로 파싱해버릴 수 있으며, 이는 그것이 일어났다는 것을 아무것도 알려주지 않기 때문에 더 나쁜 실패다. 항목이 항상 스크립트에 의해서만 쓰인다면, 이 트레이드오프는 대체로 사라지고 JSON의 더 엄격한 파싱이 더 안전한 기본 선택이 된다.
체인지로그 페이지는 그것을 공급하는 파일과 별개의 자체 구조화된 형식이 필요한가
별개의 것이 아니라, 다르게 렌더링된 같은 것이. 체인지로그 페이지는 JSON 피드와 schema.org 마크업을 통해 페이지 자체를 기계가 읽을 수 있게 만드는 법을 다룬다. 그 피드는 생성된 출력이지, 근본적인 파일과 동기화된 상태로 유지해야 할 두 번째 진실의 원천이 아니다. 소스 파일과 페이지의 피드라는 두 곳에서 구조화된 데이터를 손으로 유지하는 것이 그 둘이 결국 갈라지는 방식이며, 그래서 여기서 내려지는 파일 형식 결정은 이후의 모든 것, 페이지, 위젯, 이메일이 생성되는 유일한 것이어야 하고, 절대 손으로 복사되어서는 안 된다.
기존 Markdown 체인지로그를 구조화된 형식으로 변환하는 마이그레이션 비용은 가치가 있는가
보통 자동화가 실제 목표가 되었을 때만 그렇지, 그 전에는 아니다. GitHub README에 Markdown 파일을 발행하는 1인 프로젝트는 실질적인 자동화 필요가 없으며, 그것을 YAML로 변환하는 것은 의식 절차 외에는 아무것도 사지 못한다. 그 변환은 페이지, 요약 이메일, 공개 피드 같은 하나 이상의 다운스트림 소비자가 같은 데이터를 읽어야 할 때 스스로 값을 한다, 그것이 정확히 Markdown 파서의 비일관성이 유지하기 짜증나는 것을 넘어 눈에 띄게 잘못된 출력을 만들어내기 시작하는 지점이기 때문이다.
FAQ
Markdown 체인지로그를 형식을 완전히 바꾸지 않고 파싱 가능하게 만들 수 있는가? 부분적으로, frontmatter로: 산문을 위한 Markdown 본문 옆에 각 항목 맨 위의 작은 YAML 블록(날짜, 타입, 버전). 이것은 전체 항목을 JSON이나 YAML로 강제하지 않고도 파서가 필요로 하는 구조화된 필드를 얻으며, 완전한 마이그레이션에 아직 준비되지 않은 팀에게 합리적인 중간 지점이다.
파일 형식이 SEO나 체인지로그 페이지의 순위에 영향을 주는가? 직접적으로는 아니다. 검색 엔진은 렌더링된 페이지를 읽지 소스 파일을 읽지 않으므로 파일 형식은 그들에게 보이지 않는다. 페이지 자체에 중요한 것은 그것이 자체적으로 기계가 읽을 수 있는지 여부이며, 이는 무엇이 그것을 생성하는지와는 별개의 문제다.
모든 체인지로그 항목이 같은 파일을 거쳐야 하는가, 아니면 타입별로 여러 파일에 나눌 수 있는가? 하나의 파일이 항목 양이 diff나 검토를 불편하게 만들기 전까지는 더 단순하다. 연도나 카테고리별 분할은 하나의 파일의 diff가 합리적으로 검토하기에 너무 커질 때 합리적인 안전 밸브이지만, 다운스트림의 무언가가 “모든 항목”을 하나의 목록으로 읽을 수 있기 전에 병합 단계를 추가한다.
RSS에 표준이 있듯이 표준 체인지로그 파일 형식이 존재하는가? 널리 채택된 것은 없다. Keep a Changelog는 Markdown 관례를 제안하고, 여러 도구가 자체 형식을 가지고 있다. changeset은 패키지와 버전 올림 수준을 지정하는 YAML frontmatter가 붙은 Markdown 파일로, 앞에서 설명한 frontmatter 패턴 그대로다. 이들 중 어느 것도 RSS 리더가 보편적으로 RSS를 이해하듯이 다른 도구들이 바로 읽는 형식은 아니다.
이 글의 기술적 내용은 독립적으로 검토되지 않았습니다. 잘못된 부분이 있으면 알려 주세요. 바로잡겠습니다.