Files
document-haness/docs/TechLog/tech-log-studio/addresses-frozen-at-publish-time/case/case-an-address-frozen-at-publish-time.md
T
DongHyeonkaandClaude Opus 5 6feee5ba57 docs(TechLog): 자료에 남아 있던 사람의 흔적을 제자리에 놓는다
writing-as-the-person-who-did-it 을 서브에이전트 셋으로 나눠 56편에 적용했다.
56편 중 20편만 고쳤다 — 나머지 36편은 SSOT 를 절 단위로 대조했을 때 옮길 흔적이
이미 옮겨져 있었거나 없었다. 없는 목소리를 채우지 않는다.

옮긴 것은 전부 SSOT 의 어느 절에서 왔는지 댈 수 있다.

  §3.4  「눈으로 찾을 일이 아니었다」— 세 계약을 파싱해 뽑은 이유
  §4.3  구현하지 않기로 한 것과 빠뜨린 것은 다르다
  §8.5  표의 마지막 줄을 더할 때 이 목록을 또 빠뜨렸다
  §9.4  「왜 주제 링크가 탐색으로 가지?」— 우회를 남겨 두면 계속 나온 질문
  §11.3 「세 버튼」을 실제 이름으로 되돌리고 두 언어가 섞인 것을 그 자리에
  §12.2 막지 않은 대신 메모리에 남긴 것
  §13.1 여섯 벌 인용이 어느 커밋이 짚은 말인지
  §13.3 고쳐 쓴 첫 안이 거절당한 것과 사용자가 고른 말 두 쌍
  §14.3 「문서가 그대로 나온다」는 구조 차이가 아니라 내용 양의 차이라는 정정
  §16.1 삭제가 막힌 실제 기록 이름과 그것을 막은 프로젝트 링크
  §16.9 주제 논지와 축 결론이 AI 가 써서 DB 에 직접 넣은 미검토 초안이라는 것
  §17.5 바운딩 박스로 잘못 지목한 대상이 「판단 기준」이었다는 것

검증 환경의 커밋 해시 하나가 틀려 있었다(ca1cfa2 → ca1fc92). SSOT §13.1 과
부록 A 가 적은 값이고 저장소에 그 커밋이 있다.

검사 넷 전부 통과한다 — check_prose 56편 error 0 · check_body PASS ·
check_evidence --repo 문제 없음 · verify-tech-log-tree 프로젝트 5 error 0 warn 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 16:31:48 +09:00

5.7 KiB

kind, slug, title, topic, topicName, project, status, lastVerifiedOn, assets, evidence, sourceRevision, source
kind slug title topic topicName project status lastVerifiedOn assets evidence sourceRevision source
CASE an-address-frozen-at-publish-time 계약은 앵커라고 적었고 만드는 쪽은 경로를 만들었다 — 이미 저장된 행까지 고쳤다 addresses-frozen-at-publish-time 주소가 만들어지고 굳어지는 곳 TechLog 게시 전 2026-09-04
key file
decision-path-404 ../../../final/assets/diagrams/decision-path-404/decision-path-404.svg
../../../final/evidence/raw/db/decision-path-after-v15.txt
../../../final/evidence/raw/api/decision-anchor-fixed.txt
../../../final/evidence/raw/audit/dead-link-sweep.txt
tech-log@2026-09-02
final/document.md#§9.2

계약은 앵커라고 적었고 만드는 쪽은 경로를 만들었다 — 이미 저장된 행까지 고쳤다

공개 화면의 「다음에 읽을 것」 두 번째 항목이 404 였다. 계약은 결정의 공개 주소가 목록 위의 앵커라고 이미 적어 두었는데, 주소를 만드는 두 곳이 그 대신 별도 경로를 만들고 있었다. 주소는 게시할 때 만들어 DB 에 저장되므로 코드만 고치면 이미 게시된 링크는 깨진 채 남는다.

관계

  • 서버가 준 주소는 라우트 표에 맞춰 보고, 맞는 라우트가 없으면 링크로 그리지 않는다 이 사건에서 세운 두 겹 가드다.
  • 결정에는 상세 화면이 없어 목록 항목이 문서 전체를 실어야 했다 같은 앵커 구조에서 난 계약 쪽 사건이다.
  • 축 링크가 자기 자신을 가리켰고, 고친 뒤에는 백엔드를 먼저 배포했다 같은 시기에 주소를 옮기다 난 다른 사건이다.

문제

