11 KiB
종류마다 무엇을 어떤 순서로 쓰나
칸 목록과 상한은 record-kinds.md, 문장 규칙은 explaining.md, 문서군의 리듬은 ai-tells.md에
있다. 이 문서는 그 칸을 무엇으로 채우는가다.
Studio 에 실제로 올라간 47건에서 뽑았다. keycloak 23건(Case 4·Concept 6·Reference 7· Question 4·Decision 2), n+1liner 24건(Case 5·Reference 7·Question 5·Decision 7). 「대개 이렇게 쓴다」는 말은 그 47건이 그렇게 돼 있다는 뜻이다.
clean-architecture-backend-template 의 949건은 다른 절 이름으로 쓰여 있었고, 지금 이 기준으로
다시 판정하는 중이다. 아직 기준을 만족한 상태가 아니므로 그 949건을 본보기로 삼지 않는다. 올라간
적 없는 초안이 아니라 올라간 것이 기준이다.
파일 뼈대 — 다섯 종류가 같다
---
id · kind · slug · title · topic · topicName · project · status · studio
source · sourceRevision
(종류별) basisVersion · decisionStatus · questionStatus · lastVerifiedOn
(있으면) evidence · assets — assets 는 Case 와 Concept 만
---
# 제목
리드 문단. 이것이 Studio 의 `요약` 칸이다. ← 47건 모두 있다
## 관계 ← Decision 만 「근거」다
## <칸 이름> ← 종류마다 다르다
## 본문 ← Case · Concept 만
<!-- body:start -->
...
<!-- body:end -->
frontmatter 는 메타데이터, ## 는 Studio 의 칸, 제목 아래 첫 문단은 요약이다. 47건 모두 이 모양이다.
## 요약 이라는 절을 만들지 않는다. 요약은 제목 바로 아래 문단이다. 절로 만들면 Studio 에
그런 칸이 없어서 통째로 사라진다.
## 출처 도 칸이 아니다. 원본 분석 문서나 파일 경로는 frontmatter 의 source 에 적는다.
본문 마지막에 두면 게시된 글에 저장소 내부 경로가 그대로 실린다.
source:
- final/document.md#a05-adapter-outbound-persistence-jpa#L354
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
source 는 SSOT 의 앵커다. 분석을 접어 넣은 프로젝트에는 analysis/ 가 없으므로 그 경로를 적으면
가리키는 파일이 없다.
관계 항목은 굵은 제목 한 줄 + 이유 한 줄이다.
- **Keyset Pagination 설계 기준**
이 결정을 규칙으로 편 기준이다.
Case — 9건
칸은 관계 · 문제 · 결론 · 검증 환경 · 재현 조건 · 본문. 9건 모두 여섯 칸을 채웠다.
| 칸 | 무엇을 |
|---|---|
| 문제 | 무엇이 어떠해야 했는데 어떻게 됐나. 요구를 먼저, 실제를 다음에 |
| 결론 | 재현해서 확정한 것. 수치를 그대로. 「~일 것이다」가 아니라 「~였다」 |
| 검증 환경 | 런타임·버전·DB·측정 도구. 이름 : 값으로 줄을 나눈다 |
| 재현 조건 | 다른 사람이 같은 값을 얻는 순서. 번호를 매긴다 |
본문의 절은 하나의 주장과 그 근거가 이어지는 단위로 나눈다. 47건에서는 대개 여섯 절 안팎이었지만 절 수는 작성 조건이 아니다. 숫자를 맞추려고 절을 쪼개거나 붙이면 문서마다 같은 모양이 된다. 아래는 그 47건에서 실제로 반복된 순서다.
- 첫 절은 무대를 세운다. 잰 코드나 구조를 먼저 보여 준다 — 「측정한 loadFeed 구현」, 「무대 — 페이징 한 줄만 추가」, 「가시성을 얹기 전 — 인덱스로 커서 이후만」, 「Mediator에서 Access Token과 Refresh Token을 관리하는 위치」
- 가운데는 측정값(표) → 그 값을 어떻게 읽나 → 실행계획이나 로그 순서다
- 마지막 절은 범위나 다음이다. 9건 중 4건이 확인 범위(「증명하지 않는 것」, 「현재 자동 테스트로 확인한 범위」, 「Redirect URI와 CORS에서 아직 확인하지 않은 부분」), 2건이 「다음 선택」, 나머지가 지표 읽는 법이나 남긴 이유다. 재지 않은 것을 적지 않고 닫는 Case 는 없다
그 마지막 절은 본문 안이다. 칸으로 빼면 Studio 에 그런 칸이 없어 사라진다.
코드블록에는 라벨로 무엇인지 적는다. 표는 머리글이 무엇을 묻는지 말하게 하고, 그 표를 어떻게 읽는지 설명하는 문장(「이렇게 갈린다」「함께 읽어야 한다」)은 두지 않는다. 예시는 한 규모로 고정한다 — 표가 전체 계열을 이미 보여 준다.
Concept — 6건
칸은 관계 · 본문 둘뿐이다. 문제도 결론도 재현 조건도 없다. 내가 잰 결과가 아니라 이미 그렇게
동작하는 것을 적기 때문이다.
basisVersion 은 frontmatter 에 있고 본 것을 · 로 잇는다.
basisVersion: Keycloak 26.7.0 · oidc-client-ts 3.3.0
basisVersion: oauth2-proxy 7.15.2 · Nginx auth_request
절의 개수를 정해 두지 않는다. 설명해야 할 참여자와 단계가 몇 개인지가 정한다. 47건에서 반복된 순서는 이렇다.
- 첫 절은 무엇이 무엇을 주고받는지다 — 「두 개의 OAuth 왕복이 이어진다」, 「Resource Server가 받는 입력」, 「요청 하나가 두 번 평가된다」
- 가운데는 단계마다 실제로 일어나는 일이다
- 마지막 절은 막지 않는 것이나 확인한 범위다 — 「PKCE가 막지 않는 것」, 「CSRF가 XSS를 대신하지 않는다」, 「현재 검증한 범위」, 「지금 구성이 보여 주지 않는 것」
「확인했다」는 Case 의 말이다. Concept 은 「~한다」로 적는다. 규격이 정한 것과 그 구현이 그렇게 한 것을 구분한다.
Reference — 14건
칸은 관계 · 목적 · 규칙 · 적용 조건 · 예외 · 예시. 14건 모두 여섯 칸을 채웠다. 본문이 없다.
| 칸 | 무엇을 |
|---|---|
| 목적 | 이 기준이 무엇을 막는가. 막으려는 실패를 먼저 |
| 규칙 | 제목은 무엇을 하는지/하지 않는지로. 본문에 왜인지 |
| 적용 조건 | 언제 이 기준이 걸리는가 |
| 예외 | 걸리지 않는 경우. 이 칸이 비면 규칙이 과잉 적용된다 |
| 예시 | 짧은 문장. 코드가 아니다 |
규칙 제목만 읽어도 무엇을 금지하는지 알아야 한다. 「지표를 정확히 읽는다」보다
「지표 이름이 뜻하는 것을 그대로 읽는다」가 낫다. 코드가 필요하면 그 코드가 있는 Case 를 만들고
관계로 가리킨다 — Reference 칸은 평문이라 백틱이 글자로 보인다.
Question — 9건
칸은 관계 · 사실 · 가정 · 미지수 · 제약 · 선택지 · 다음 검증. 9건 모두 일곱 칸을 채웠다.
questionStatus 는 frontmatter 에 있다.
가정을 사실 칸에 넣지 않는 것이 이 종류의 전부다. 사실은 확인한 것, 가정은 확인하지 않고 전제한 것이다.
다음 검증은 실행할 수 있는 문장으로 적는다. 「더 알아본다」로는 닫히지 않는다 —
「seed(1000) 뒤 ANALYZE highlights 를 돌리고 Plan B 를 다시 잰다」처럼 적는다.
그 아래 닫는 조건을 한 줄 붙인다. 어떤 결과가 나오면 이 질문을 닫거나 Decision 으로 넘기는지
적지 않으면 검증을 마쳐도 질문이 그대로 열려 있다. 계약의 decision-criterion 이 이 줄이다.
## 다음 검증
1. seed(1000) 뒤 `ANALYZE highlights` 를 돌리고 Plan B 를 다시 잰다
닫는 조건 : Plan B 의 실제 행 수가 추정치의 2배 안에 들어오면 닫고, 벗어나면 통계 갱신 주기를
정하는 Decision 으로 넘긴다
Decision — 9건
칸은 근거 · 결정문 · 판단 이유 · 영향. 다른 넷과 달리 관계 절 이름이 「근거」다.
decisionStatus 는 frontmatter 에 있다. 근거가 1개 이상 없으면 게시가 거절된다.
| 칸 | 무엇을 |
|---|---|
| 결정문 | 「~한다」로 끝나는 문장. 조건이 있으면 한 문단 더 |
| 판단 이유 | 무엇을 보고 그렇게 정했나. 근거로 건 기록을 가리킨다 |
| 영향 | 감수한 비용을 포함한다. 좋아진 것만 적지 않는다 |
대안을 적고 왜 고르지 않았는지 적는다. 대안이 없으면 결정이 아니라 사실이다. 자료가 뒷받침하지 않는 이유를 만들지 않는다.
본문이 있는 두 종류의 공통 규칙
- 그림이 필요한지와 무엇을 그릴지는
choosing-a-diagram.md가 정한다 — 종류마다 그림이 답해야 할 물음이 다르다. Case 는 순서, Concept 은 구조나 변환 사슬이 대개 논지다 - 그림은
technical-visualizer로 만든다. 손으로 SVG 를 그리지 않는다 - 그림 안에는 이름만 넣는다. 문장은
<desc>와 옆 문단에 둔다 - 그림과 증거는 frontmatter 의
assets·evidence로 잇는다. 같은 파일을 기록 옆에 복사하지 않는다 assets는 본문이 있는 두 종류만 갖는다. Reference·Question·Decision 은 그림을 렌더링할 자리가 없어서 선언해도 화면에 나오지 않는다- 본문은
<!-- body:start -->와<!-- body:end -->사이다. 그 밖은 Studio 로 가지 않는다
관계를 어디서 가져오나
관계는 다른 기록을 가리키는 링크다. 지어내지 않는다. 분해 계약(tech-log-tree.json)이 노드마다
relations 를 적어 두면 그것을 그대로 옮긴다.
계약이 관계를 적지 않은 노드는 한 가지 규칙만 쓸 수 있다 — Reference 의 근거 사건은 같은
source 리프의 판정이 소유한다. 그래서 같은 분석 문서에서 나온 Reference 와 Case 는 서로
걸 수 있다. 그 밖의 짝은 읽고 정해야 한다. 「같은 모듈이다」는 관계가 아니라 분류다.
## 관계
- **SQL 실패가 재시도 불가로 분류된다**
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
Studio 는 Decision 만 관계를 1개 이상 요구한다. 나머지는 비어도 게시되지만, 관계 없는 기록은 다른 기록에서 도달할 수 없다.
Studio 파서가 거절하는 세 가지
check_body.mjs 가 잡는다. 셋 다 글자를 바꾸지 않고 고칠 수 있다.
| 쓴 것 | 파서가 읽는 것 | 고치는 법 |
|---|---|---|
`:11`~`:14` |
~…~ 를 취소선으로 |
`:11`\~`:14` |
afterPropertiesSet(:43) |
:43 을 인라인 디렉티브로 |
(\:43) 또는 백틱으로 감싼다 |
:::note 안에 문단 둘 |
거절 | 문단 하나만 담거나 절 제목 아래 평문으로 푼다 |
## 확인하지 못한 것 처럼 절 제목이 이미 무엇인지 말하는 자리에서는 :::note 로 다시 감싸지
않는다. 제목과 콜아웃이 같은 말을 두 번 한다.