# Git Writing

> 팀원이 읽는 git 텍스트 — PR 제목·본문, 이슈, 커밋 메시지 — 를 사람이 읽기 좋게 쓴다. 사용자가 "PR 올려줘", "PR 써줘", "PR 본문 작성해줘", "PR 문구 다듬어줘", "이슈 올려줘", "이슈로 남겨줘", "이슈 정리해줘", "커밋 메시지 다듬어줘"라고 하거나, 작업을 마치고 `gh pr create`·`gh issue create`를 실행하기 직전이면 — 사용자가 문구 얘기를 꺼내지 않았어도 — 반드시 발동한다. 이미 올라간 내 PR·이슈의 본문을 수정할 때도 발동한다. 팀원이 올린 PR을 리뷰할 때는 이 스킬이 아니라 pr-review-loop다. 또한 "이 스킬 의도대로 작동해?", "이 스킬 잘 되고 있어?"처럼 스킬 자체의 효과를 점검해 달라는 요청에도 발동하며, 그때는 같은 폴더의 `RATIONALE.md`를 읽고 이번 세션·기존 기록과 대조한다.

- Skill: `iceberggymnast/git-writing` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add iceberggymnast/git-writing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/iceberggymnast/git-writing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: iceberggymnast (https://skillmd.com/u/iceberggymnast)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/iceberggymnast/git-writing

---


# Git Writing — 사람이 읽는 PR·이슈·커밋

## 이 스킬이 다루는 것

| 상황 | 담당 |
|---|---|
| **내가 올리는 PR의 제목·본문** | **이 스킬** |
| **이슈 작성·수정** | **이 스킬** |
| **커밋 메시지** | **이 스킬** (전역 규칙 — 한국어, Co-Authored-By 금지 — 위에 얹힌다) |
| 팀원이 올린 PR을 리뷰 | `pr-review-loop` |
| 커밋·PR 직후 이해도 확인 | `senior-mentor` |

트리거를 나눈 이유: 같은 시점을 두고 스킬이 경합하면 발동 신뢰도가 떨어진다.
PR 생성 시점에는 이 스킬(본문)과 `senior-mentor`(이해도)가 **둘 다** 걸릴 수 있고, 서로 배타가 아니다.

## 전제 — 구조는 문제가 아니다

이 사용자의 레포들에서 PR·이슈의 섹션 골격은 이미 잘 작동한다 (PR: 개요/주요 변경/검증/리뷰 포인트/남긴 것 · 이슈: 배경/실측/해결 방향/완료 조건). **골격을 갈아엎거나 새 템플릿을 강제하지 마라.** 이 스킬이 고치는 것은 **문장 안에서 일어나는 일**이다.

실제 산출물(팀 게임 프로젝트의 PR들, 그래픽 툴 플러그인의 이슈들)에서 관찰된 문제는 매체를 가리지 않고 같다:

1. 한 문장에 결정 + 근거 + 반사실("~였다면 ~로 남습니다")을 전부 욱여넣은 고밀도 문장
2. `계약③`, `ADR-2`, `[G6]` 같은 내부 참조 코드와 "슬루", "그리디 홀드" 같은 전문용어가 설명 없이 등장
3. 문서마다, 심지어 한 문서 안에서 어미가 섞임

## 독자를 그려라

읽는 사람은 소규모 팀의 팀원이다. 리뷰어이거나, 이 변경·이슈 위에 다음 작업을 쌓을 사람이다. 이 글은 분석 보고서가 아니라 **팀원이 한 번 읽고 다음 행동(리뷰 시작, 작업 착수, 판단)에 들어갈 수 있는 작업 문서**다. 문장이 완결적이고 정확해도, 읽는 사람이 두 번 읽어야 하면 실패다.

## 공통 규칙 — 모든 매체에 적용

### 1. 한 문장에는 하나의 정보

무엇을 했는지(또는 무엇이 문제인지) 한 문장. 왜 그런지는 **다음 문장**. 대안이 왜 아닌지는 필요할 때만 그다음 문장. 이 셋을 대시(—)와 쉼표로 한 문장에 이으면, 정보는 보존되지만 읽기는 무너진다.

실제 PR에서 관찰된 패턴을 재구성한 예시:

**전 (한 호흡에 결정·이유·계약 노출까지):**
> `QuestLogWidget`은 자체 `bCompleted` 플래그를 버리고 표시 전용으로 전환, 완료 여부는 매번 QuestState에 질의. 위젯 로컬 상태는 레벨 전환·세이브에서 사라지고, Reward(보상 지급)·Dialogue(`HasQuestDone` 조건)가 같은 상태를 읽어야 해서 공유 계약③으로 노출했다.

**후 (문장마다 정보 하나, 서술어까지 완결):**
> `QuestLogWidget`은 이제 표시만 담당합니다. 완료 여부는 매번 QuestState에 물어봅니다. 위젯이 직접 들고 있던 `bCompleted` 플래그는 레벨 전환이나 세이브에서 사라지는 값이라 버렸습니다. Reward와 Dialogue도 같은 완료 상태를 읽어야 해서, 조회 함수들을 공유 계약③(위젯–상태 간 공유 API 규약)으로 노출했습니다.

### 1-b. 쪼갠 문장은 연결어미로 다시 잇는다

규칙 1로 정보를 나눈 뒤, 인접한 두 문장이 인과·역접·조건 관계면 연결어미(-아서, -라서, -지만, -는데, -면)로 잇는다. 관계를 "그래서", "다만" 같은 접속부사로 문장 밖에서 되붙이지 말고 어미 안에 넣어라. 한국어는 논리 관계를 연결어미가 나르기 때문에, 그 자리가 비면 짧은 단정문이 줄지어 서고 읽는 사람은 관계를 스스로 채워 넣어야 한다. 위 "후" 예시가 읽히는 이유가 그것이다 — 셋째·넷째 문장이 "-라", "-해서"로 이어져 있고 앞 두 문장과 길이가 다르다. 전부 짧으면 아무것도 강조되지 않는다.

주어는 현상이 아니라 행위자로 잡는다. 무너지다·갈라지다·덮다 같은 동사가 손에 잡히면 그 문장에 들어갈 실측이나 호출 순서를 아직 확인하지 않았다는 신호이니, 사실을 찾아 넣으면 동사는 저절로 평범해진다.

> ❌ 완료 상태가 두 줄기로 갈라집니다. 세이브에서 값이 무너집니다.
> ⭕ 위젯과 QuestState가 각자 완료 여부를 들고 있어서, 세이브 직렬화가 위젯 쪽 `bCompleted`를 포함하지 않으면 로드 뒤 두 값이 어긋납니다.

### 2. 문장을 끝까지 써라

"~로 전환," "~에 질의." 같은 서술어 생략체를 쓰지 마라. 명사 뭉치("중복·잔량 판정을 상태 소유자가 최종 결정")는 동사로 풀어라. 글자 수를 아끼는 만큼 읽는 사람의 해석 비용이 늘어난다 — 아껴야 하는 것은 글자가 아니라 독자의 시간이다.

**비유로 기술적 사실을 대체하지 마라.** "범인은 리타겟 정책이 아니었습니다", "쓰레기 회전이 됩니다", "축이 눕는 순간"처럼 비유가 사실의 자리에 서면, 읽는 사람은 무슨 일이 일어났는지 추측해야 한다. 사실을 먼저 쓰고, 비유는 이해를 돕는 자리에만 뒤따르게 해라 — "실제 포말이 공기 섞인 흰 물이라 불투명한 것과 같은 이치입니다"처럼 설명을 마친 뒤 붙는 비유가 그 자리다.

### 3. 참조 코드·전문용어는 첫 등장에서 풀어준다

`계약③`, `ADR-002`, `Milestones §3`, `[G6]` 같은 내부 코드와, 팀원이 모를 수 있는 전문용어("히스테리시스", "슬루", "temporal IK")는 쓰는 사람 머릿속에는 선명하지만 읽는 사람은 찾아봐야 한다. **첫 등장에서 괄호 한 줄로 무엇인지 적어라.** 두 번째부터는 코드·용어만 써도 된다.

> 공유 계약③(위젯–상태 간 공유 API 규약)으로 노출했습니다. … 계약③의 시그니처는 그대로입니다.

문서 링크가 가능하면 링크가 더 좋다. 단, 링크가 있어도 한 줄 설명은 남긴다 — 링크를 타는 것도 비용이다.

**설명은 확인한 것만 붙여라.** 문서나 코드에서 뜻을 확인하지 못한 용어는 설명을 지어 붙이지 말고 원문 표현 그대로 둬라. 그럴듯하게 틀린 설명은 설명 없는 코드보다 해롭다 — 읽는 사람이 확인 없이 틀린 이해를 갖게 된다. (실측 사례: 이슈 재작성 테스트에서 bone_swing에 "팔뚝 평행 스윙"이라는 지어낸 설명이 붙었다. 실제로는 세로 본 swing이다.)

**단, "확인 못 했으니 그냥 둔다"로 끝내지 마라.** 본문에 쓸 용어는 쓰기 전에 코드·문서에서 뜻을 확인하는 것이 기본 순서다. 확인이 안 되면 먼저 그 용어를 쓰지 않고 풀어 쓸 수 있는지 본다. 그래도 써야 하면 `docs/rig.md §21` 같은 출처를 함께 남긴다 — 설명도 출처도 없는 용어가 가장 나쁘다.

**수식·기호는 결과를 먼저 쓰고 표기를 뒤에 붙인다.** `(2π−θ, −a)`를 그대로 던지지 말고 그 표기가 무엇을 뜻하는지 먼저 쓴다.

> ❌ 축 연속성 규칙은 내적이 음수면 `(2π−θ, −a)`로 바꿉니다.
> ⭕ 축 연속성 규칙은 같은 회전을 반대 방향으로 도는 표현(`2π−θ`만큼 축 `−a` 둘레로)으로 바꿉니다.

**혼자 쓰고 혼자 머지하는 레포일수록 이 규칙을 세게 적용한다.** 되묻는 사람이 없어서 무설명이 교정되지 않고, 몇 주 뒤 자기 자신이 못 읽는 문서가 된다. 독자를 "이 코드를 안 본 팀원"으로 계속 가정해라.

### 4. 근거는 선별한다

모든 결정에 근거와 반사실을 달면 본문 전체의 밀도가 올라가 정작 중요한 근거가 묻힌다. 기준은 전역 문서 작성 원칙과 같다: **이 근거가 읽는 사람의 행동을 바꾸는가.**

- 읽는 사람이 뒤집을 수 있고 지금 뒤집는 게 싼 결정 → 근거를 충분히. PR이면 리뷰 포인트 섹션으로 올린다
- 이미 확정된 결정의 실행, 사소한 구현 선택 → 결정만 적는다. 이유가 궁금하면 물어볼 것이다
- **실제 이유를 모르면 지어내지 마라.** 근거 없는 결정은 근거 없이 적는 것이 정직하다

### 5. 어미는 합쇼체, 팀원 지칭은 이름+님

- 팀원에게 보내는 글이므로 기본값은 **합쇼체(-습니다)**다. 한 문서 안에서 섞지 말고, 문서 사이에서도 유지해라.
- 팀원을 지칭할 때는 **이름 + 님**으로 쓴다 ("민수님이 볼 부분"). 이름만 부르는 반말 지칭("민수이 볼 부분")을 쓰지 마라.
- (팀이 다른 관례를 정하면 그것을 따른다 — 중요한 것은 일관성이다.)

### 6. 굵은 글씨는 놓치면 사고 나는 것에만

문단마다 균일하게 볼드가 있으면 아무것도 강조되지 않는다. 읽는 사람이 놓쳤을 때 실제로 문제가 되는 것 — 머지 전 확인 필수, 깨진 상태로 들어가는 것, 되돌리기 어려운 결정 — 에만 써라.

## PR

- **제목**: 한 줄만 보고 "무엇이 바뀌는지" 알 수 있어야 한다. GitHub 목록 화면에서 잘리지 않을 길이로. 팀에 굳은 접두 관례(트랙/주차 표기 등)가 있으면 유지한다. 병기(A + B + C)를 세 개 이상 잇지 마라 — 셋 다 중요하면 개요 첫 문장에서 풀어라.
- **골격**: 기존 PR들의 골격(개요/주요 변경/검증/리뷰 포인트/남긴 것)을 따른다. 해당 없는 섹션은 비워두지 말고 뺀다. **검증 섹션만은 뺄 수 없다** — 레포의 기존 PR 골격에 검증 섹션이 없어도 만든다. 실행·미실행 구분이 들어갈 자리가 거기뿐이고, 체크리스트만 있던 레포에서 이 스킬을 쓴 PR이 검증 절 없이 올라간 사례가 있다.
- **검증 섹션**: 리뷰어가 그대로 따라할 수 있게 — 어떤 씬·명령·조작으로 무엇을 보는지까지.
- **검증은 실행한 것과 안 한 것을 나눠 적는다.** 실제로 돌린 것은 무엇으로 확인했는지 결과와 함께 적고, 안 돌린 것은 "미실행"으로 명시한다. 예상을 실행 결과처럼 쓰면 리뷰어는 확인된 것으로 믿는다 — "머지 전에 돌려보겠습니다"는 검증이 아니라 계획이다.

## 이슈

- **제목은 증상 중심 한 줄.** 읽는 사람이 목록에서 제목만 보고 "무슨 문제인지"를 알아야 한다. 원인 분석을 제목에 압축하지 마라 — 원인은 본문 몫이다.
- **골격**: 기존 이슈들의 골격(배경 / 지금 상태·실측 / 해결 방향 / 완료 조건)을 따른다. 이 골격 자체는 좋다.
- **본문 첫 문단은 코드를 안 연 사람도 읽혀야 한다.** 파일:라인 참조는 근거로 붙이되, 문장 자체는 참조 없이도 뜻이 통하게 써라. "무엇이 어떻게 잘못 동작하고, 사용자·결과물에는 어떻게 보이는가"를 먼저, 코드 수준 원인은 그다음에.
- **실측이 있으면 실측을 적어라.** "고착될 수 있다"보다 "f103~130 사이 28프레임이 동일 회전으로 정지한다"가 낫다. 다만 실측 나열이 본문을 삼키면 요약 한 줄 + 상세는 접거나 뒤로 보낸다.
- **완료 조건은 확인 가능한 문장으로.** "개선된다"가 아니라 "이 구간이 지표에 잡힌다"처럼, 닫을 때 판정할 수 있게 쓴다.

## 커밋 메시지

전역 규칙(한국어, Co-Authored-By 금지)에 다음을 얹는다:

- **제목 줄은 "무엇을 왜"의 무엇 쪽 한 줄.** 목록(`git log --oneline`)에서 잘리지 않을 길이로, 이 커밋이 코드를 어떻게 바꾸는지가 드러나게.
- 본문이 필요한 커밋(설계 결정이 들어간 것, 이유가 코드에 안 보이는 것)은 빈 줄 하나 띄우고 **왜**를 문장으로 적는다. 공통 규칙 1~4가 그대로 적용된다.
- 루틴 커밋(오타, 정리, 단순 반영)에 본문을 억지로 달지 마라. 제목 한 줄이면 끝이다.
- 본문이 있는 커밋은 게시 전에 린트를 거친다(아래 "올리기 전 검사" 1). 실측에서 갈라지다·무너지다·조용히 같은 어휘가 몰려 있던 곳은 커밋 본문이었다. PR 본문에는 거의 없었다. 스크립트는 합쇼체·해라체를 모두 센다.

## 올리기 전 검사 — 린트, 판정자, 자가 검사

작성자는 자기 초안의 리듬을 보지 못한다. 규칙을 쓴 바로 그 문단에서 같은 리듬이 다시 나오는 것이 원작성자 실측으로 확인됐고, 판단형 자가 검사는 그냥 통과한다. 그래서 세는 일은 스크립트가, 판정은 초안을 쓰지 않은 컨텍스트가 한다.

본문은 파일로 쓴다(`gh pr create --body-file`, `gh issue create --body-file`). 그 파일에 대해:

1. **린트.** `python scripts/prose-lint.py <본문 파일> > <린트 출력 파일>`. 걸린 문장을 줄 번호와 함께 인용해 준다. 후보 목록이다. 사실을 정확히 말하는 문장은 걸려도 그대로 둔다.
2. **판정자.** 초안을 쓰지 않은 컨텍스트에 본문 파일·린트 출력·`references/review-request.md`를 본문 파일 옆에 복사해 빈칸을 채운 사본을 넘기고 문장 단위 교체안을 받는다. 원본 양식은 고치지 않는다. **작업 중인 모델이 Claude이고 codex 플러그인이 있으면 codex 서브에이전트에게 받는다** — 이 리듬은 Claude 고유의 성향이라 다른 모델이 사각을 공유하지 않는다. 없으면 같은 모델의 서브에이전트다. **판정자는 본문을 다시 쓰지 않는다.** 통째로 다시 쓰면 같은 리듬이 돌아온다. 걸린 문장마다 "원문 → 교체안"만 받고, 본 에이전트가 그 교체만 적용한다.
3. **린트 재실행.** 교체를 적용한 뒤 한 번 더 돌려 새로 걸린 것이 없는지 본다.

커밋 메시지는 1만 한다. 자동 커밋 규약 아래서 커밋마다 판정자를 부르면 무겁고, 커밋 층에서 실측된 문제는 어휘라 단어 검사로 충분하다.

그 뒤 본문을 다시 읽으며 확인한다:

- [ ] 첫 문단(또는 커밋 제목 줄)만 읽은 팀원이 "이게 무슨 일인지" 한 문장으로 말할 수 있는가
- [ ] 아무 불릿이나 골라 소리 내어 읽었을 때 한 호흡에 끝나는가 — 숨이 차면 문장을 쪼개고, 쪼갠 문장이 인과·역접이면 연결어미로 다시 잇는다(규칙 1-b)
- [ ] 참조 코드·전문용어가 설명 없이 처음 등장하는 곳이 없는가
- [ ] **개요(이슈면 배경) 첫 문단에 뜻이 안 풀린 용어가 3개 이상인가** — 그렇다면 그 문단은 코드를 이미 아는 사람만 읽을 수 있는 상태다
- [ ] 붙인 설명이 문서·코드에서 실제로 확인한 것인가 — 확인 못 했으면 설명을 빼고 원문 표현으로 되돌린다
- [ ] 검증 섹션에 실행하지 않은 항목이 실행한 것처럼 적혀 있지 않은가
- [ ] 어미가 섞이지 않았는가, 팀원 지칭이 이름+님인가
- [ ] AI 내부 상태값·수사(전역 "보고서·문서 작성 원칙"의 금지 목록)가 없는가
- [ ] 도구가 붙인 자동 푸터("Generated with …")가 남아 있지 않은가 — 전역 지침은 팀원에게 가지 않고 이 스킬은 간다

## 하지 말 것

- 섹션 골격을 새로 발명하는 것 — 기존 골격을 따르고, 해당 없는 섹션은 뺀다
- 근거를 지어내는 것
- 밀도를 낮춘다는 이유로 정보를 삭제하는 것 — 문장을 쪼개는 것이지 내용을 버리는 것이 아니다. 판단이 애매하면 남긴다
- 전역 "보고서·문서 작성 원칙"을 여기 다시 쓰는 것 — 그 원칙은 이 스킬 위에 그대로 얹힌다

## 성공 기준 · 존재 의의

같은 폴더의 `RATIONALE.md`에 있다. **여기 옮겨 적지 않는다** — 두 벌이 되면 갈라진다.

`RATIONALE.md`는 원작성자의 관측 기록이라 배포에 포함되지 않는다. 이 스킬을 새로 받았다면 자기 관측 기록으로 직접 만든다. 그때 `## 재는 것`에는 아래 기준을 그대로 옮긴다 — 메커니즘에 딸린 것이라 사람이 바뀌어도 같다:

- 팀원이 PR·이슈를 읽고 내용을 되묻는 횟수가 줄어든다
- 사용자가 게시 전에 본문을 손으로 고치는 빈도가 줄어든다 — 수동으로 고친 부분이 다음 규칙 후보다
- 문서 간 문체가 일관된다

사용자가 *"이 스킬 의도대로 작동해?"* 라고 물으면 그 파일을 읽고 이번 세션과 대조한다.

