docs(TechLog): 글감 56개를 기록으로 쓴다

주제 13개 · Case 28 · Concept 5 · Reference 15 · Question 4 · Decision 4.
계약의 노드마다 종류가 요구하는 칸을 채우고, 본문이 있는 두 종류에는 SSOT 가 이미
그려 둔 도식 셋(value-boundaries · decision-path-404 · topic-variant-model)을
tech-log-studio/ 로 옮겨 붙였다. 새로 그린 그림은 없다.

검사 셋 전부 통과한다.
  check_body.mjs      56 편 중 본문이 있는 33 편 PASS
  check_prose.mjs     56 편 error 0
  check_evidence.mjs  --repo 포함 문제 없음
  verify-tech-log-tree.py  프로젝트 5 · error 0 · warn 0

인용한 코드블록은 전부 SSOT 에서 찾아 대조했다. check_evidence.mjs 가 본문의 각 줄과
source 앵커와 계약 제목을 다시 확인한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-07 15:29:33 +09:00
co-authored by Claude Opus 5
parent 6955611439
commit f6c825e858
62 changed files with 6381 additions and 186 deletions
@@ -0,0 +1,85 @@
---
kind: CASE
slug: a-link-that-pointed-at-itself
title: 축 링크가 자기 자신을 가리켰고, 고친 뒤에는 백엔드를 먼저 배포했다
topic: addresses-frozen-at-publish-time
topicName: 주소가 만들어지고 굳어지는 곳
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§9.1
- final/document.md#§9.3
---
# 축 링크가 자기 자신을 가리켰고, 고친 뒤에는 백엔드를 먼저 배포했다
주제 화면의 네 줄은 링크인데 눌러도 아무 일이 없었다. 축의 주소를 주제 화면 안의 앵커로 바꿨더니, 정작 주제 화면에서는 그 링크가 자기 자신을 가리켰다. 결국 축에 자기 화면을 줬고, 그 화면을 만들고 백엔드를 프론트보다 먼저 배포해 사용자가 네 링크 전부 404 인 화면을 봤다.
## 관계
- **새 라우트는 프론트엔드를 먼저 배포한다**
이 사건에서 정한 순서다.
- **우회를 남길 때는 되돌릴 조건을 함께 적는다**
같은 주제 링크를 다루며 굳힌 기준이다.
- **축은 주제가 이름을 정하고, 기록은 종류와 아이디의 쌍으로 축에 걸린다**
축에 자기 화면을 주려면 알아야 하는 구조다.
## 문제
주제 화면의 네 줄(SPA·Mediator·BFF·Forward-Auth)은 링크로 그려져 있었다. 눌러도 아무 일이 없었다.
처음에 `/topics/{주제}/{축}` 이라 적어 두었는데 그런 화면이 없었다.
## 결론
주소를 두 번 옮긴 끝에 축에 자기 화면을 줬다.
1차 : 축의 주소를 주제 화면 안의 앵커로 바꿨다 — 주제 화면에서는 그 링크가 자기 자신을 가리켰다
2차 : 축에 자기 화면을 줬다 — 목록 조회에 축 필터를 더해 걸러 낸다
축 slug 는 주제 안에서만 유일하므로 조회에서 주제까지 함께 맞춘다. 주제를 빼면 다른 주제의 같은 이름 축이 함께 걸린다.
같은 시기에 주제가 없는 기록이 이름 없는 주제 링크를 달고 있던 것도 고쳤다. 문서 머리말의 breadcrumb 과 탐색의 「주제 없음」 묶음 둘 다였고, 프로젝트 조각은 처음부터 조건부였는데 주제 쪽만 아니었다.
## 검증 환경
tech-log-frontend : 8828005 · 67a5491
tech-log-backend : 63eb177 · 6d3b68b
tech-log-design-package : 71bab4c · b93d62a
확인 방식 : 배포본에서 주제 화면의 네 링크를 눌러 각각 어디로 가는지 확인
## 재현 조건
1. 주제에 축을 넷 만들고 기록을 각 축에 건다
2. 주제 화면에서 축 줄을 누른다
3. 주소가 바뀌는지, 화면이 바뀌는지를 따로 본다
## 본문
<!-- body:start -->
## 주소만 바뀌고 화면은 그대로였다
처음에 축의 주소를 `/topics/{주제}/{축}` 이라 적어 두었는데 그런 화면이 없었다. 그래서 축의 주소를 주제 화면 안의 앵커로 바꿨다.
주제 화면에서 그 링크를 누르면 주소에 앵커가 붙는다. 화면은 이미 그 주제 화면이므로 아무것도 바뀌지 않는다.
## 축에 자기 화면을 줬다
목록 조회에 축 필터를 더하고 `record_variant` 로 거른다. 축 slug 는 주제 안에서만 유일하므로 주제까지 함께 맞춘다 — 주제를 빼면 다른 주제의 같은 이름 축이 함께 걸린다.
## 배포 순서로 만든 2차 사고
> **이 건에서 제가 만든 2차 사고:** 축 화면을 만들고 **백엔드를 프론트보다 먼저 배포했습니다.** nginx 설정은 라우트 계약에서 생성되므로, 프론트가 배포되기 전까지 `/topics/x/y` 는 404 입니다. 서버는 이미 그 주소를 내보내고 있었고, 사용자는 네 링크가 전부 404 인 화면을 봤습니다. **순서가 있습니다 — 새 라우트는 프론트가 먼저입니다.**
## 주제가 없는 기록
같은 시기에 주제 없이 게시된 기록이 이름 없는 주제 링크를 달고 있었다. 문서 머리말의 breadcrumb 과 탐색의 「주제 없음」 묶음 둘 다였다. 프로젝트 조각은 처음부터 조건부였는데 주제 쪽만 아니었다.
## 확인하지 못한 것
축 slug 가 주제 안에서만 유일하다는 전제를 조회에 반영했다. 주제를 빼고 조회하는 경로가 남아 있는지는 세지 않았다.
<!-- body:end -->
@@ -0,0 +1,89 @@
---
kind: CASE
slug: a-slug-rule-that-threw-korean-away
title: slug 생성이 한글을 버려 주제 만들기가 간헐적으로 실패했다
topic: addresses-frozen-at-publish-time
topicName: 주소가 만들어지고 굳어지는 곳
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§13.6
---
# slug 생성이 한글을 버려 주제 만들기가 간헐적으로 실패했다
주제 만들기가 간헐적으로 실패했다 — 「그 slug 를 가진 주제가 이미 있습니다」. 다른 이름으로 다시 하면 됐다. 규칙은 간헐적이었던 적이 없었고 보이지 않았을 뿐이다. slug 생성이 영문 소문자와 숫자만 남기고 나머지를 버려서, 한글 이름은 아무것도 기여하지 못했다.
## 관계
- **계약은 앵커라고 적었고 만드는 쪽은 경로를 만들었다**
주소를 만드는 다른 곳에서 난 사건이다.
- **한 화면에 종류 이름이 아홉 개 떠 있었다 — 표가 여섯 벌이었다**
이름을 다루는 다른 사건이다.
- **서버가 준 주소는 라우트 표에 맞춰 보고, 맞는 라우트가 없으면 링크로 그리지 않는다**
slug 가 주소의 재료라는 점에서 이어진다.
## 문제
주제를 만들면 가끔 「그 slug 를 가진 주제가 이미 있습니다」가 나왔다. 다른 이름으로 다시 하면 됐다.
같은 이름으로 두 번 만든 적은 없었다.
## 결론
간헐적으로 보인 것은 두 가지 결정적 어긋남이었고, 사용자는 둘 다 만났다.
`인증` : 남는 글자가 없어 빈 문자열 → 폼이 요청 전에 거절
`Redis 캐시``Redis 클러스터` : 둘 다 `redis` → 두 번째가 충돌
> 규칙은 간헐적이었던 적이 없다. **보이지 않았을 뿐이다** — slug 생성이 `[a-z0-9]` 만 남기고 나머지를 버려서, 한글 이름은 아무것도 기여하지 못했다.
한글을 버리지 않고 로마자로 옮긴다. 음절을 초성·중성·종성으로 산술 분해하므로 표가 필요 없고 결정적이다.
`백엔드 아키텍처``baekendeu-akitekcheo`
국어의 로마자 표기법의 자모 대응만 적용하고 음운 변화 규칙은 일부러 뺐다. slug 는 읽는 것이지 발음하는 것이 아니고, 그 규칙을 넣으면 같은 이름이 문맥에 따라 다른 slug 가 된다.
## 검증 환경
tech-log-frontend : 5cffe30 · 7093d84
변환 : 국어의 로마자 표기법의 자모 대응 · 음운 변화 규칙 제외
확인 방식 : 한글 이름 여럿으로 주제를 만들어 생성된 slug 를 확인
## 재현 조건
1. 주제 이름을 `인증` 으로 적고 저장한다 — 옛 규칙에서는 빈 slug 가 되어 폼이 거절한다
2. `Redis 캐시``Redis 클러스터` 를 차례로 만든다 — 옛 규칙에서는 두 번째가 충돌한다
3. 새 규칙에서 같은 이름들의 slug 를 확인한다
## 본문
<!-- body:start -->
## 간헐적으로 보인 이유
slug 생성이 `[a-z0-9]` 만 남기고 나머지를 버렸다. 한글 이름은 통째로 사라지므로 이름에 영문이 얼마나 섞였는지에 따라 결과가 갈린다.
영문이 하나도 없으면 빈 문자열이 되어 폼이 요청 전에 거절한다. 영문이 앞에 붙어 있으면 그 부분만 남으므로 뒤가 다른 두 이름이 같은 slug 가 된다.
`Redis 캐시``Redis 클러스터` 가 둘 다 `redis` 였다. 두 번째를 만들 때 충돌이 났고, 사용자에게는 「가끔 안 된다」로 보였다.
## 산술 분해로 로마자를 만든다
한글 음절은 초성·중성·종성이 정해진 순서로 조합된 코드다. 음절 코드에서 세 값을 산술로 분해할 수 있으므로 변환표가 필요 없고 결과가 결정적이다.
`백엔드 아키텍처``baekendeu-akitekcheo`
## 음운 변화 규칙을 뺀 이유
국어의 로마자 표기법에는 자모 대응 외에 음운 변화 규칙이 있다. 그것을 넣지 않았다.
slug 는 읽는 것이지 발음하는 것이 아니다. 음운 변화를 적용하면 같은 이름이 앞뒤 글자에 따라 다른 slug 가 되고, 그러면 같은 이름을 두 번 만들 때 결과가 갈린다.
## 확인하지 못한 것
음운 변화 규칙을 빼서 같은 발음의 다른 이름이 다른 slug 가 된다. 그 충돌이 실제로 얼마나 자주 나는지는 재지 않았다.
<!-- body:end -->
@@ -0,0 +1,110 @@
---
kind: CASE
slug: an-address-frozen-at-publish-time
title: 계약은 앵커라고 적었고 만드는 쪽은 경로를 만들었다 — 이미 저장된 행까지 고쳤다
topic: addresses-frozen-at-publish-time
topicName: 주소가 만들어지고 굳어지는 곳
project: TechLog
status: 게시 전
lastVerifiedOn: 2026-09-04
assets:
- key: decision-path-404
file: ../../../final/assets/tech-log-studio/decision-path-404.svg
evidence:
- ../../../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
sourceRevision: tech-log@2026-09-02
source:
- 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 다
## 본문
<!-- body:start -->
## 주소가 만들어져 저장되고 방문에서 끝난다
:::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"
:::
## 확인하지 못한 것
이 감사는 서버가 내보내는 주소만 본다. 본문 안에 작성자가 손으로 쓴 링크는 대상이 아니다.
<!-- body:end -->
@@ -0,0 +1,47 @@
---
kind: PROJECT_DECISION
slug: a-new-route-ships-frontend-first
title: 새 라우트는 프론트엔드를 먼저 배포한다
topic: addresses-frozen-at-publish-time
topicName: 주소가 만들어지고 굳어지는 곳
project: TechLog
status: 게시 전
decisionStatus: ADOPTED
decidedOn: 2026-09-01
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§9.1
---
# 새 라우트는 프론트엔드를 먼저 배포한다
새 라우트를 여는 변경은 프론트엔드를 먼저 배포한다. nginx 설정이 라우트 계약에서 생성되므로, 프론트가 배포되기 전까지 그 경로는 엣지에서 404 다. 백엔드를 먼저 배포하면 서버는 이미 그 주소를 내보내고 사용자는 전부 404 인 화면을 본다.
## 근거
- **축 링크가 자기 자신을 가리켰고, 고친 뒤에는 백엔드를 먼저 배포했다**
이 순서를 정하게 된 사건이다. 반대 순서로 배포해 사용자가 네 링크 전부 404 인 화면을 봤다.
- **nginx 가 모르는 라우트는 새로고침에서 404 다**
엣지가 왜 그 경로를 모르는지가 그 기록에 있다.
- **catch-all 라우트는 nginx 패턴으로 번역하지 않는다**
이 순서가 필요해진 이유가 그 결정에 있다.
## 결정문
새 공개 라우트를 여는 변경은 프론트엔드를 먼저 배포하고, 그 주소를 내보내는 백엔드 변경을 다음 배포에 넣는다.
## 판단 이유
nginx 설정은 라우트 계약에서 생성된다. 프론트 이미지가 배포되기 전까지 그 경로는 서빙 패턴에 없고, 엣지에서 404 로 끝난다.
백엔드를 먼저 배포하면 서버는 이미 그 주소를 링크로 내보낸다. 방문자는 화면에 그려진 링크를 누르고 404 를 만난다. 축 화면을 만들 때 실제로 그렇게 배포했고 사용자가 네 링크 전부 404 인 화면을 봤다.
catch-all 을 서빙 패턴으로 번역하지 않기로 했으므로 이 구간이 soft 200 으로 덮이지 않는다. 그 결정과 이 순서는 함께 간다.
## 영향
새 주소를 내보내는 백엔드 변경이 한 배포 늦게 나간다. 두 저장소를 한 번에 배포하고 싶은 변경에서 그 사이가 벌어진다.
프론트를 먼저 배포한 뒤에는 그 경로가 열려 있지만 서버가 아직 그 주소를 내보내지 않는다. 이 구간에서는 화면에 링크가 그려지지 않으므로 방문자에게 보이는 문제가 없다.
배포 순서를 사람이 기억해야 한다. 이 순서를 강제하는 검사는 없다.
@@ -0,0 +1,62 @@
---
kind: REFERENCE
slug: do-not-draw-a-link-that-does-not-resolve
title: 서버가 준 주소는 라우트 표에 맞춰 보고, 맞는 라우트가 없으면 링크로 그리지 않는다
topic: addresses-frozen-at-publish-time
topicName: 주소가 만들어지고 굳어지는 곳
project: TechLog
status: 게시 전
verifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§9.2
---
# 서버가 준 주소는 라우트 표에 맞춰 보고, 맞는 라우트가 없으면 링크로 그리지 않는다
주소를 서버가 만들어 내보내고 화면이 그대로 링크로 그리면, 그 주소가 틀렸다는 것은 방문자만 안다. 화면 코드 어디에도 그 주소가 없기 때문이다. 만드는 쪽과 그리는 쪽 양쪽에서 라우트 표와 맞춘다.
## 관계
- **계약은 앵커라고 적었고 만드는 쪽은 경로를 만들었다**
이 기준의 근거 사건이다.
- **catch-all 라우트는 nginx 패턴으로 번역하지 않는다**
엣지의 404 가 감사에 남아야 이 기준이 성립한다.
- **라우트에 딸린 목록은 라우트 계약에서 유도하고, 유도할 수 없는 것은 대조 검사를 둔다**
라우트 표가 어디서 오는지가 그 기준에 있다.
## 목적
서버가 만든 주소가 열리지 않는 것을 방문자보다 먼저 잡는다. 이 부류는 화면 코드에 흔적이 없어 저장소 안의 링크 리터럴을 훑는 감사로는 잡히지 않는다.
## 규칙
**만드는 쪽에서 생성한 경로를 공개 라우트 패턴에 맞춘다**
종류마다 만들어 낸 주소가 실제 라우트에 걸리는지 백엔드 테스트가 본다.
**그리는 쪽에서 서버가 준 주소를 라우트 표에 맞추고, 맞는 라우트가 없으면 링크로 그리지 않는다**
같은 부류가 또 생겨도 방문자가 404 를 만나지는 않는다.
**주소를 고쳤으면 이미 저장된 행도 함께 고친다**
주소가 게시 시점에 굳어져 저장되면 코드만 고쳐도 기존 링크는 깨진 채 남는다.
**배포 뒤 서버가 내보내는 주소를 전수로 훑는다**
저장소를 훑는 감사와 다른 것을 본다. 실제로 나가는 주소는 DB 에 있다.
## 적용 조건
주소를 서버가 만들어 내보내고 화면이 그대로 링크로 그리는 구조. 게시 시점에 주소가 굳어져 저장되면 특히 걸린다.
## 예외
외부 주소는 라우트 표에 없으므로 이 대조의 대상이 아니다.
그리는 쪽에만 가드를 두면 링크가 아예 그려지지 않는 것으로 끝나고 원인이 남는다. 만드는 쪽에도 같은 검사를 둔다.
## 예시
결정 링크가 404 였다. 계약은 앵커라고 적었고 만드는 두 곳이 경로를 만들었다.
배포 후 서버가 내보내는 주소 26개와 주제·축 9개를 더해 35개 전부 200 인 것을 확인했다.
저장소 안의 링크 리터럴을 훑는 감사로는 이 결함이 잡히지 않았다. 그 주소는 코드에 없다.
@@ -0,0 +1,59 @@
---
kind: REFERENCE
slug: write-down-what-would-undo-a-workaround
title: 우회를 남길 때는 되돌릴 조건을 함께 적는다
topic: addresses-frozen-at-publish-time
topicName: 주소가 만들어지고 굳어지는 곳
project: TechLog
status: 게시 전
verifiedOn: 2026-09-04
sourceRevision: tech-log@2026-09-02
source:
- final/document.md#§9.4
---
# 우회를 남길 때는 되돌릴 조건을 함께 적는다
그 화면이 줄 수 있는 것이 아직 비어 있어 링크를 다른 곳으로 돌린 적이 있다. 우회 자체는 틀리지 않았다. 문제는 우회를 남겨 두면 「왜 이 링크가 저기로 가지?」라는 질문이 계속 남는다는 것이다. 우회할 때 되돌릴 조건을 함께 적는다.
## 관계
- **축 링크가 자기 자신을 가리켰고, 고친 뒤에는 백엔드를 먼저 배포했다**
같은 주제 링크를 다루며 이 기준이 나왔다.
- **홈의 비교 구역이 세 번 바뀌었다**
단계마다 무엇을 고치려 했는지 적어 둔 다른 예다.
- **새 라우트는 프론트엔드를 먼저 배포한다**
같은 사건에서 나온 짝이 되는 결정이다.
## 목적
임시 조치가 영구 구조로 굳는 것을 막는다. 되돌릴 조건이 적혀 있지 않으면 다음 사람이 그 우회를 설계로 읽는다.
## 규칙
**우회를 넣는 커밋에 되돌릴 조건을 적는다**
무엇이 채워지면 되돌리는지 한 줄로 적는다. 그 조건이 충족됐을 때 실제로 되돌린다.
**우회할 때 무엇이 비어 있어서 우회하는지 함께 적는다**
채울 것이 없어서 돌린 것과 구조상 그쪽이 맞아서 돌린 것은 다르다.
**되돌릴 생각이 없으면 우회가 아니라 결정으로 적는다**
그때는 조건이 아니라 근거와 감수한 비용을 적는다.
## 적용 조건
그 화면이 줄 수 있는 것이 아직 비어 있어 링크나 흐름을 다른 곳으로 돌릴 때.
## 예외
되돌릴 생각이 없는 영구 변경은 우회가 아니다. 조건 대신 근거를 적는다.
조건을 적을 수 없으면 그것은 우회가 아니라 아직 정하지 않은 것이다. 열린 질문으로 남긴다.
## 예시
주제 화면이 주제 셋을 하드코딩해 두고 있어 실제 주제는 무엇이든 404 였다. 그때 주제 페이지를 채우는 대신 링크를 탐색 필터로 돌렸다.
돌린 이유는 그 페이지만 줄 수 있는 것 — 설명, 범위, 선별한 대표 기록 — 이 전부 비어 있었고 Studio 에 주제 설명을 쓸 칸조차 없었기 때문이다.
그 조건을 커밋 메시지에 적었고, 주제 화면을 계약에 잇고 하드코딩을 없앤 뒤 링크를 곧장 주제 화면으로 되돌렸다.