Files
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

6.0 KiB

kind, slug, title, topic, project, status, sourceRevision, basisVersion, rootTreeNode, evidenceCapturedOn, assets, evidence, source
kind slug title topic project status sourceRevision basisVersion rootTreeNode evidenceCapturedOn assets evidence source
CONCEPT independent-flyway-streams 독립 Flyway 스트림과 baseline version 0 schema-ownership-and-capability-streams clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 Flyway 11.14.1 · PostgreSQL 16 · 리비전 21234e38 concept:independent-flyway-streams 2026-09-01
key file
independent-flyway-streams ../../../final/evidence/rendered/independent-flyway-streams.svg
../../../final/evidence/raw/independent-flyway-streams.txt
원본 분석 절은 final/document.md#4-1 · final/document.md#a05 §8.3 이다.

독립 Flyway 스트림과 baseline version 0

능력마다 자기 마이그레이션 위치와 자기 히스토리 테이블을 갖는다. 그래야 각 능력의 버전 계열이 독립적이고, 켜지 않은 능력은 테이블도 히스토리도 남기지 않는다.

관계

  • 두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다 이 구조가 필요해진 사례다.
  • 마이그레이션 스트림은 자기 history 테이블을 갖는다 이 개념을 규칙으로 옮긴 것이다.
  • capability_schema_registry — 스키마 적용과 사용 승인의 분리 스트림이 설치되었다는 사실을 기록하는 쪽이다.

본문

이 저장소에 Flyway 스트림이 여덟 개이고 각각 자기 history 테이블을 갖는 이유의 설명이다. 뻔한 해법(디렉터리를 primary location 목록에 추가)이 틀린 이유는 두 트리가 다 V1부터 번호를 매기고 공유 history가 두 V1을 같은 버전으로 만들어 하나를 거부하거나 resolution 순서에 따라 건너뛰기 때문이다.

뻔한 해법이 틀린 이유

:::evidence key="independent-flyway-streams" alt="분석 문서 final/document.md 에서 이 기록의 근거 절을 그대로 잘라낸 18줄. 코드베이스를 측정한 것이 아니라 원본 판정이 무엇을 적었는지를 보여 준다." caption="final/document.md 발췌 — 18줄" zoom="true" :::

baselineOnMigrate 가 필요한 이유

core가 이미 채운 스키마 위에 자기 history를 만들어야 하므로, 없으면 Flyway가 "history 없는 비어있지 않은 스키마"라며 거부한다.

baseline이 0이어야 하는 이유

더 높은 baseline은 그 스트림의 마이그레이션을 건너뛴다 — 이 설정이 보통 두려워하는 실패 모드다.

:::note

마이그레이션 레인 미실행

:::

왜 위치만 더하면 안 되는가

/**
 * The notification schema as its own Flyway stream, with its own history table.
 *
 * <p>The migrations live in {@code db/migration/jpa/notification-platform} while the primary Flyway
 * location is {@code db/migration/postgresql}, so nothing applied them. The obvious fix — adding
 * the directory to the primary location list — is the wrong one: both trees number from V1, and a
 * shared history table would make {@code V1__notification_platform_core} and {@code
 * V1__initial_schema} the same version. Flyway would either refuse the second or, worse, record one
 * and skip the other depending on resolution order.
 */

두 트리가 각자 V1 부터 번호를 매긴다. 히스토리를 공유하면 두 개의 V1 이 같은 버전이 된다.

Flyway 의 반응이 두 가지인 것이 문제다. 거절하면 발견되지만, 해석 순서에 따라 하나를 기록하고 다른 하나를 건너뛰면 발견되지 않는다.

별도 스트림이 만드는 것

/**
 * <p>A separate stream with {@code flyway_jpa_notification_history} keeps the two version series
 * independent, which is what makes the capability genuinely optional: a deployment that never
 * enables notifications has no notification history table and no notification tables, and a
 * deployment that enables it later applies a stream that starts at its own V1.
 */
public static final String LOCATION = "classpath:db/migration/jpa/notification-platform";
public static final String HISTORY_TABLE = "flyway_jpa_notification_history";

능력을 켜지 않은 배포에는 그 능력의 히스토리 테이블도 없다. 나중에 켜면 자기 V1 부터 적용한다.

선택 가능성이 스키마 수준에서 성립한다

능력이 선택적이라는 말이 코드 수준에서만 참이면, 스키마에는 쓰지 않는 테이블이 남는다. 스트림이 독립적이면 그 테이블도 생기지 않는다.

:::tip

이 구조에서 "이 능력을 쓰지 않는다"는 것과 "이 능력의 스키마가 없다"는 것이 같은 사실이 된다. 두 사실이 갈라지면 나중에 어느 쪽이 진실인지 알 수 없다.

:::

버전 공간을 공유하는 경우

같은 Flyway 위치 목록에 병합되는 트리들은 하나의 버전 공간을 공유한다. 샘플 컴포지션이 두 위치를 병합하므로, 한쪽이 이미 쓴 번호를 다른 쪽이 쓸 수 없다.

-- Numbered V9, not V8 or V7. `db/migration/postgresql` and `db/sample-migration` are merged into
-- one Flyway location list by the sample composition root, so the two trees share a single version
-- space: the sample already owns V2, V7 and V8. A duplicate version is not a merge conflict Flyway
-- resolves — it refuses to start at all.

번호를 고를 때 다른 트리를 봐야 한다는 뜻이고, 그 사실이 마이그레이션 헤더에 적혀 있다.

두 위치가 같은 테이블을 만들 때

-- Both locations create capability_schema_registry, so both have to grow the column. A deployment
-- that migrated through only one of them would otherwise still reject a stream path over 32
-- characters, and the error would name the column rather than the reason.

한쪽만 고치면 그 경로로만 마이그레이션한 배포가 옛 제약을 유지한다. 그리고 그때의 오류 메시지는 컬럼 이름을 부르지 이유를 말하지 않는다.