docs(TechLog): 남은 주제를 다시 쓰고 SSOT 를 저장소 실물로 더 보강한다

주제 11~13 을 다시 쓰고, Case 가 얇은 것들을 저장소에서 실물을 확인해 채웠다.

  §13.4  ManagementClientSafeMessages — 삭제 관련 코드 여섯의 고정 문구와
         원문 메시지를 내보내지 않는 이유(javadoc)
  §16.1  다섯 참조가 전부 DOCUMENT_IN_USE 하나로 나가고, SSOT 가 인용한 영어 문장은
         DeleteDocumentDraftUseCase 안에 남는 진단 메시지라 밖으로 나가지 않는다
  §13.6  romanizeSyllable 실물과 음운 변동을 뺀 이유, 문서 slug 와 같은 정규식을 쓰는 이유
  §15.4  check:types 가 도는 tsconfig 여섯 — app·node·test·recipes·web-worker·service-worker

SSOT 62,643 → 67,526 자. 인용한 코드는 전부 저장소에서 찾아 대조했다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-07 19:12:37 +09:00
co-authored by Claude Opus 5
parent b1653dbba8
commit 6917ce2420
14 changed files with 279 additions and 99 deletions
@@ -57,22 +57,51 @@ tech-log-backend : 857e6a9 — 삭제 거절 사유를 클라이언트 안전
## 화면이 세 가지를 추측했다
화면 문구는 「게시됐거나, 참조하는 곳이 있거나, 누가 먼저 고쳤을 수 있습니다」다. 세 가지 원인을 나열하고 어느 것인지는 말하지 않는다.
작업본 삭제가 실패하면 화면이 「게시됐거나, 참조하는 곳이 있거나, 누가 먼저 고쳤을 수 있습니다」를 적었다. 세 가지 원인을 나열하고 어느 것인지는 말하지 않는다.
서버는 하나를 답하고 있었다. 게이트웨이가 그 답을 버리고 화면이 자기 목록을 그렸다.
## 서버는 코드로 답한다
서버는 오류 코드마다 고정 문구를 갖고 있다. 삭제와 관련된 것만 여섯이다.
```java
case VERSION_CONFLICT -> "다른 곳에서 먼저 수정되었습니다. 새로 불러온 뒤 다시 시도해 주세요";
case DOCUMENT_PUBLISHED -> "공개된 기록은 삭제할 수 없습니다. 먼저 공개를 취소해 주세요";
case DOCUMENT_IN_USE -> "이 기록을 참조하는 곳이 있어 삭제할 수 없습니다";
case QUESTION_IN_USE -> "이 질문을 참조하는 곳이 있어 삭제할 수 없습니다";
case DECISION_IN_USE -> "이 결정을 참조하는 곳이 있어 삭제할 수 없습니다";
case TOPIC_IN_USE -> "이 주제를 쓰는 기록이 있어 삭제할 수 없습니다";
```
화면이 추측하던 셋이 이 중 셋에 그대로 있다. 코드는 카테고리와 재시도 가능 여부도 함께 답한다.
## 왜 원문 메시지를 안 내보내나
고정 문구를 두는 이유가 그 클래스의 javadoc 에 있다.
> code 별 고정 문구. 예외의 원문 메시지는 진단용이라 그대로 내보내지 않는다 — 저장소 제약 이름이나 SQL 조각이 새어 나갈 수 있고, 그건 클라이언트가 분기할 값도 아니다.
그래서 화면이 실어 나를 수 있는 것은 이 고정 문구다. 서버 안의 진단 메시지는 서버 로그에만 남는다.
## 무엇이 구분되지 않았나
버전 충돌은 「누가 먼저 고쳤다」이고 참조 존재는 「사용 중」이다. 문구가 셋을 한꺼번에 적으므로 작성자는 둘을 구분할 수 없다.
세 원인은 해야 할 일이 다르다.
버전 충돌이면 다시 받아서 지우면 되고, 참조가 있으면 그 참조를 먼저 풀어야 한다.
| 무엇이 막았나 | 작성자가 할 일 |
|---|---|
| 버전 충돌 | 다시 받아서 지운다 |
| 참조가 있음 | 그 참조를 먼저 푼다 |
| 이미 게시됨 | 게시를 취소한다 |
## 서버의 답을 실어 나른다
문구가 셋을 함께 적으므로 작성자는 어느 것인지 모른 채 세 가지를 다 시도하게 된다. 어떤 삭제는 되고 어떤 삭제는 안 되는 것을 지켜보면서도 둘을 구분할 방법이 없었다.
게이트웨이가 서버의 클라이언트 안전 메시지를 그대로 싣고 화면이 그것을 보인다.
## 고친 것
게이트웨이가 서버의 클라이언트 안전 메시지를 그대로 싣고 화면이 그것을 보인다. 서버가 답하지 않은 것을 화면이 만들지 않는다.
## 확인하지 못한 것
서버가 답하는 그 한 문장이 다섯 이유를 다 같은 말로 덮고 있다. 참조 검사가 다섯 테이블을 하나로 묶어 검사하기 때문이고, 그 문제는 아직 열려 있다.
코드 하나에 문구 하나라는 구조는 참조가 어느 표에서 왔는지까지는 말하지 못한다. 다섯 참조가 전부 같은 코드로 나가므로, 그 안에서 어느 것이 막았는지는 아직 열려 있다.
<!-- body:end -->
@@ -67,9 +67,9 @@ tech-log-frontend : dc2fda7 · ca1fc92 · 82e992d
바로 아래 「종류별로 읽기」: 검증 기록 · 동작 원리 · 적용 기준 · 열린 질문
```
두 목록이 세로로 붙어 있다. 위는 계약의 enum 이름을, 아래는 사람이 붙인 이름을 쓴다.
두 목록이 세로로 붙어 있다. 위는 계약의 enum 이름을, 아래는 사람이 붙인 이름을 쓴다. 독자는 둘이 같은 것이라는 단서를 어디서도 받지 못했다.
화면은 이름을 바꾸기 전보다 나빠졌다. 바꾸기 전에는 양쪽이 다 enum 이름이 적어도 같아 보였다.
름을 바꾸기 전에는 양쪽이 다 enum 이름이었으므로 적어도 같아 보였다. 이 화면은 이름을 바꾸면서 나빠졌다.
## 표가 여섯 벌이었다
@@ -77,9 +77,17 @@ tech-log-frontend : dc2fda7 · ca1fc92 · 82e992d
> 표가 화면마다 복사되어 **여섯 벌**이었고 그래서 갈라졌다: 같은 QUESTION 이 공개 화면에서 "Open Question", 작업본 목록과 게시 기록에서 "Question", 편집기 상태 줄에서 "QUESTION" 이었다. **쓰는 사람은 같은 문서를 화면마다 다른 이름으로 만난다.**
여섯 벌이 동시에 틀린 것이 아니다. 이름을 바꿀 때 그중 일부만 고쳤고, 어느 것을 고쳤는지가 화면마다 달랐다.
## 표 하나로 모았다
종류에서 표시 이름으로 가는 표를 하나 만들고 여섯 곳이 그것을 쓰게 했다. 종류가 늘면 그 표에서 빠진 값을 컴파일러가 잡는다.
종류에서 표시 이름으로 가는 표를 하나 만들고 여섯 곳이 그것을 쓰게 했다. 그 표의 javadoc 이 왜 한 곳에 있는지를 적는다.
> 한 곳에 두면 다음에 종류가 늘어날 때도 한 번만 고친다. 종류를 더하면 이 표가 비어 있는 것을 타입이 잡는다 — `Record<RecordKind, string>` 이므로 빠진 종류가 있으면 컴파일되지 않는다.
같은 파일에 표가 하나 더 있다. 다섯 종류를 셋으로 접어 지식의 상태로 만드는 표다.
> 독자가 실제로 구분해야 하는 것은 지식의 상태다. 다섯 종류를 셋으로 접는다 — 확인한 것, 정리한 것, 아직 모르는 것. 목록에서 미해결만 눈에 띄게 하는 것이 이 표의 쓰임이다. 미해결이 이 기록의 가장 정직한 신호인데 다섯 종류가 같은 회색 11px 로 나오면 그것이 가장 안 보인다.
## 편집기 칸 이름도 맞췄다
@@ -96,6 +104,6 @@ tech-log-frontend : dc2fda7 · ca1fc92 · 82e992d
## 확인하지 못한 것
이름을 바꾸기 전보다 나빠진 화면이 홈 하나였다는 것은 화면으로 확인했다. 다른 화면에서 두 이름이 같이 뜨는 곳을 전수로 세지는 않았다.
이름을 바꾸기 전보다 나빠진 화면이 홈이라는 것은 화면으로 확인했다. 다른 화면에서 두 이름이 같이 뜨는 곳을 전수로 세지는 않았다.
<!-- body:end -->
@@ -62,7 +62,7 @@ tech-log-frontend : a6413d0 → af5a6bb
Case, Reference, Open Question 은 그 글을 어떤 형식에 담았는지를 말한다. 그 글이 독자에게 무엇을 주는지는 말하지 않는다.
독자는 그 말을 먼저 배워야 목록을 읽을 수 있었다. 뜻풀이는 홈 바닥 2,000px 아래에 있었다.
독자는 그 말을 먼저 배워야 목록을 읽을 수 있었고, 뜻풀이는 홈 바닥 2,000px 아래에 있었다. 목록을 훑는 사람이 거기까지 내려가지 않는다.
## 1차 — 하는 일을 말하게 했다
@@ -72,9 +72,11 @@ Question → 아직 모르는 것 Concept → 어떻게 동작하나
Decision → 이렇게 하기로
```
이름만 읽어도 그 글이 무엇을 주는지 알 수 있다. 뜻풀이를 찾아 내려갈 이유가 없어진다.
## 2차 — 문어체로 다시 세웠다
1차 안이 기술 기록의 톤에 비해 가벼웠다. 역할은 그대로 말하되 문어체로 바꿨다.
**그런데 이게 기술 기록의 톤에 비해 가벼웠다.** 역할은 그대로 말하되 문어체로 바꿨다.
```text
CASE → 검증 기록 CONCEPT → 동작 원리
@@ -82,9 +84,13 @@ REFERENCE → 적용 기준 DECISION → 설계 결정
QUESTION → 열린 질문
```
두 안이 말하는 것은 같다. 「직접 해보니」와 「검증 기록」은 둘 다 그 글이 재현한 결과라고 말한다. 갈린 것은 이 사이트의 다른 글들이 쓰는 어조와 맞느냐다.
## 계약의 kind 는 그대로 뒀다
바꾼 것은 화면에 보이는 이름이다. 계약의 `RecordKind` 는 다섯 값 그대로이고 주소도 바뀌지 않았다.
바꾼 것은 화면에 보이는 이름이다. 계약의 `RecordKind` 는 다섯 값 그대로이고 주소도 그대로다.
표시 이름과 계약 값을 갈라 두었기 때문에 두 번 바꾸면서 계약을 한 번도 건드리지 않았다. 계약을 바꿨다면 반입한 두 저장소가 함께 움직여야 했고, 이미 게시된 주소도 함께 흔들렸을 것이다.
## 확인하지 못한 것
@@ -29,19 +29,25 @@ source:
작성자의 목소리로 쓰인 글을 고쳐 쓰다 두 번 거절당하는 것을 막는다.
톤을 지적할 때 사용자가 가리키는 것은 문장의 품질이 아니라 그 말을 누가 쓰는가다. 「더 나은 문장」을 제안할 때와 그 사람의 말투로 쓸 때 필요한 것이 다르고, 후자는 제안하는 쪽이 잘하지 못한다.
## 규칙
### 1. 톤을 지적받으면 고쳐 쓰기 전에 어떤 말을 쓸지 묻는다
「더 나은 문장」을 제안하는 것과 그 사람의 말투로 쓰는 것은 다른 일이고, 후자는 제안하는 쪽이 잘하지 못한다.
고쳐 쓴 안을 내면 그것도 같은 이유로 거절될 수 있다. 실제로 첫 번째 안이 거절당했고, 결국 사용자가 직접 쓴 텍스트를 그대로 실었다.
### 2. 무엇이 AI 스러운지 구체적으로 받아 적는다
무엇을 하는지 말하지 않는 동사로 끝나는 것과 번역투가 실제로 지적된 두 가지였다.
지적이 「AI 스럽다」로 끝나면 무엇을 고칠지 알 수 없다. 이 저장소에서 받은 지적은 두 갈래였다 — 무엇을 하는지 말하지 않는 동사로 끝나는 것(「섞는다」·「함께 기록한다」·「흩어지지 않게」)과 번역투(「결론이 서는 조건」·「프로젝트를 답니다」·「접근을 나눠 견주고」).
### 3. 작성자가 이미 쓰는 말투를 따른다
Case 소제목에 쓰는 말이 「~한 것」 명사형이면 새 제목도 그 형태로 맞춘다. 의문형 꼬리와 이 기록에서 쓰지 않는 낱말은 쓰지 않는다.
새 문구를 만들 때 기존 글에 없던 어미나 낱말을 들이지 않는다. 이 저장소의 Case 소제목은 「이 구조에서 감수한 것」처럼 「~한 것」 명사형이라, 의문형 꼬리를 단 「무엇을 견줬나」는 그 소제목들과 나란히 서지 못했다.
### 4. 고친 결과를 전후로 함께 적는다
무엇이 무엇으로 바뀌었는지 남겨 두면 다음에 같은 문구를 고칠 때 방향이 정해진다.
## 적용 조건
@@ -52,17 +58,12 @@ Case 소제목에 쓰는 말이 「~한 것」 명사형이면 새 제목도 그
## 예외
- 오류 문구처럼 서버가 답한 사실을 그대로 실어야 하는 곳에서는 말투를 묻지 않는다. 무엇을 실을지를 먼저 정한다.
- 계약이나 코드가 정한 이름은 이 규칙에서 뺀다. 표시 이름만 바꾸고 계약 값은 건드리지 않는다.
- 계약이나 코드가 정한 이름은 이 규칙에서 뺀다. 표시 이름만 바꾸고 계약 값은 그대로 둔다.
## 예시
- 「섞는다」·「함께 기록한다」·「흩어지지 않게」가 무엇을 하는지 말하지 않는 동사로 끝난다고 지적받았다.
-결론이 서는 조건」·「프로젝트를 답니다」·「접근을 나눠 견주고」가 번역투로 지적받았다.
-무엇을 견줬나」는 의문형 꼬리에 이 기록에서 쓰지 않는 낱말이었다. 작성자가 Case 소제목에 쓰는 말은 「이 구조에서 감수한 것」처럼 「~한 것」 명사형이라 그쪽에 맞췄다.
- 「이 프로젝트가 밝힌 것」은 「프로젝트를 통해 확인한 결과」로, 「운영 가능한 설계로 연결합니다」는 「실제 운영에 적용할 수 있는 형태로 정리합니다」로 바꿨다.
- 고쳐 쓴 첫 번째 안이 거절당한 뒤 사용자가 직접 쓴 텍스트를 실었다.
- 「섞는다」·「함께 기록한다」·「흩어지지 않게」가 무엇을 하는지 말하지 않는 동사로 끝난다고 지적받았다
- 「결론이 서는 조건」·「프로젝트를 답니다」·「접근을 나눠 견주고」가 번역투로 지적받았다
-무엇을 견줬나」는 의문형 꼬리에 이 기록에서 쓰지 않는 낱말이었다. 작성자가 Case 소제목에 쓰는 말은 「~한 것」 명사형이라 그쪽에 맞췄다
- 「이 프로젝트가 밝힌 것」을 「프로젝트를 통해 확인한 결과」로 바꿨다
-운영 가능한 설계로 연결합니다」를 「실제 운영에 적용할 수 있는 형태로 정리합니다」로 바꿨다