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>
5.7 KiB
kind, slug, title, topic, topicName, project, status, questionStatus, evidence, sourceRevision, source
| kind | slug | title | topic | topicName | project | status | questionStatus | evidence | sourceRevision | source | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| QUESTION | the-refusal-does-not-name-what-blocks-it | 삭제를 막는 이유 다섯 가지가 전부 같은 한 문장으로 나온다 | one-thing-many-names | 같은 것이 화면마다 다른 이름 | TechLog | 게시 전 | OPEN |
|
tech-log@2026-09-02 |
|
삭제를 막는 이유 다섯 가지가 전부 같은 한 문장으로 나온다
작업본 삭제가 막히는 이유는 다섯 가지인데 전부 같은 한 문장으로 나온다. 실제 사례에서 막은 것은 프로젝트 링크 한 행이었고, 문구는 「다른 기록이 참조한다」고 말했다.
관계
- 서버는 하나를 답했는데 화면은 추측 셋을 출력했다 화면 쪽 문구를 고친 사건이고, 서버 쪽 문구는 고치지 않았다.
- 그 SQL 은 한 번도 실행된 적이 없었다 이 참조 검사를 실제 DB 에서 돌리게 만든 사건이다.
- 화면은 못 읽은 것을 없다고 말하지 않는다 화면이 무엇을 말해야 하는지를 다루는 기준이다.
사실
작업본 삭제 실패는 다섯 참조 중 무엇이 막았든 같은 오류 코드로 나간다 — DOCUMENT_IN_USE.
클라이언트에 나가는 문구는 코드마다 하나로 고정돼 있다. 그 코드의 문구는 「이 기록을 참조하는 곳이 있어 삭제할 수 없습니다」이다.
고정 문구를 두는 이유는 예외의 원문 메시지에 저장소 제약 이름이나 SQL 조각이 섞일 수 있어서다. 그 판단은 서버 쪽 클래스의 javadoc 에 적혀 있다.
참조 검사는 다섯 표를 하나의 존재 검사로 묶는다.
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_question_link 와 home_focus_config.open_question_id 다.
실제 사례에서 관계를 다 지워도 삭제가 안 됐다. 남아 있던 것은 프로젝트 링크 한 행이었고, 그 링크는 「관계」 편집기가 아니라 문서의 Project 필드가 만든다.
사용자는 Project 필드를 「미지정」으로 바꾸고 저장한 뒤 삭제했다.
가정
문구가 「another record」라고 하니 사용자가 관계를 먼저 찾는다고 보고 있다. 실제 사례가 하나이고, 다른 사용자가 같은 순서로 움직이는지는 확인하지 않았다.
다섯 참조를 종류별로 갈라도 응답 시간이 문제가 되지 않는다고 보고 있다. 하나의 존재 검사를 다섯 개로 나누는 비용은 재지 않았다.
질문 삭제처럼 참조가 둘뿐이면 이 문제가 덜하다고 보고 있다. 질문 삭제에서 사용자가 실제로 헤맨 기록은 없다.
미지수
무엇이 막는지 말하면서 내부 표 이름을 노출하지 않는 문구가 무엇인가.
사용자가 고칠 수 있는 화면의 이름으로 옮기면 다섯 참조가 몇 가지로 줄어드는가. 문서의 Project 필드와 주제의 대표 기록은 서로 다른 화면이고, 관계 편집기는 또 다른 화면이다.
코드를 다섯으로 나누면 계약의 오류 코드 열거형도 함께 늘어난다. 그것을 반입하는 두 저장소가 그 값을 알아야 하는데, 그 비용이 얼마인가.
제약
클라이언트에 내보내는 메시지에 내부 표 이름이나 컬럼 이름을 넣지 않는다.
참조 검사는 삭제 경로에서 돈다. 이 경로의 응답 시간을 늘리지 않는다.
오류 코드는 계약이 열거한다. 코드를 늘리면 계약과 반입한 두 저장소가 함께 움직인다.
선택지
참조 검사를 종류별로 갈라 어느 것이 걸렸는지 돌려준다 다섯 개의 존재 검사를 따로 돌리고 걸린 종류를 응답에 싣는다. 화면이 그 종류를 사용자가 고칠 수 있는 화면의 이름으로 옮긴다. 코드를 늘리지 않고 응답의 부가 필드로 실으면 계약 변경이 작다.
오류 코드를 참조 종류만큼 나눈다 문구가 코드마다 하나이므로 코드를 나누면 문구도 갈린다. 대신 계약의 열거형이 늘고 반입한 두 저장소가 함께 움직인다.
막는 참조를 목록으로 돌려준다 어느 기록이 걸었는지까지 보인다. 관계는 이름을 보일 수 있지만 프로젝트 링크와 주제 대표 기록은 다른 화면이라 이름만으로는 어디를 고칠지 알기 어렵다.
문구만 고쳐 프로젝트 연결을 함께 언급한다 가장 싸다. 다섯 중 어느 것인지는 여전히 말하지 못하고, 사용자가 확인할 화면이 셋으로 늘어난다.
다음 검증
- 참조 검사를 종류별로 갈라 걸린 종류를 응답에 실어 보고, 삭제 경로의 응답 시간이 얼마나 달라지는지 잰다
- 다섯 종류를 사용자가 고칠 수 있는 화면 이름으로 옮겨 적고 몇 가지로 줄어드는지 센다
- 실제로 막힌 작업본 하나로 새 문구를 보여 주고, 어디를 고쳐야 하는지 문구만으로 찾을 수 있는지 확인한다
닫는 조건 : 삭제가 막혔을 때 어디를 고쳐야 하는지 문구만 보고 알 수 있으면 닫는다. 종류별로 가르는 비용이 응답 시간에 드러나면 문구만 고치는 쪽으로 정하고 Decision 으로 넘긴다