docs(TechLog): 글감 56개를 기록으로 쓴다

주제 13개 · Case 28 · Concept 5 · Reference 15 · Question 4 · Decision 4.
계약의 노드마다 종류가 요구하는 칸을 채우고, 본문이 있는 두 종류에는 SSOT 가 이미
그려 둔 도식 셋(value-boundaries · decision-path-404 · topic-variant-model)을
tech-log-studio/ 로 옮겨 붙였다. 새로 그린 그림은 없다.

검사 셋 전부 통과한다.
  check_body.mjs      56 편 중 본문이 있는 33 편 PASS
  check_prose.mjs     56 편 error 0
  check_evidence.mjs  --repo 포함 문제 없음
  verify-tech-log-tree.py  프로젝트 5 · error 0 · warn 0

인용한 코드블록은 전부 SSOT 에서 찾아 대조했다. check_evidence.mjs 가 본문의 각 줄과
source 앵커와 계약 제목을 다시 확인한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-07 15:29:33 +09:00
co-authored by Claude Opus 5
parent 6955611439
commit f6c825e858
62 changed files with 6381 additions and 186 deletions
@@ -0,0 +1,78 @@
---
kind: CASE
slug: an-error-message-that-guessed
title: 서버는 하나를 답했는데 화면은 추측 셋을 출력했다
topic: one-thing-many-names
topicName: 같은 것이 화면마다 다른 이름
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§13.4
---
# 서버는 하나를 답했는데 화면은 추측 셋을 출력했다
작업본 삭제가 실패하면 화면이 「게시됐거나, 참조하는 곳이 있거나, 누가 먼저 고쳤을 수 있습니다」라고 적었다. 세 가지 추측이다. 서버는 정확히 하나를 답하고 있었다.
## 관계
- **삭제를 막는 이유 다섯 가지가 전부 같은 한 문장으로 나온다**
이 화면 문구를 고친 뒤에도 남은 문제다.
- **화면은 못 읽은 것을 없다고 말하지 않는다**
화면이 모르는 것을 말할 때의 짝이 되는 규칙이다.
- **한 화면에 종류 이름이 아홉 개 떠 있었다 — 표가 여섯 벌이었다**
같은 시기에 문구를 한 곳으로 모은 사건이다.
## 문제
작업본 삭제가 실패하면 화면이 세 가지 추측을 나열했다.
서버는 정확히 하나를 답하고 있었다 — 「이 기록을 참조하는 곳이 있어 삭제할 수 없습니다」.
## 결론
화면이 서버의 답을 쓰지 않고 자기가 가능한 원인을 나열하고 있었다.
그래서 버전 충돌이 「사용 중」으로 읽혔다. 어떤 삭제는 되고 어떤 삭제는 안 되는 것을 지켜보는 작성자는 둘을 구분할 방법이 없었다.
게이트웨이가 서버의 클라이언트 안전 메시지를 실어 나르고 화면이 그것을 보이게 했다.
## 검증 환경
tech-log-frontend : 1801414
tech-log-backend : 857e6a9 — 삭제 거절 사유를 클라이언트 안전 메시지로 답함
확인 방식 : 실패하는 삭제를 실제로 시도해 화면 문구와 서버 응답을 대조
## 재현 조건
1. 다른 기록이 참조하는 작업본을 지운다 — 서버가 참조 사유를 답한다
2. 버전이 어긋난 상태로 작업본을 지운다 — 서버가 다른 사유를 답한다
3. 두 경우의 화면 문구가 다른지 본다
## 본문
<!-- body:start -->
## 화면이 세 가지를 추측했다
화면 문구는 「게시됐거나, 참조하는 곳이 있거나, 누가 먼저 고쳤을 수 있습니다」였다. 세 가지 원인을 나열하고 어느 것인지는 말하지 않는다.
서버는 하나를 답하고 있었다. 게이트웨이가 그 답을 버리고 화면이 자기 목록을 그렸다.
## 무엇이 구분되지 않았나
버전 충돌은 「누가 먼저 고쳤다」이고 참조 존재는 「사용 중」이다. 문구가 셋을 함께 적으므로 작성자는 둘을 구분할 수 없다.
두 경우에 해야 할 일이 다르다. 버전 충돌이면 다시 받아서 지우면 되고, 참조가 있으면 그 참조를 먼저 풀어야 한다.
## 서버의 답을 실어 나른다
게이트웨이가 서버의 클라이언트 안전 메시지를 그대로 싣고 화면이 그것을 보인다. 서버가 답하지 않은 것은 화면이 만들지 않는다.
## 확인하지 못한 것
서버가 답하는 그 한 문장이 다섯 이유를 다 같은 말로 덮고 있다. 참조 검사가 다섯 테이블을 하나로 묶어 검사하기 때문이고, 그 문제는 아직 열려 있다.
<!-- body:end -->
@@ -0,0 +1,99 @@
---
kind: CASE
slug: nine-names-for-five-kinds
title: 한 화면에 종류 이름이 아홉 개 떠 있었다 — 표가 여섯 벌이었다
topic: one-thing-many-names
topicName: 같은 것이 화면마다 다른 이름
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§13.1
- final/document.md#§13.5
---
# 한 화면에 종류 이름이 아홉 개 떠 있었다 — 표가 여섯 벌이었다
홈 한 화면에 문서 종류 이름이 아홉 개 떠 있었다. 최근 기록 목록은 계약의 enum 이름을, 바로 아래 「종류별로 읽기」는 사람이 붙인 이름을 쓰고 있었다. 독자는 둘이 같은 것이라는 단서를 어디서도 받지 못했다. 원인은 종류 이름 표가 화면마다 복사되어 여섯 벌이었다는 것이다.
## 관계
- **종류 이름을 두 번 바꿨다 — 화면의 이름과 계약의 kind 를 갈랐다**
이 표를 한 곳으로 모은 뒤에 이름 자체를 다시 정한 기록이다.
- **개념을 하나 더하자 열세 곳이 그것을 조용히 삼켰다**
같은 종류 목록이 코드 쪽에서 갈라진 사건이다.
- **톤을 지적받으면 고쳐 쓰지 말고 어떤 말을 쓸지 묻는다**
같은 시기에 문구를 다룬 기준이다.
## 문제
홈 화면 하나에 종류 이름이 아홉 개 있었다.
```text
최근 기록 목록: CASE · CONCEPT · OPEN QUESTION · REFERENCE
바로 아래 「종류별로 읽기」: 검증 기록 · 동작 원리 · 적용 기준 · 열린 질문
```
두 목록이 같은 다섯 종류를 가리키는데 이름이 겹치지 않는다. 독자는 그 둘이 같은 것이라는 단서를 받지 못한다.
## 결론
종류 이름 표가 화면마다 복사되어 여섯 벌이었고, 그래서 갈라졌다.
> 표가 화면마다 복사되어 **여섯 벌**이었고 그래서 갈라졌다: 같은 QUESTION 이 공개 화면에서 "Open Question", 작업본 목록과 게시 기록에서 "Question", 편집기 상태 줄에서 "QUESTION" 이었다. **쓰는 사람은 같은 문서를 화면마다 다른 이름으로 만난다.**
종류에서 이름으로 가는 표 하나로 모았다.
편집기 칸 이름도 공개 화면과 맞췄다. 쓰는 사람이 지금 채우는 칸이 공개 화면 어디로 가는지 외우지 않아도 된다.
## 검증 환경
tech-log-frontend : dc2fda7 · ca1cfa2 계열 · 82e992d
확인 방식 : 한 화면에 동시에 뜨는 종류 이름을 세고, 표가 몇 벌인지 확인
## 재현 조건
1. 홈 화면을 열고 최근 기록 목록과 「종류별로 읽기」를 함께 본다
2. 두 목록에서 같은 종류를 가리키는 이름을 대조한다
3. 작업본 목록·게시 기록·편집기 상태 줄에서 같은 종류의 이름을 확인한다
## 본문
<!-- body:start -->
## 한 화면에 아홉 개
```text
최근 기록 목록: CASE · CONCEPT · OPEN QUESTION · REFERENCE
바로 아래 「종류별로 읽기」: 검증 기록 · 동작 원리 · 적용 기준 · 열린 질문
```
두 목록이 세로로 붙어 있다. 위는 계약의 enum 이름을, 아래는 사람이 붙인 이름을 쓴다.
이름을 바꾸기 전보다 나빠진 유일한 화면이었다. 바꾸기 전에는 양쪽이 다 enum 이름이라 적어도 같아 보였다.
## 표가 여섯 벌이었다
> 표가 화면마다 복사되어 **여섯 벌**이었고 그래서 갈라졌다: 같은 QUESTION 이 공개 화면에서 "Open Question", 작업본 목록과 게시 기록에서 "Question", 편집기 상태 줄에서 "QUESTION" 이었다. **쓰는 사람은 같은 문서를 화면마다 다른 이름으로 만난다.**
## 표 하나로 모았다
종류에서 표시 이름으로 가는 표를 하나 만들고 여섯 곳이 그것을 쓰게 했다. 종류가 늘면 그 표에 자리가 비었다고 컴파일러가 잡는다.
## 편집기 칸 이름도 맞췄다
같은 문제가 칸 이름에도 있었다. 편집기에서 「목적」이라 부른 칸이 공개 화면에서는 다른 이름으로 나왔다.
```text
목적 → 이 기준을 쓰는 이유 규칙 → 판단 기준
적용 조건 → 적용할 때 예외 → 예외와 주의
사실 → 확인한 사실 미지수 → 남은 미지수
선택지 → 검토한 선택지
```
## 확인하지 못한 것
이름을 바꾸기 전보다 나빠진 화면이 홈 하나였다는 것은 화면으로 확인했다. 다른 화면에서 두 이름이 같이 뜨는 곳을 전수로 세지는 않았다.
<!-- body:end -->
@@ -0,0 +1,95 @@
---
kind: CASE
slug: renaming-the-kinds-twice
title: 종류 이름을 두 번 바꿨다 — 화면의 이름과 계약의 kind 를 갈랐다
topic: one-thing-many-names
topicName: 같은 것이 화면마다 다른 이름
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§13.2
---
# 종류 이름을 두 번 바꿨다 — 화면의 이름과 계약의 kind 를 갈랐다
이 저장소의 종류 이름은 글을 담아 둔 방식의 이름이었다. 독자는 그 말을 배우고 나서야 목록을 읽을 수 있었고, 뜻풀이는 홈 바닥 2,000px 아래에 있었다. 이름이 하는 일을 말하게 바꿨다가, 그 안이 기술 기록의 톤에 비해 가벼워 문어체로 다시 세웠다.
## 관계
- **한 화면에 종류 이름이 아홉 개 떠 있었다 — 표가 여섯 벌이었다**
이 이름을 한 곳으로 모은 뒤에 이 변경이 왔다.
- **톤을 지적받으면 고쳐 쓰지 말고 어떤 말을 쓸지 묻는다**
두 번째 안이 왜 필요했는지가 그 기준에 있다.
- **slug 생성이 한글을 버려 주제 만들기가 간헐적으로 실패했다**
이름을 주소로 옮기는 다른 사건이다.
## 문제
종류 이름이 Case, Reference, Open Question 이었다. 이것은 글을 담아 둔 방식의 이름이다.
독자는 그 말을 배우고 나서야 목록을 읽을 수 있었고, 정작 뜻풀이는 홈 바닥 2,000px 아래에 있었다.
## 결론
두 번 바꿨다.
1차 : 이름이 하는 일을 말하게 했다 — 직접 해보니 · 다음에 쓸 기준 · 아직 모르는 것 · 어떻게 동작하나 · 이렇게 하기로
2차 : 역할은 그대로 말하되 문어체로 다시 세웠다 — 검증 기록 · 적용 기준 · 열린 질문 · 동작 원리 · 설계 결정
1차 안이 기술 기록의 톤에 비해 가벼웠다.
계약의 kind 는 그대로 뒀다. 바꾸는 것은 화면에 보이는 이름뿐이다.
## 검증 환경
tech-log-frontend : a6413d0 → af5a6bb
계약 : RecordKind 다섯 값은 변경 없음
확인 방식 : 화면의 표시 이름과 계약의 kind 를 대조
## 재현 조건
1. 공개 화면에서 종류 배지와 「종류별로 읽기」의 이름을 본다
2. 편집기의 새 문서 화면에서 같은 종류의 이름을 본다
3. 계약의 kind 값과 대조한다
## 본문
<!-- body:start -->
## 담아 둔 방식의 이름
Case, Reference, Open Question 은 그 글을 어떤 형식에 담았는지를 말한다. 그 글이 독자에게 무엇을 주는지는 말하지 않는다.
독자는 그 말을 먼저 배워야 목록을 읽을 수 있었다. 뜻풀이는 홈 바닥 2,000px 아래에 있었다.
## 1차 — 하는 일을 말하게 했다
```text
Case → 직접 해보니 Reference → 다음에 쓸 기준
Question → 아직 모르는 것 Concept → 어떻게 동작하나
Decision → 이렇게 하기로
```
## 2차 — 문어체로 다시 세웠다
1차 안이 기술 기록의 톤에 비해 가벼웠다. 역할은 그대로 말하되 문어체로 바꿨다.
```text
CASE → 검증 기록 CONCEPT → 동작 원리
REFERENCE → 적용 기준 DECISION → 설계 결정
QUESTION → 열린 질문
```
## 계약의 kind 는 그대로 뒀다
바꾼 것은 화면에 보이는 이름이다. 계약의 `RecordKind` 는 다섯 값 그대로이고, 주소도 그대로다.
표시 이름과 계약 값을 갈라 두면 이름을 다시 바꿀 때 계약을 건드리지 않아도 된다.
## 확인하지 못한 것
바꾼 이름이 읽기 쉬워졌는지는 재지 않았다. 1차 안이 가볍다는 판단은 사용자의 지적이고 측정이 아니다.
<!-- body:end -->
@@ -0,0 +1,85 @@
---
kind: QUESTION
slug: the-refusal-does-not-name-what-blocks-it
title: 삭제를 막는 이유 다섯 가지가 전부 같은 한 문장으로 나온다
topic: one-thing-many-names
topicName: 같은 것이 화면마다 다른 이름
project: TechLog
status: 게시 전
questionStatus: OPEN
evidence:
- ../../../final/evidence/raw/db/delete-blocked-by-project-link.txt
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§16.1
---
# 삭제를 막는 이유 다섯 가지가 전부 같은 한 문장으로 나온다
작업본 삭제가 막히는 이유는 다섯 가지인데 전부 같은 한 문장으로 나온다. 실제 사례에서 막은 것은 프로젝트 링크 한 행이었고, 문구는 「다른 기록이 참조한다」고 말했다. 문구가 잘못된 것을 가리키고 있다.
## 관계
- **서버는 하나를 답했는데 화면은 추측 셋을 출력했다**
화면 쪽 문구를 고친 사건이고, 서버 쪽 문구는 그대로 남았다.
- **그 SQL 은 한 번도 실행된 적이 없었다**
이 참조 검사를 실제 DB 에서 돌리게 만든 사건이다.
- **화면은 못 읽은 것을 없다고 말하지 않는다**
화면이 무엇을 말해야 하는지를 다루는 기준이다.
## 사실
작업본 삭제 실패는 다섯 가지 이유가 전부 같은 한 문장으로 나온다 — `another record still links to this one; unlink it first`.
실제로 막는 것은 다섯 참조 중 하나다.
```sql
SELECT 1 FROM document_relation WHERE target_document_id = :id
UNION ALL SELECT 1 FROM question_document_link WHERE document_id = :id
UNION ALL SELECT 1 FROM project_document_link WHERE document_id = :id
UNION ALL SELECT 1 FROM topic_featured_document WHERE document_id = :id
UNION ALL SELECT 1 FROM project_decision WHERE source_case_id = :id
```
실제 사례에서 관계를 다 지워도 삭제가 안 됐다. 남아 있던 것은 프로젝트 링크 한 행이었다.
프로젝트 연결은 「관계」 편집기가 아니라 문서의 Project 필드다. 관계를 아무리 지워도 그 행은 남는다.
사용자는 Project 필드를 「미지정」으로 바꾸고 저장한 뒤 삭제했다.
## 가정
문구가 `another record` 라고 말하므로 사용자가 관계를 먼저 찾는다고 보고 있다. 실제 사례가 하나이고, 다른 사용자가 같은 순서로 움직이는지는 확인하지 않았다.
다섯 참조를 종류별로 갈라도 성능이 문제가 되지 않는다고 보고 있다. 다섯 개의 존재 검사를 따로 돌리는 비용은 재지 않았다.
## 미지수
무엇이 막는지 말하면서 내부 테이블 이름을 노출하지 않는 문구가 무엇인가.
사용자가 고칠 수 있는 곳의 이름으로 옮기면 다섯 참조가 몇 가지로 줄어드는가. 문서의 Project 필드와 주제의 대표 기록은 서로 다른 화면이다.
## 제약
클라이언트에 내보내는 메시지에 내부 테이블 이름이나 컬럼 이름을 넣지 않는다.
참조 검사는 삭제 경로에서 돈다. 이 경로의 응답 시간을 늘리지 않는다.
## 선택지
**참조 검사를 종류별로 갈라 어느 것이 걸렸는지 돌려준다**
다섯 개의 존재 검사를 따로 돌리고 걸린 종류를 응답에 싣는다. 화면이 그 종류를 사용자가 고칠 수 있는 곳의 이름으로 옮긴다.
**막는 참조를 목록으로 돌려준다**
어느 기록이 걸었는지까지 보인다. 관계는 이름을 보일 수 있지만 프로젝트 링크와 주제 대표 기록은 다른 화면이라 이름만으로는 어디를 고칠지 알기 어렵다.
**문구만 고쳐 프로젝트 연결을 함께 언급한다**
가장 싸다. 다섯 중 어느 것인지는 여전히 말하지 못한다.
## 다음 검증
1. 참조 검사를 종류별로 갈라 걸린 종류를 응답에 실어 보고, 삭제 경로의 응답 시간이 얼마나 달라지는지 잰다
2. 다섯 종류를 사용자가 고칠 수 있는 화면 이름으로 옮겨 적고 몇 가지로 줄어드는지 센다
3. 실제로 막힌 작업본 하나로 새 문구를 보여 주고 어디를 고쳐야 하는지 문구만으로 찾을 수 있는지 확인한다
닫는 조건 : 삭제가 막혔을 때 어디를 고쳐야 하는지 문구만 보고 알 수 있으면 닫는다. 종류별로 가르는 비용이 응답 시간에 드러나면 문구만 고치는 쪽으로 정하고 Decision 으로 넘긴다
@@ -0,0 +1,61 @@
---
kind: REFERENCE
slug: ask-which-words-to-use
title: 톤을 지적받으면 고쳐 쓰지 말고 어떤 말을 쓸지 묻는다
topic: one-thing-many-names
topicName: 같은 것이 화면마다 다른 이름
project: TechLog
status: 게시 전
verifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§13.3
---
# 톤을 지적받으면 고쳐 쓰지 말고 어떤 말을 쓸지 묻는다
사용자가 프로필의 문구가 AI 스럽다고 지적했다. 고쳐 쓴 첫 번째 안도 거절당했고, 결국 사용자가 직접 쓴 텍스트를 그대로 실었다. 이 사이트의 글은 작성자가 자기 말로 쓴다. 더 나은 문장을 제안할 때와 그 사람의 말투로 쓸 때 필요한 것이 다르다.
## 관계
- **종류 이름을 두 번 바꿨다 — 화면의 이름과 계약의 kind 를 갈랐다**
두 번째 안을 문어체로 세울 때 이 기준을 썼다.
- **서버는 하나를 답했는데 화면은 추측 셋을 출력했다**
그 문구는 목소리가 아니라 서버가 답한 사실을 실어야 한다.
- **한 화면에 종류 이름이 아홉 개 떠 있었다 — 표가 여섯 벌이었다**
같은 시기에 종류 이름을 표 하나로 모았다.
## 목적
작성자의 목소리로 쓰인 글을 고쳐 쓰다 두 번 거절당하는 것을 막는다. 톤을 지적할 때 사용자가 가리키는 것은 문장의 품질이 아니라 그 말을 누가 쓰는가다.
## 규칙
**톤을 지적받으면 고쳐 쓰기 전에 어떤 말을 쓸지 묻는다**
「더 나은 문장」을 제안할 때와 그 사람의 말투로 쓸 때 필요한 것이 다르다.
**무엇이 AI 스러운지 구체적으로 받아 적는다**
무엇을 하는지 말하지 않는 동사로 끝나는 것과 번역투가 실제로 지적된 두 가지였다.
**작성자가 이미 쓰는 말투를 따른다**
Case 소제목에 쓰는 말이 「~한 것」 명사형이면 새 제목도 그 형태로 맞춘다. 의문형 꼬리와 이 기록에서 쓰지 않는 낱말은 쓰지 않는다.
## 적용 조건
공개 화면의 글이 작성자의 목소리인 곳 — 프로필, 프로젝트 소개, 구역 제목, 기록의 소제목.
## 예외
오류 문구처럼 서버가 답한 사실을 그대로 실어야 하는 곳에서는 말투를 묻지 않는다. 무엇을 실을지를 먼저 정한다.
계약이나 코드가 정한 이름은 이 규칙에서 뺀다. 표시 이름만 바꾸고 계약 값은 그대로 둔다.
## 예시
「섞는다」·「함께 기록한다」·「흩어지지 않게」가 무엇을 하는지 말하지 않는 동사로 끝난다고 지적받았다.
「결론이 서는 조건」·「프로젝트를 답니다」·「접근을 나눠 견주고」가 번역투로 지적받았다.
「무엇을 견줬나」는 의문형 꼬리에 이 기록에서 쓰지 않는 낱말이었다. 작성자가 Case 소제목에 쓰는 말은 「이 구조에서 감수한 것」처럼 「~한 것」 명사형이라 그쪽에 맞췄다.
고쳐 쓴 첫 번째 안이 거절당한 뒤 사용자가 직접 쓴 텍스트를 그대로 실었다.