GitHub 릴리스 노트, 자동 생성한 뒤 읽히게 다듬는 법
5분 분량
GitHub 릴리스 노트는 저장소의 Releases 페이지에서 각 릴리스에 붙는 설명이며, GitHub는 이전 태그 이후 병합된 pull request를 바탕으로 그 초안을 대신 써 준다. 초안은 라벨별로 묶인 pull request 제목 목록에 기여자 줄과 비교 링크가 붙은 형태다. 정확하고 빠짐이 없지만, pull request를 병합한 사람들을 위해 쓰인 글이다. 프로젝트 사용자가 읽을 수 있는 글로 바꾸려면 .github/release.yml 파일 하나와 짧은 편집 과정이 필요하고, 둘 다 아래에서 설명한다.
| 노트를 만드는 방법 | 실행되는 곳 | 얻는 것 |
|---|---|---|
| “Generate release notes” 버튼 | 웹 UI의 릴리스 폼 | 마지막 태그 이후의 PR 제목, release.yml 카테고리로 묶임 |
gh release create v1.4.0 --generate-notes | GitHub CLI, 로컬 또는 CI | 같은 초안, 릴리스 생성과 함께 명령 하나로 |
POST /repos/{owner}/{repo}/releases/generate-notes | REST API | 릴리스를 만들지 않고 초안만 텍스트로, 자체 파이프라인용 |
| release-please, semantic-release, conventional-changelog | GitHub Actions 또는 릴리스 잡 | PR 제목 대신 커밋 메시지로 만든 노트, 버전 올리기와 CHANGELOG.md 포함 |
| 직접 작성 | 릴리스 폼 | 입력한 그대로, pull request로 돌아가는 링크 없음 |
GitHub에서 릴리스 노트를 자동으로 생성하려면 어떻게 하는가
릴리스 폼을 열고 태그를 고르거나 만든 뒤 “Generate release notes”를 누른다. GitHub는 이전 릴리스 태그를 찾고, 두 태그 사이에 대상 브랜치로 병합된 모든 pull request를 나열하며, pull request마다 제목, 작성자, 번호가 든 한 줄을 쓴다. 명령줄에서는 gh release create <tag> --generate-notes가 같은 일을 하면서 릴리스까지 한 번에 발행하고, --notes-start-tag로 범위가 시작하는 이전 태그를 바꿀 수 있다.
이 기능은 pull request를 기준으로 동작하므로, pull request 없이 main에 바로 병합하는 저장소는 빈 초안을 받는다. 스쿼시 병합은 괜찮다. pull request 자체는 남아 있기 때문이다. 오래 유지된 브랜치를 main으로 병합한 머지 커밋은 병합하는 pull request에 대한 한 줄만 만들고, 그 브랜치에 먼저 병합되었던 pull request들은 나오지 않는다. 범위가 이상해 보인다면 흔한 원인은 이전 태그가 없거나 순서가 어긋난 경우다. 생성기는 대상 브랜치의 최신 릴리스를 기준으로 삼으며, 릴리스가 붙지 않은 태그는 무시된다.
버튼은 자동 생성 릴리스 노트에 관한 GitHub Docs 페이지가, CLI 플래그는 gh release create 매뉴얼이 다룬다.
release.yml은 무엇을 바꾸는가
.github/release.yml은 생성기에 어떤 pull request를 빼고 나머지를 어떻게 묶을지 알려준다. 이 파일이 없으면 Dependabot까지 포함한 모든 pull request가 목록 하나에 들어간다. 파일이 있으면 pull request가 라벨에 따라 카테고리로 분류되고, 라벨이 붙었거나 봇이 만든 잡음은 사라진다.
# .github/release.yml
changelog:
exclude:
labels:
- skip-changelog
authors:
- dependabot
- renovate
categories:
- title: Breaking changes
labels:
- breaking-change
- title: New
labels:
- enhancement
- title: Fixed
labels:
- bug
- title: Other changes
labels:
- "*"
알아 둘 규칙이 셋 있다. 카테고리는 순서대로 대조되므로, breaking-change와 bug가 모두 붙은 pull request는 먼저 일치하는 제목 아래로 들어간다. 라벨 없는 pull request를 어떻게든 보이게 하려면 "*" 포괄 항목이 필요하다. 없으면 조용히 빠진다. 그리고 이 파일은 생성기가 쓰는 내용에만 영향을 주므로, 바꿔도 이미 있는 노트는 건드리지 않는다. CI의 체인지로그 검사를 위해 이미 pull request에 라벨을 붙이는 팀은 같은 라벨을 여기서 다시 쓸 수 있다.
자동 생성된 GitHub 릴리스 노트는 왜 읽기 나쁜가
pull request 제목은 변경이 끝나기 전에 리뷰어를 위해 쓰이고, 코드를 설명하기 때문이다. “Refactor export worker to use streaming”은 좋은 pull request 제목이지만 릴리스 노트로는 쓸모가 없다. 릴리스를 읽는 사람이 알고 싶은 것은 100MB가 넘는 내보내기가 더 이상 시간 초과되지 않는다는 사실이다.
두 번째 이유는 병합된 모든 pull request가 같은 무게를 갖는다는 점이다. 한 줄짜리 오타 수정이 새 인증 흐름 옆에, 병합된 순서대로 놓인다. 독자는 자기에게 영향을 주는 세 줄을 찾으려고 목록 전체를 훑어야 한다.
세 번째는 초안에 도입부가 없다는 것이다. 위에 문장 하나 없는 마흔 줄짜리 목록은 이 릴리스를 받아도 안전한지, 마이그레이션이 필요한지, 의존성 하나를 고정하려고 나온 것인지 누구에게도 말해 주지 않는다.
편집 과정에서는 무엇을 바꿔야 하는가
처음부터 다시 쓰지 말고, 생성된 목록은 그대로 두고 덧붙여라. 목록은 감사 추적이고, pull request 번호는 누군가가 한 줄을 diff까지 거슬러 올라가는 수단이다. 편집 과정은 생성기가 알 수 없는 부분을 더한다.
- 맨 위에 두세 문장을 써라. 이 릴리스가 무엇을 위한 것인지, 업그레이드에 조치가 필요한지, 무엇을 먼저 읽어야 하는지. 파괴적 변경이 있다면 첫 줄에서 말하라.
- 사람들이 신경 쓸 줄은 독자 쪽에서 다시 써라. 사라진 증상, 이제 할 수 있게 된 일, 옮겨진 설정. 줄 끝의 pull request 번호는 남겨 둔다. 전체 형태는 릴리스 노트를 쓰는 방법에 있고, 수정 항목만 따로 다루는 글은 버그 수정 릴리스 노트다.
- 독자가 해야 할 일은 별도 절로 옮겨라. 정확한 명령이나 설정과 함께. “Other changes” 목록에 묻힌 파괴적 변경은 일주일 뒤의 지원 티켓이다.
- 생성된 목록에서는 아무것도 지우지 마라. 길다면 “Full list of changes” 제목 아래로 접되, 목록은 남겨라. 프로젝트의 기여자들이 그것을 쓰기 때문이다.
이렇게 하면 보통의 릴리스에서 GitHub 릴리스 노트 편집은 10분쯤 걸리고, 노트는 두 독자층을 모두 섬긴다. 위의 요약은 사용자를 위해, 아래의 목록은 기여자를 위해.
GitHub 릴리스를 체인지로그로 써도 되는가
변경을 알아야 하는 모든 사람이 이미 Releases 페이지를 읽고 있을 때만 그렇다. 개발자가 패키지 관리자로 쓰는 라이브러리라면 대개 그렇고, Releases 페이지에 저장소의 CHANGELOG.md를 더하면 충분하다. GitHub를 한 번도 열지 않는 사용자가 있는 제품이라면 그렇지 않다. 릴리스 페이지는 잘못된 눈높이로 쓰이고, 개발자용 URL 뒤에 있으며, GitHub 계정이 없는 사람은 구독할 수 없다.
버티는 패턴은 GitHub 릴리스를 개발자용 기록으로, 제품 체인지로그를 독자용 기록으로 다루고, 릴리스에서 체인지로그 항목으로 링크하는 것이다. Git 태그, 릴리스, 체인지로그는 세 기록이 어떻게 맞물리는지 다룬다. 제품 체인지로그를 같은 커밋에서 생성한다면 체인지로그 생성기가 그쪽의 초안도 만들어 주고, 체인지로그 대 릴리스 노트의 구분은 어떤 세부 사항이 어디에 속하는지 설명한다.
릴리스 노트 자체의 버전은 어떻게 관리하는가
GitHub에 발행된 릴리스는 언제든 편집할 수 있고, 편집 이력은 페이지에 보이지 않는다. 대부분의 프로젝트에는 그래도 괜찮다. 노트가 규정 준수나 고객이 의지하는 기록인 프로젝트라면 두 가지 습관이 도움이 된다. 정본 텍스트는 저장소에 두고(CHANGELOG.md나 docs/releases/ 폴더) 릴리스 본문이 그곳을 가리키게 하며, 요금제가 지원한다면 저장소에 불변 릴리스를 켜서 발행된 태그와 자산을 잠그는 것이다. 릴리스 관리에 관한 GitHub Docs는 초안, 프리릴리스, 그리고 직접 지정하지 않으면 시맨틱 버전 순서로 붙는 “latest” 라벨을 설명한다.
FAQ
GitHub 릴리스 노트를 자동으로 생성할 수 있는가?
그렇다. 릴리스 폼의 “Generate release notes” 버튼, gh release create의 --generate-notes 플래그, generate-notes REST 엔드포인트 모두 이전 릴리스 태그 이후 병합된 pull request로 초안을 만든다. .github/release.yml 파일이 묶음과 제외를 제어한다.
생성된 릴리스 노트가 비어 있는 이유는 무엇인가? 생성기는 pull request를 나열하므로 브랜치에 직접 넣은 커밋은 나오지 않고, 범위는 최신 태그가 아니라 대상 브랜치의 최신 릴리스에서 시작한다. 이전 릴리스가 존재하는지, 변경이 pull request를 거쳐 들어왔는지 확인하라.
release.yml은 이미 있는 릴리스에도 적용되는가? 아니다. 파일이 자리 잡은 뒤에 생성되는 노트만 바꾼다. 기존 릴리스 본문은 누군가 편집하기 전까지 그대로다.
GitHub 릴리스 노트와 CHANGELOG.md 중 무엇을 써야 하는가? 프로젝트에 기여자와 사용자가 모두 있다면 둘 다다. 릴리스 페이지는 개발자가 찾는 곳이자 자산이 놓이는 곳이고, 저장소의 파일은 GitHub를 떠나도 살아남으며 오프라인으로 읽을 수 있다. 릴리스 노트를 생성하고, 파일을 최신으로 유지하고, 서로 링크하라.
이 글의 기술적 내용은 독립적으로 검토되지 않았습니다. 잘못된 부분이 있으면 알려 주세요. 바로잡겠습니다.