docs(TechLog): 얇은 Case 열 편과 Question 셋을 저장소 실물로 채운다
SSOT 를 저장소에서 확인해 더 보강하고 그것으로 다시 썼다.
§7.2 참조 검사 SQL 을 문자열로 조립하는 실제 코드 — 컴파일러가 표 이름도
컬럼 이름도 보지 않는다는 것이 그 모양에서 드러난다
§11.2 section-heading-rank 가 미디어 쿼리 값을 먼저 걷어내는 이유(테스트 주석)
§16.1 질문 삭제는 참조가 둘뿐이라 같은 문제가 덜하다는 대조
Case 열 편과 Question 셋을 다시 썼다. Question 은 사실·가정·미지수·제약을 갈라
채우고 선택지마다 무엇을 감수하는지 적었다 — 오류 코드를 나누면 계약과 반입한 두
저장소가 함께 움직인다는 것처럼.
SSOT 62,643 → 68,319 자. 검사 넷 전부 통과한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6917ce2420
commit
fd221353a3
+11
-1
@@ -86,9 +86,19 @@ QUESTION → 열린 질문
|
||||
|
||||
두 안이 말하는 것은 같다. 「직접 해보니」와 「검증 기록」은 둘 다 그 글이 재현한 결과라고 말한다. 갈린 것은 이 사이트의 다른 글들이 쓰는 어조와 맞느냐다.
|
||||
|
||||
## 이름 표가 하나였기 때문에 두 번 바꿀 수 있었다
|
||||
|
||||
이름을 바꾸는 작업이 한 파일을 고치는 일이 됐다. 표가 화면마다 복사돼 있던 때였다면 두 번 바꾸는 동안 여섯 벌이 두 번씩 갈렸을 것이다.
|
||||
|
||||
같은 파일에 표가 하나 더 있다. 다섯 종류를 셋으로 접어 지식의 상태로 만드는 표다 — 확인한 것, 정리한 것, 아직 모르는 것.
|
||||
|
||||
> 미해결이 이 기록의 가장 정직한 신호인데 다섯 종류가 같은 회색 11px 로 나오면 그것이 가장 안 보인다.
|
||||
|
||||
이름을 바꿔도 이 표는 그대로였다. 표시 이름과 지식 상태가 다른 축이라 따로 두었기 때문이다.
|
||||
|
||||
## 계약의 kind 는 그대로 뒀다
|
||||
|
||||
바꾼 것은 화면에 보이는 이름이다. 계약의 `RecordKind` 는 다섯 값 그대로이고 주소도 그대로다.
|
||||
바꾼 것은 화면에 보이는 이름이다. 계약의 종류 값은 다섯 그대로이고 주소도 그대로다.
|
||||
|
||||
표시 이름과 계약 값을 갈라 두었기 때문에 두 번 바꾸면서 계약을 한 번도 건드리지 않았다. 계약을 바꿨다면 반입한 두 저장소가 함께 움직여야 했고, 이미 게시된 주소도 함께 흔들렸을 것이다.
|
||||
|
||||
|
||||
+25
-14
@@ -29,9 +29,13 @@ source:
|
||||
|
||||
## 사실
|
||||
|
||||
작업본 삭제 실패는 다섯 가지 이유가 전부 같은 한 문장으로 나온다 — `another record still links to this one; unlink it first`.
|
||||
작업본 삭제 실패는 다섯 참조 중 무엇이 막았든 같은 오류 코드로 나간다 — `DOCUMENT_IN_USE`.
|
||||
|
||||
실제로 막는 것은 다섯 참조 중 하나다.
|
||||
클라이언트에 나가는 문구는 코드마다 하나로 고정돼 있다. 그 코드의 문구는 「이 기록을 참조하는 곳이 있어 삭제할 수 없습니다」이다.
|
||||
|
||||
고정 문구를 두는 이유는 예외의 원문 메시지에 저장소 제약 이름이나 SQL 조각이 섞일 수 있어서다. 그 판단은 서버 쪽 클래스의 javadoc 에 적혀 있다.
|
||||
|
||||
참조 검사는 다섯 표를 하나의 존재 검사로 묶는다.
|
||||
|
||||
```sql
|
||||
SELECT 1 FROM document_relation WHERE target_document_id = :id
|
||||
@@ -41,47 +45,54 @@ UNION ALL SELECT 1 FROM topic_featured_document WHERE document_id = :id
|
||||
UNION ALL SELECT 1 FROM project_decision WHERE source_case_id = :id
|
||||
```
|
||||
|
||||
실제 사례는 「DTO 변환 과정에서 발생한 Highlight 컬렉션 N+1」이다. 관계를 다 지워도 삭제가 안 됐고, 남아 있던 것은 프로젝트 「Liner N + 1문제」로 가는 링크 한 행이었다.
|
||||
같은 어댑터의 질문 삭제는 참조가 둘뿐이라 같은 문제가 덜하다 — `project_question_link` 와 `home_focus_config.open_question_id` 다.
|
||||
|
||||
프로젝트 연결은 「관계」 편집기가 아니라 문서의 Project 필드다. 관계를 아무리 지워도 그 행은 남는다.
|
||||
|
||||
문구가 `another record` 라고 하니 관계를 찾아 지우게 되는데, 정작 막는 것은 record 가 아니라 프로젝트다. 문구가 잘못된 것을 가리키고 있다.
|
||||
실제 사례에서 관계를 다 지워도 삭제가 안 됐다. 남아 있던 것은 프로젝트 링크 한 행이었고, 그 링크는 「관계」 편집기가 아니라 문서의 Project 필드가 만든다.
|
||||
|
||||
사용자는 Project 필드를 「미지정」으로 바꾸고 저장한 뒤 삭제했다.
|
||||
|
||||
## 가정
|
||||
|
||||
문구가 `another record` 라고 말하므로 사용자가 관계를 먼저 찾는다고 보고 있다. 실제 사례가 하나이고, 다른 사용자가 같은 순서로 움직이는지는 확인하지 않았다.
|
||||
문구가 「another record」라고 하니 사용자가 관계를 먼저 찾는다고 보고 있다. 실제 사례가 하나이고, 다른 사용자가 같은 순서로 움직이는지는 확인하지 않았다.
|
||||
|
||||
다섯 참조를 종류별로 갈라도 성능이 문제가 되지 않는다고 보고 있다. 다섯 개의 존재 검사를 따로 돌리는 비용은 재지 않았다.
|
||||
다섯 참조를 종류별로 갈라도 응답 시간이 문제가 되지 않는다고 보고 있다. 하나의 존재 검사를 다섯 개로 나누는 비용은 재지 않았다.
|
||||
|
||||
질문 삭제처럼 참조가 둘뿐이면 이 문제가 덜하다고 보고 있다. 질문 삭제에서 사용자가 실제로 헤맨 기록은 없다.
|
||||
|
||||
## 미지수
|
||||
|
||||
무엇이 막는지 말하면서 내부 테이블 이름을 노출하지 않는 문구가 무엇인가.
|
||||
무엇이 막는지 말하면서 내부 표 이름을 노출하지 않는 문구가 무엇인가.
|
||||
|
||||
사용자가 고칠 수 있는 곳의 이름으로 옮기면 다섯 참조가 몇 가지로 줄어드는가. 문서의 Project 필드와 주제의 대표 기록은 서로 다른 화면이다.
|
||||
사용자가 고칠 수 있는 화면의 이름으로 옮기면 다섯 참조가 몇 가지로 줄어드는가. 문서의 Project 필드와 주제의 대표 기록은 서로 다른 화면이고, 관계 편집기는 또 다른 화면이다.
|
||||
|
||||
코드를 다섯으로 나누면 계약의 오류 코드 열거형도 함께 늘어난다. 그것을 반입하는 두 저장소가 그 값을 알아야 하는데, 그 비용이 얼마인가.
|
||||
|
||||
## 제약
|
||||
|
||||
클라이언트에 내보내는 메시지에 내부 테이블 이름이나 컬럼 이름을 넣지 않는다.
|
||||
클라이언트에 내보내는 메시지에 내부 표 이름이나 컬럼 이름을 넣지 않는다.
|
||||
|
||||
참조 검사는 삭제 경로에서 돈다. 이 경로의 응답 시간을 늘리지 않는다.
|
||||
|
||||
오류 코드는 계약이 열거한다. 코드를 늘리면 계약과 반입한 두 저장소가 함께 움직인다.
|
||||
|
||||
## 선택지
|
||||
|
||||
**참조 검사를 종류별로 갈라 어느 것이 걸렸는지 돌려준다**
|
||||
다섯 개의 존재 검사를 따로 돌리고 걸린 종류를 응답에 싣는다. 화면이 그 종류를 사용자가 고칠 수 있는 곳의 이름으로 옮긴다.
|
||||
다섯 개의 존재 검사를 따로 돌리고 걸린 종류를 응답에 싣는다. 화면이 그 종류를 사용자가 고칠 수 있는 화면의 이름으로 옮긴다. 코드를 늘리지 않고 응답의 부가 필드로 실으면 계약 변경이 작다.
|
||||
|
||||
**오류 코드를 참조 종류만큼 나눈다**
|
||||
문구가 코드마다 하나이므로 코드를 나누면 문구도 갈린다. 대신 계약의 열거형이 늘고 반입한 두 저장소가 함께 움직인다.
|
||||
|
||||
**막는 참조를 목록으로 돌려준다**
|
||||
어느 기록이 걸었는지까지 보인다. 관계는 이름을 보일 수 있지만 프로젝트 링크와 주제 대표 기록은 다른 화면이라 이름만으로는 어디를 고칠지 알기 어렵다.
|
||||
|
||||
**문구만 고쳐 프로젝트 연결을 함께 언급한다**
|
||||
가장 싸다. 다섯 중 어느 것인지는 여전히 말하지 못한다.
|
||||
가장 싸다. 다섯 중 어느 것인지는 여전히 말하지 못하고, 사용자가 확인할 화면이 셋으로 늘어난다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 참조 검사를 종류별로 갈라 걸린 종류를 응답에 실어 보고, 삭제 경로의 응답 시간이 얼마나 달라지는지 잰다
|
||||
2. 다섯 종류를 사용자가 고칠 수 있는 화면 이름으로 옮겨 적고 몇 가지로 줄어드는지 센다
|
||||
3. 실제로 막힌 작업본 하나로 새 문구를 보여 주고 어디를 고쳐야 하는지 문구만으로 찾을 수 있는지 확인한다
|
||||
3. 실제로 막힌 작업본 하나로 새 문구를 보여 주고, 어디를 고쳐야 하는지 문구만으로 찾을 수 있는지 확인한다
|
||||
|
||||
닫는 조건 : 삭제가 막혔을 때 어디를 고쳐야 하는지 문구만 보고 알 수 있으면 닫는다. 종류별로 가르는 비용이 응답 시간에 드러나면 문구만 고치는 쪽으로 정하고 Decision 으로 넘긴다
|
||||
|
||||
Reference in New Issue
Block a user