- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다 - 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5 (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를 techviz 로 만들었다 - 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs 돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다. Concept 이 인용한 코드가 SSOT 에 없어 뺐다 - candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
129 lines
5.9 KiB
Markdown
129 lines
5.9 KiB
Markdown
---
|
|
kind: CONCEPT
|
|
slug: independent-flyway-streams
|
|
title: 독립 Flyway 스트림과 baseline version 0
|
|
topic: schema-ownership-and-capability-streams
|
|
project: clean-architecture-backend-template
|
|
status: 게시 전
|
|
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
|
rootTreeNode: concept:independent-flyway-streams
|
|
evidenceCapturedOn: 2026-09-01
|
|
assets:
|
|
- key: independent-flyway-streams
|
|
file: ../../../final/evidence/rendered/independent-flyway-streams.svg
|
|
evidence:
|
|
- ../../../final/evidence/raw/independent-flyway-streams.txt
|
|
source:
|
|
- 원본 분석 절은 final/document.md#4-1 · final/document.md#a05 §8.3 이다.
|
|
---
|
|
|
|
# 독립 Flyway 스트림과 baseline version 0
|
|
|
|
능력마다 자기 마이그레이션 위치와 자기 히스토리 테이블을 갖는다. 그래야 각 능력의 버전 계열이 독립적이고, 켜지 않은 능력은 테이블도 히스토리도 남기지 않는다.
|
|
|
|
## 관계
|
|
|
|
- **두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다**
|
|
이 구조가 필요해진 사례다.
|
|
- **마이그레이션 스트림은 자기 history 테이블을 갖는다**
|
|
이 개념을 규칙으로 옮긴 것이다.
|
|
- **capability_schema_registry — 스키마 적용과 사용 승인의 분리**
|
|
스트림이 설치되었다는 사실을 기록하는 쪽이다.
|
|
|
|
## 본문
|
|
|
|
<!-- body:start -->
|
|
|
|
이 저장소에 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
|
|
|
|
마이그레이션 레인 미실행
|
|
|
|
:::
|
|
|
|
## 왜 위치만 더하면 안 되는가
|
|
|
|
```java
|
|
/**
|
|
* 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 의 반응이 두 가지인 것이 문제다. 거절하면 발견되지만, 해석 순서에 따라 하나를 기록하고 다른 하나를 건너뛰면 발견되지 않는다.
|
|
|
|
## 별도 스트림이 만드는 것
|
|
|
|
```java
|
|
/**
|
|
* <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.
|
|
*/
|
|
```
|
|
|
|
```java
|
|
public static final String LOCATION = "classpath:db/migration/jpa/notification-platform";
|
|
public static final String HISTORY_TABLE = "flyway_jpa_notification_history";
|
|
```
|
|
|
|
능력을 켜지 않은 배포에는 그 능력의 히스토리 테이블도 없다. 나중에 켜면 자기 V1 부터 적용한다.
|
|
|
|
## 선택 가능성이 스키마 수준에서 성립한다
|
|
|
|
능력이 선택적이라는 말이 코드 수준에서만 참이면, 스키마에는 쓰지 않는 테이블이 남는다. 스트림이 독립적이면 그 테이블도 생기지 않는다.
|
|
|
|
:::tip
|
|
|
|
이 구조에서 "이 능력을 쓰지 않는다"는 것과 "이 능력의 스키마가 없다"는 것이 같은 사실이 된다. 두 사실이 갈라지면 나중에 어느 쪽이 진실인지 알 수 없다.
|
|
|
|
:::
|
|
|
|
## 버전 공간을 공유하는 경우
|
|
|
|
같은 Flyway 위치 목록에 병합되는 트리들은 하나의 버전 공간을 공유한다. 샘플 컴포지션이 두 위치를 병합하므로, 한쪽이 이미 쓴 번호를 다른 쪽이 쓸 수 없다.
|
|
|
|
```sql
|
|
-- 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.
|
|
```
|
|
|
|
번호를 고를 때 다른 트리를 봐야 한다는 뜻이고, 그 사실이 마이그레이션 헤더에 적혀 있다.
|
|
|
|
## 두 위치가 같은 테이블을 만들 때
|
|
|
|
```sql
|
|
-- 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.
|
|
```
|
|
|
|
한쪽만 고치면 그 경로로만 마이그레이션한 배포가 옛 제약을 유지한다. 그리고 그때의 오류 메시지는 컬럼 이름을 부르지 이유를 말하지 않는다.
|
|
|
|
<!-- body:end -->
|