/references/external-idp-federation-application-boundary 의 「다음에 읽을 것」 두 번째 항목이 404 였다.

화면 코드 어디에도 그 주소를 만드는 곳이 없다. 주소는 게시할 때 서버가 만들어 DB 에 저장한 문자열이고, 화면은 그것을 그대로 링크로 그린다.

결론

결정에는 상세 화면이 없고 공개 라우트는 목록 하나뿐인데, 게시할 때 만든 주소는 목록 아래에 slug 를 붙인 경로였다.

계약 : 공개 주소가 앵커라고 이미 적혀 있었다 게시 시점 : 앵커가 아니라 경로를 만들어 저장했다 조회 시점 : 저장된 주소를 읽어 링크로 내보냈다 방문자 : 맞는 라우트가 없어 404

고친 것은 넷이다.

두 곳이 앵커를 만들게 했다 이미 게시된 행도 V15 마이그레이션에서 함께 고쳤다 — 코드만 고치면 기존 링크는 깨진 채 남는다 공개 라우트의 slug 를 앵커가 있으면 그 뒤를 조각으로 읽게 했다 목록 항목이 앵커를 달 수 있도록 계약에 slug 를 더하고, 화면이 그 slug 를 element id 로 달고 앵커로 들어오면 데이터를 받아 그린 뒤 스크롤하게 했다

배포 후 서버가 내보내는 주소 26개와 주제·축 9개를 더해 35개 전부 200 인 것을 확인했다.

검증 환경

tech-log-design-package : 1aae8dc tech-log-backend : 8cd8ee3 · V15 마이그레이션 적용 tech-log-frontend : fe6b56a 확인 방식 : 배포본에서 서버가 내보내는 주소를 전수로 훑어 상태 코드를 셌다

재현 조건

  1. 결정을 하나 게시하고 다른 기록에서 그것을 관계로 건다
  2. 공개 화면에서 그 관계 링크를 누른다
  3. 저장된 주소와 공개 라우트 패턴을 대조한다 — 맞는 라우트가 없으면 404 다

본문

주소가 만들어져 저장되고 방문에서 끝난다

:::evidence key="decision-path-404" alt="계약·게시 시점 경로 생성·저장 테이블·조회 시점 경로 생성·방문자·공개 라우트 여섯 참가자 사이의 순서도" caption=" " zoom="true" :::

계약은 결정의 공개 주소가 앵커라고 규정한다. 게시 시점의 PublicPaths.forKind 는 그 대신 경로를 만들어 public_resource_projection 에 저장한다. 조회 시점의 PublicSql.pathOf 가 저장된 주소를 읽고 방문자에게 링크로 내보낸다. 방문자가 그 주소를 요청하면 공개 라우트에는 목록 하나뿐이라 맞는 라우트가 없다.

계약은 이미 맞게 적혀 있었다

공개 주소가 #{slug} 앵커라는 것이 계약에 이미 있었고, 만드는 쪽 두 곳이 그것을 따르지 않았다.

저장된 행까지 고쳐야 한다

주소가 게시 시점에 굳어져 저장되므로 코드만 고치면 이미 게시된 링크는 깨진 채 남는다. V15 마이그레이션에서 저장된 행도 고쳤다.

public_route.slug 도 손봤다. 마지막 슬래시 뒤를 자르면 앵커가 붙은 주소에서 decisions#slug 전체가 slug 로 저장된다. 앵커가 있으면 그 뒤를 조각으로 읽게 했다.

두 겹 가드

PublicPathsTest 는 백엔드에서 종류마다 만들어 낸 경로가 실제 공개 라우트 패턴에 맞는지 본다.

resolvesToPublicRoute 는 프론트에서 라우트 계약이 준 표에 서버가 준 주소를 맞춰 보고, 맞는 라우트가 없으면 링크로 그리지 않는다. 이 부류가 또 생겨도 방문자가 404 를 만나지는 않는다. 틀린 주소가 만들어지는 것 자체는 백엔드 쪽 검사가 잡는다.

배포 뒤 전수 감사

배포 후 사이트 전체를 훑어 서버가 내보내는 주소 26개와 주제·축 9개를 더해 35개 전부 200 인 것을 확인했다.

:::evidence key="dead-link-sweep" alt="서버가 내보내는 주소 35개를 전수로 훑은 감사 출력" caption=" " zoom="false" :::

확인하지 못한 것

이 감사는 서버가 내보내는 주소만 본다. 본문 안에 작성자가 손으로 쓴 링크는 대상이 아니다.