Files
document-haness/docs/TechLog/tech-log-studio/failure-drawn-as-absence/case/case-it-said-there-were-no-open-questions.md
T
DongHyeonkaandClaude Opus 5 ab59130196 chore: 이전 세션이 남긴 변경을 커밋한다
이번 파이프라인 작업과 무관하게 작업 트리에 남아 있던 것을 그대로 올린다.
사용자가 「전부 커밋」으로 정했고, 이번 작업과 섞이지 않게 커밋만 나눴다.

대부분은 clean-architecture-backend-template 의 그림 정본 재배치다 —
final/assets/diagrams/<이름>/ 에 있던 것이 CLAUDE.md 가 적은 배치인
final/assets/<이름>/ 로 옮겨졌고 .techviz/<이름>/ 이 함께 들어왔다.
삽입 줄의 대부분(3.15M)이 그 .techviz context.json 이다.

그 밖에 ca-tmpl·document-haness 의 정리, .claude/agents/ 열한 개,
writing-practitioner-guides 스킬, .playwright-mcp 세션 산출물,
scripts/check-ssot-facts.py 와 그 시험이 들어 있다.

이 커밋의 내용은 내가 만든 것이 아니라 이전 세션이 남긴 것이고 검증하지 않았다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:02:02 +09:00

105 lines
5.5 KiB
Markdown

---
kind: CASE
slug: it-said-there-were-no-open-questions
title: 「이 프로젝트에 열린 질문이 없습니다」 — 실제로는 넷이 있었다
topic: failure-drawn-as-absence
topicName: 실패를 없음으로 그린다
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§10.1
---
# 「이 프로젝트에 열린 질문이 없습니다」 — 실제로는 넷이 있었다
홈 「지금 집중하는 것」 편집기가 「이 프로젝트에 열린 질문이 없습니다」라고 적었다. 실제로는 넷이 있었고 공개 사이트에도 나오고 있었다. 편집기가 질문과 결정을 못 읽으면 빈 배열로 삼키고 있었다.
## 관계
- **화면은 못 읽은 것을 없다고 말하지 않는다**
이 사건에서 굳힌 규칙이다.
- **계약에 선언만 있고 구현이 없어 화면 다섯 곳이 비어 있었다**
못 읽은 원인이 그 기록에 있다 — 컨트롤러가 없었다.
- **한 칸의 실패가 옆 칸을 끌고 내려갔다**
같은 편집기에서 난 다른 부류의 실패다.
## 문제
홈 편집기에서 「지금 집중하는 것」에 걸 질문을 고르려 했다. 목록이 비어 있고 「이 프로젝트에 열린 질문이 없습니다」가 적혀 있었다.
같은 프로젝트의 공개 사이트에는 질문 넷이 나오고 있었다.
## 결론
편집기가 질문과 결정 목록을 못 읽으면 빈 배열로 삼키고 있었다. 서버는 404 를 주고 있었다 — 그 두 연산에 컨트롤러가 없었다.
작성자에게는 「아직 안 쓴 것」으로 읽힌다. 그래서 화면이 지킬 규칙을 하나 정했다.
거짓말을 하느니 못 읽었다고 말한다.
못 읽었을 때 못 읽었다고 적게 고쳤다. 같은 판단을 주제 탭에도 적용했다.
## 검증 환경
tech-log-frontend : 7acde27 · 3bb724b
tech-log-backend : 911e8ba — 없던 두 컨트롤러를 구현
확인 방식 : 편집기 목록과 공개 사이트의 같은 프로젝트를 대조
## 재현 조건
1. 프로젝트에 Open Question 을 하나 이상 게시한다
2. 그 목록을 주는 연산을 서버에서 막는다
3. 홈 편집기를 연다 — 옛 코드에서는 「없습니다」가, 지금은 못 읽었다는 문구가 나온다
## 본문
<!-- body:start -->
## 빈 배열이 두 가지를 뜻했다
편집기는 질문 목록을 받아 고를 수 있게 그린다. 목록이 비면 「이 프로젝트에 열린 질문이 없습니다」를 적는다.
요청이 실패했을 때도 빈 배열이 되고 있었다. 실패 경로가 빈 값을 만들고, 그 아래의 「비어 있으면 이 문구」 분기가 두 경우를 같은 화면으로 만든다.
서버는 404 를 주고 있었다. 그 두 목록 조회에 컨트롤러가 없었고, 계약에는 선언돼 있어 프론트가 그것을 믿고 불렀다.
## 작성자가 무엇으로 읽었나
작성자는 자기가 쓴 것과 화면을 대조한다. 화면이 「없습니다」라고 하면 아직 안 썼거나 게시하지 않았다고 읽는다.
이 경우에는 넷이 있었고 공개 사이트에도 나오고 있었다. 두 화면이 같은 데이터베이스를 보는데 한쪽만 비어 있었으므로, 공개 사이트를 함께 열어 보지 않으면 알아챌 방법이 없었다.
읽기 전용 화면이면 방문자가 「데이터가 없나 보다」로 넘어간다. 작성 도구에서는 그 오독이 곧바로 작업 판단이 된다 — 없다고 읽으면 다시 쓰게 된다.
## 이 설정은 없는 대상을 가리킬 수 있다
홈이 무엇을 앞에 세울지 정하는 설정은 지목한 대상에 외래키를 걸지 않는다. 설정이 대상보다 오래 살아남는 것을 허용하는 설계다.
대신 저장할 때 그 대상이 실제로 있는지 확인한다. 확인하지 않으면 없는 id 가 그대로 저장되고, 공개 화면은 조용히 빈 focus 를 그린다 — 저장은 성공했는데 화면에는 아무것도 안 나오는, 이유를 알 수 없는 실패가 된다.
확인하는 것은 있는지까지다. 그 대상이 공개인지는 저장할 때 보지 않는다. 아직 게시하지 않은 프로젝트를 미리 지목해 두고 게시와 동시에 홈에 뜨게 하는 것이 정상적인 순서이고, 공개 여부는 공개 조회 쪽이 매번 다시 판단한다.
같은 화면의 두 자리가 반대로 처리돼 있었다. 저장 쪽은 없는 대상을 막고, 목록을 못 읽은 쪽은 없는 것으로 그렸다.
## 못 읽었다고 적는다
> 거짓말을 하느니 못 읽었다고 말한다.
요청이 실패하면 실패했다고 적고 0건은 0건이라고 적는다. 이 둘을 구분할 수 있어야 작성자가 다음에 무엇을 할지 정한다 — 실패면 다시 부르거나 서버를 보고, 0건이면 쓰면 된다.
실패를 빈 값으로 접는 지점을 없애는 것이 고치는 방법이다. 문구만 바꾸면 그 지점이 그대로여서 다음 화면에서 같은 일이 난다.
## 같은 판단을 다른 화면에
주제 탭에도 같은 판단을 적용했다. 탭 하나를 못 받아도 탭 줄과 나머지 탭은 그대로 그리고, 못 받은 탭에는 못 받았다고 적는다.
탭 줄이 남는 것이 중요하다. 탭 줄까지 사라지면 그 주제가 없는 것처럼 보이고, 못 읽은 범위가 화면에서 더 넓어진다.
## 확인하지 못한 것
화면이 못 읽은 것을 없다고 그리는 곳을 전수로 세지 않았다. 고친 것은 홈 편집기와 주제 탭 둘이다.
<!-- body:end -->