# SVG semantic review — 2026-09-01 기계 검증(`validate_svg.py`)은 통과하지만 그림이 기록의 주장과 반대를 말하는지 확인한 회차다. `validate_svg.py` 는 라벨 길이 · 문장형 · 상자 수 · 뷰포트만 본다. **화살표가 무엇을 뜻하는지는 보지 않는다.** 그래서 이번 검토는 사람이 했다. ## 검토 모집단 `` 가 부재(없 · 않 · 미배선 · 도달하지 · 연결되지 · 0건 · 존재하지 · 못하 · 빠진 · 비어 · 아니 · 끊)를 말하면서 정상 방향 화살표도 가진 설명용 SVG **33개**. 181개 중 그 조건에 걸리는 전부이며, 나머지 148개는 부재를 말하지 않으므로 이 회차의 대상이 아니다. 33개를 일괄 치환하지 않았다. 각각에 대해 다음 다섯을 대조했다. - 기록의 주장(`## 요약` · 본문) - owning SSOT 의 해당 finding - SVG 의 `` - 보이는 라벨 - 화살표의 방향과 도착 지점 ## 판정 기준 정상 방향 화살표는 **실재하는 호출 · 의존 · 전이 · 데이터 흐름 · 도달성**을 뜻한다. 그래서 도착 상자가 빗금이라는 사실만으로 화살표의 뜻이 뒤집히지 않는다. 그림이 결함인 경우는 **화살표가 가리키는 관계 자체가 없을 때**다. 반대로, 들어오는 전이는 실재하고 기록이 말하는 부재가 **나가는** 전이인 경우가 있다. 상태 기계의 종착 상태가 그 형태다. 그 경우 빗금 상자로 들어가는 화살표는 정확하다. ## 결과 | 판정 | 수 | |---|---:| | 재설계 | 3 | | 유지 — 들어오는 전이는 실재하고 부재는 나가는 쪽 | 3 | | 유지 — 빗금 상자에 화살표가 닿지 않음 | 2 | | 유지 — 빗금 상자가 없고 화살표가 전부 실재 흐름 | 25 | ## 재설계 3건 ### `adapter-inbound-graphql-c04.svg` 기록의 주장은 "요청 계층만 배선되고, 네 파생 계층은 메서드로 존재하되 프로덕션 호출자가 0" 이다. 기존 그림은 배선된 요청 데드라인에서 네 파생 계층으로 정상 화살표 넷을 그리고 그 위에 `파생 없음` 이라는 글자를 얹었다. 화살표가 글자를 이긴다. 고친 형태는 화살표를 **하나도 그리지 않는다.** 네 계층은 `파생 없음 — 프로덕션 호출자 0` 이라고 이름 붙인 별도 영역 안에 놓인다. ### `adapter-inbound-graphql-c10.svg` 주장은 "자동설정이 참조하는 두 타입에서 실제로 닿는 패키지는 dataloader 하나이고, fetch · pagination · mutation 41개 파일은 어떤 배선 경로에도 없다" 이다. 기존 그림은 네 갈래 전부에 정상 화살표를 그렸다. 고친 형태는 `dataloader` 에만 화살표를 두고, 나머지 셋은 `배선 경로 없음 — 화살표 없음` 영역에 놓는다. ### `adapter-inbound-websocket-c01.svg` 주장은 "설정 접두사 셋 중 `backend.websocket` 만 그것을 읽어 조립하는 `@Configuration` 이 없고, 그 접두사가 규정하는 범위가 main 169 파일 중 약 90개로 가장 넓다" 이다. 기존 그림은 세 갈래에 모두 정상 화살표를 그려, 접두사가 소비자에 닿는다는 뜻과 닿지 않는다는 뜻이 한 그림 안에서 충돌했다. 고친 형태는 소비자가 있는 두 접두사에만 화살표를 두고, `backend.websocket` 은 `읽는 Configuration 없음` 영역에 화살표 없이 놓는다. ## 유지 3건 — 들어오는 전이는 실재한다 ### `adapter-outbound-objectstorage-c05.svg` · `adapter-outbound-fileserver-c03.svg` 계열 `` 가 "그 네 상태에서 **나오는** 전이는 없다" 라고 적는다. 그림의 화살표 넷은 정상 사슬에서 그 상태로 **들어가는** 전이이고, 그것은 실재한다. 부재는 반대 방향이며 `` 가 방향을 밝힌다. 정확한 그림이다. ### `adapter-outbound-persistence-jpa-c51.svg` 주장은 "Stable persistence unit 의 스캔 문자열 목록에 experimental package 가 **이미 들어 있다**" 이다. 화살표는 그 목록이 그 항목을 담는다는 실재하는 포함 관계이고, 빗금은 부재가 아니라 바로 아래 라벨이 말하는 `조건 없음` 을 표시한다. ### `messaging-kafka-c02.svg` 주장은 "연속 구간만 커밋되고 빈 자리 뒤는 완료돼 있어도 보류된다" 이다. 화살표는 완료 표시 맵이 두 구간으로 갈리는 실재하는 분할이고, 빗금 상자는 없는 것이 아니라 `보류` 상태다. 라벨이 `빈 자리 뒤 구간 — 보류` 로 그것을 말한다. ## 유지 2건 — 빗금 상자에 화살표가 닿지 않는다 `grpc-policy-f02.svg` 와 `messaging-nats-experimental-f01.svg` 는 빗금 상자를 갖지만 어떤 화살표도 그 안으로 들어가지 않는다. 이미 이번 회차가 정한 규칙을 지키는 형태다. ## 유지 25건 — 빗금 상자가 없다 나머지 25개의 `` 에 나오는 부정 표현은 부재가 아니라 **규칙이나 순서**를 말한다 — "반대 방향 의존이 없다", "뒤 규칙이 앞 규칙이 금지한 것을 다시 허용할 수 없다", "검증되지 않은 설정을 쓰는 bean 이 생기지 않는다" 같은 형태다. 화살표는 전부 실재하는 흐름이고 빗금 상자 자체가 없다. ## 규칙을 어디에 고정했나 이 판정 기준을 `designing-tech-log-visuals` 에 명문화했다. - `SKILL.md` — hard gate 한 줄 - `references/diagram-editorial-rules.md` — "A normal arrow asserts that the relation exists" 절과, 부재를 그리는 세 형태(no edge · separated region · 명시적으로 라벨된 broken/crossed edge) - `references/review-checklist.md` — 검토 항목 한 줄 - `tools/tests/test_writing_quality_contracts.py` — 위 셋이 실제로 존재하는지 검사하는 테스트 ## 전 파일 분류 | SVG | 화살표 | 빗금 | 빗금 진입 | 판정 | |---|---:|---:|---:|---| | `adapter-inbound-graphql-c04.svg` | 0 | 4 | 0 | 재설계 | | `adapter-inbound-graphql-c10.svg` | 1 | 3 | 0 | 재설계 | | `adapter-inbound-web-c01.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-inbound-websocket-c01.svg` | 2 | 1 | 0 | 재설계 | | `adapter-outbound-cache-redis-c01.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-cache-redis-c03.svg` | 1 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-cache-redis-c08.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-cache-redis-c12.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-cache-redis-c13.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-fileserver-c03.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-httpclient-c04.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-objectstorage-c05.svg` | 4 | 4 | 4 | 유지 — 들어오는 전이는 실재 | | `adapter-outbound-persistence-jpa-c02.svg` | 1 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-persistence-jpa-c24.svg` | 1 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-persistence-jpa-c26.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-persistence-jpa-c51.svg` | 2 | 1 | 1 | 유지 — 들어오는 전이는 실재 | | `adapter-outbound-persistence-mongo-c03.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `adapter-outbound-support-c02.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `application-core-c01.svg` | 1 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `application-core-c04.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `commit-evidence-phases.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `grpc-advanced-resilience-c01.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `grpc-policy-f02.svg` | 3 | 1 | 0 | 유지 — 빗금 상자에 화살표 없음 | | `messaging-claim-check-c01.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-inbox-jdbc-postgresql-c06.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-kafka-c02.svg` | 2 | 1 | 1 | 유지 — 들어오는 전이는 실재 | | `messaging-nats-experimental-f01.svg` | 3 | 1 | 0 | 유지 — 빗금 상자에 화살표 없음 | | `messaging-policy-c03.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-pulsar-experimental-c01.svg` | 1 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-rabbit-c01.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-security-c03.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-testkit-c04.svg` | 2 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | | `messaging-transport-spi-c03.svg` | 3 | 0 | 0 | 유지 — 빗금 없음, 화살표가 전부 실재 흐름 | ## 좌표 직렬화 같은 회차에 정리했다. 설명용 SVG 40개의 좌표 340개가 소수점 둘 이상을 갖고 있었다 — `225.33333333333334` · `440.00000000000006` 같은 형태다. 렌더링은 같지만 생성기가 float repr 을 그대로 속성에 넣었다는 뜻이고, 같은 그림의 두 판을 diff 할 때 읽히지 않는다. 소수점 한 자리로 정규화했다(기하 변화 최대 0.05px). 그리고 규칙을 두 곳에 고정했다 — 생성기가 좌표를 직렬화할 때 한 자리로 자르고, `validate_svg.py` 가 `COORDINATE_PRECISION` 으로 설명용 SVG 를 검사한다. 터미널 SVG 는 대상이 아니다(원래 정수 좌표만 쓴다).