v0.18.0 Phase 4 실행계획 — 구조 정리에 데이터 쓰기 효율을 포함 (2026-09-10)
- 기간: 2026-09-10, 기존 리팩터링·데이터 모델 논의의 후속. 오너 지시: “phase 4 반영해서 문서 업데이트해주고, 이슈에 phase 4 작업들 생성”.
- 랜딩: 문서 저장소 main 대상 PR #49. 앱 구현·마이그레이션·Edge·Production 배포는 이번 문서 게시 범위에 없음. 문서의 main 반영과 사이트 배포는 구분한다.
- 설계서: 이 문서의 목표·범위·작업절차·예상 효과·완료조건. 기존 검토안을 사용자 요청으로 실행계획에 채택했다.
- 정본: 총괄 로드맵, HQ 운영, G05 장부.
- 도구: GitHub CLI로 중복·선행 이슈를 확인하고 게시. 일회성 로컬 스크립트로 63개 ID·의존성과 문서/이슈 연결을 대조(문서 저장소 밖 작업 디렉터리).
- 게이트: 문서 check·VitePress build·배포 자산 검사. 제품 코드 변경이 없어 앱·관리자·DB 검사를 실행하지 않음.
- 버그리포트: 없음. 운영 병목의 새 결함 판정이나 수리 구현이 아닌 승인된 실행계획이다.
- 계약: 저장 DTO·revision·receipt·generation·원본 보존 정책은 유지. 계획 배정과 향후 구현의 수용 기준만 보강.
Phase 현황
아래는 이번 문서·이슈 게시 작업의 상태다. 캠페인 Phase 4의 구현 7개는 모두 게시·미착수이며 별도다.
| Phase | 내용 | 상태 |
|---|---|---|
| Phase 1 | 승인안의 D14·선행·63개 합계·후속 검증을 문서에 반영 | 작성·목록/의존 대조 완료 |
| Phase 2 | Phase 4의 7개 실행 이슈 게시와 번호 연결 | #1531–#1537 게시·원격 본문 대조 완료 |
| Phase 3 | 문서 검사·PR·main 병합 확인 | 로컬 3종 통과; 원격 검사·main 병합 이력은 PR #49 |
1. 배경
Phase 1~3의 책임 분리·증분 계산 위에, 실제 저장과 통계 발행에서도 변하지 않은 행을 다시 쓰지 않도록 핵심 과제를 배정했다. 기존 정규 관계 모델을 유지하면서 Phase 4의 구조·CSS·화면 성능 정리에 원본 저장 비용을 포함한다.
신규 D14 1개 + 기존 D11·R01·R04·R05 보강을 채택했다. Phase 6은 만들지 않는다. 실행 작업은 62→63개, Phase 4는 6→7개다. D14 실행 이슈는 D14 #1533다. 기존 62개의 범위·완료조건·선행관계는 보존하고 필요한 의존성만 추가한다.
전제: 원본의 다섯 층 모델과 사용자 입력·통계 수치 정책을 유지한다. 세션 전체 저장 API의 의미를 유지하면서 불필요한 물리 쓰기를 줄인다. 이 계획은 구현 승인이나 Production 변경 승인을 대신하지 않는다.
| 작업 | 배치 | 처리 | 핵심 산출물 |
|---|---|---|---|
| D11 — 통계 계산 통합·동치 검증·generation publication 전환 | 기존 Phase 3-4 | 기존 #1422 범위의 구체화 | 행의 계산 출처와 공개 세대 분리, 변경된 공개 행만 원자 발행 |
| D14 — 세션 원본의 변경 행만 저장 | 신규 Phase 4-1 | 신규 실행 이슈 | 변경 집합 계산, 불변 자식 UPDATE 제거, 실제 재정렬만 처리 |
| R01 — 구현 이식 종료·퇴역 코드·테스트·문서 정리 | 기존 Phase 4 종료 | D14·D11 결과 인계 보강 | 활성 쓰기 경로·작성자·정당한 full rebuild의 소유권 마감 |
| R04 — 혼합 부하·장기 이력·UI/저장 성능 검증 | 기존 Phase 5 | 비용 측정 항목 보강 | 저장→계산→발행 전체 비용의 같은 조건 전후 결과 |
| R05 — 전체 릴리즈 리허설과 후보 확정 | 기존 Phase 5 | 변경된 저장·발행 경로를 기존 리허설에 포함 | populated upgrade·구/신 호환·복원·중단/재개 증거 |
R06의 실제 배포·운영 관찰은 기존 범위를 유지하며 R04의 지표와 R05의 후보를 인계받는다. 새로운 운영 자동화나 독립 검증 큐를 추가하지 않는다.
2. 문제 제기와 확인 근거
조회 시점 release/v0.18.0은 b0fa93ec97fab41c6bcbc59bd096f3e1926535fd였다. 실제 착수 시 최신 release를 다시 고정한다. Production 기준 main 6afe58ec와 release의 미출시 구현을 구분한다. 이번 계획에서는 새 DB 부하 실험이나 Production 데이터 프로브를 수행하지 않았다.
| 관측 | 근거 | 이번 계획의 판단 |
|---|---|---|
| 기존 자식도 반복 UPDATE하고 종목·세트 위치를 임시로 옮긴 뒤 복원 | write_session_children_v5 | D14의 직접 대상. 운영 병목이라는 실측은 아직 없음 |
| 완료 저장의 revision·영수증·통계 요청을 연결 | save_session_v5_engine | D14에서 논리 계약 보존 |
| 변경 세션 관측·합계 계산은 이미 이식 | D05 PR #1506 | 다시 구현하지 않음 |
| 기간·달력 writer와 변경 bucket 갱신은 이미 이식 | D06 PR #1518 | D06의 계산 DML 123→11을 전체 publisher 개선으로 해석하지 않음 |
| 순차 계산 checkpoint·suffix 재생도 release 병합 | D07 PR #1522 | 재사용. 과거 수정의 정당한 후속 재계산 범위 보존 |
| compute가 출력 전체 복사·세대 갱신·직렬화, publisher가 사용자 출력 전체 DELETE→INSERT | compute, publisher | D11의 실제 변경행 발행을 완료조건으로 명시 |
| D08이 delta publish·행 provenance/공개 세대 분리를 D11로 인계 | D08 기록, 인계 댓글 | 신규 D15로 중복 분리하지 않음 |
3. 해결 방안
결정 D1 (2026-09-10): 신규 D14 하나를 Phase 4-1에 추가하고 D11·R01·R04·R05의 기존 역할 안에서 쓰기 효율의 완료조건을 구체화한다. 기존 62개 ID와 직접 선행은 유지한다. D14의 직접 선행 4개와 R01의 D14 선행 의존 1개만 더해 총 191개 직접 의존이 된다.
D04·D05·D06·D07·D08 및 D11의 기존 직접 선행
→ D11 통합·차등 발행 완료 (Phase 3-4)
→ D14 원본 변경 행만 저장 (Phase 4-1)
→ R01 기존 전체 선행 + D14를 확인하고 이식 종료 (Phase 4)
→ R04 최종 혼합 부하·전체 비용 검증 (Phase 5)
→ R05 기존 R02·R03·U06 등 전체 선행과 함께 리허설 (Phase 5)
→ R06 기존 승인 범위의 배포·운영 관찰D14를 D11 뒤에 두는 이유는 Phase 3 통계 통합의 새 선행으로 넣어 현재 작업을 지연시키지 않고, 안정된 새 통계 경로 위에서 원본 저장 변경의 효과를 검증하기 위해서다. A15/A16/U07/U04/U05의 기존 선후 관계는 유지한다. D14와 다른 작업이 같은 SQL 함수·마이그레이션을 수정하면 소유자 단위로 직렬 통합한다.
채택하지 않는 대안
| 대안 | 이번 계획에서 제외하는 이유 |
|---|---|
| 운동 원본 다섯 층 통합·전면 JSON화 | 관계 모델이 병목이라는 증거가 없으며 ID·복합 동작·원본 정책 변화가 큼 |
| 메모-only 저장의 통계 enqueue 생략 | 현재 완료 저장 세대·receipt·dirty 계약과 표시 메타데이터 의존을 바꿈. D14의 물리 쓰기 감소와 분리해야 하며 이번 계획에 추가하지 않음 |
| 클라이언트 patch API/새 저장 계약 | 기존 full payload 계약으로 원본 쓰기 감소 가능. 새 구/신 호환 축을 늘리지 않음 |
| raw_payload·이력·백업 일괄 삭제/정리 | 보존 정책 변경이며 이번 쓰기 경로 최적화와 무관 |
| 인덱스 추가·삭제 캠페인, partition/sharding | D12 결과와 최종 부하 근거 없이 별도 구조 개편을 추가하지 않음 |
| 트리거 비활성화·타이머/재시도 증가·전체 full rebuild 폐기 | 보호·복구 의미를 훼손하거나 불필요 쓰기의 원인을 해결하지 못함 |
| 새 성능 도구·메트릭 플랫폼 구축 | 기존 G04/R04 도구와 필요한 작은 계측으로 검증 가능 |
4. 적용한 실행계획
Phase 4 게시 이슈
| 실행 스텝 | 실행 이슈 | 핵심 결과 |
|---|---|---|
[리팩터링 4-1] | A15 #1531 | 기능별 binding·얇은 app shell |
[리팩터링 4-1] | U07 #1532 | CSS cascade·scope·중복 정리 |
[리팩터링 4-1] | D14 #1533 | 변하지 않은 자식 행과 순서의 물리 쓰기 제거 |
[리팩터링 4-2] | A16 #1534 | 활성 any·dual shape·거대 mapper 정리 |
[리팩터링 4-2] | U04 #1535 | release 반영 · PR #1553 af5ae625 · Production 미배포 |
[리팩터링 4-3] | U05 #1536 | feature import graph·초기 bundle 비용 축소 |
[리팩터링 4-4] | R01 #1537 | D14/D11을 포함한 활성 경로·퇴역·호환 경계 마감 |
실행 스텝은 4-1 → 4-2 → 4-3 → 4-4다. 같은 스텝의 독립 작업만 병렬 진행하고 앞 스텝의 완료·검증·release 병합 후 다음 스텝을 시작한다. 각 카드의 기술적 직접 선행은 별도로 모두 확인한다. D14는 D11 뒤이므로 Phase 3 통합의 새 선행으로 들어가지 않는다. 각 이슈 본문에는 원 카드의 목표·산출물·수용 기준과 세부 절차를 담았다.
D14
신규 원본 저장 효율
실행 제목: [리팩터링 4-1] D14 — 세션 원본의 변경 행만 저장
배정: DATA / 캠페인 Phase 4 첫 실행 묶음 / 목적 release/v0.18.0 / 선행 D11과 기존 D02·D04·S10 계약. 실행 이슈: D14 #1533.
목표
세션 전체를 저장해도 실제 값이 달라지지 않은 종목·세부 종목·세트·세부 세트에는 물리 UPDATE를 하지 않는다. 사용자가 보는 저장 결과, 원본 ID, 출처, revision, 영수증, 복구 가능성은 기존과 같게 유지한다.
예: 세션 메모만 수정하면 자식 네 테이블의 쓰기는 0건이다. 단일 세트 무게만 수정하고 순서·부모 값이 그대로면 그 세부 세트와 정당한 파생 영향만 변경하며, 다른 자식 행은 쓰지 않는다.
범위와 소유 경계
- 주 대상:
supabase/definitions/workout/functions/write_session_children_v5.sql. - 연결 대상:
save_session_v5_engine.sql의 최소 배선, 자식 정규화·투영·원본 보호 트리거의 상호작용 검증. 트리거 전면 재설계는 하지 않는다. - 검증: 기존
session_write_contract_v5,session_hierarchy_layers_v1, 원본 보호·복구 pgTAP,workoutGenerationConcurrency,userFactRestoreConcurrency와 저장 비용 회귀 검사. - 생성물: forward migration, schema snapshot, registry 및 관련 계약 장부. 신규 데이터 컬럼이 불필요하면 만들지 않는다.
- 문서: Barbelic-docs의 저장 계약·원본 보존·업데이트 기록·총괄 D14와 G05 인계.
유지할 계약: 요청 DTO와 해시, 기존 자식 ID 추론/호환, 누락 필드와 null의 차이, 입력값 정규화, 원본 출처, 같은 mutation 재전송의 멱등성, 새로운 논리 저장의 revision·영수증, 완료 저장의 통계 요청 세대 규칙. 단지 값이 같다는 이유로 인증·소유권·기대 revision 검사를 건너뛰지 않는다.
작업절차 — 이슈 내부 Phase 1~5
- Phase 1 — 기준선·변경 판정 계약. 최신 release에서 메모 수정/동일 내용 새 저장/무게 한 칸/세트 추가·삭제/종목·세트 순서 교환/복합 동작/계획→완료를 고정 fixture로 실행한다. 테이블별 실제 INSERT·UPDATE·DELETE, 트리거 비용, WAL, 잠금을 계측한다. 입력을 DB에 실제 저장될 형태로 정규화한 뒤 비교할 컬럼을 명시한다. raw JSON 문자열이나 요청 hash를 행 변화의 대용으로 쓰지 않는다.
- Phase 2 — 변경 집합과 행 저장. 현재 세션 잠금·트랜잭션 안에서 ID/소속 검증 후 테이블별 삽입·실제 변경·삭제·유지 집합을 만든다. typed 값의
IS DISTINCT FROM등으로 null을 포함해 비교하고, 변경 집합만 쓴다. 단순 범용 diff 프레임워크를 만들지 않고 기존 저장 함수의 책임 안에서 해결한다. full payload를 읽고 검증하는 비용은 남는다고 명시한다. - Phase 3 — 순서·정규화·이력 연결. 기존 순서 충돌 회피는 실제 재정렬 집합에만 적용한다. 세트 추가·삭제에 따라 순서가 바뀌는 형제 행은 정당한 변경으로 센다. 무게 단위·recording_fields·bodyweight_factor·load_multiplier 변경에 필요한 자식 파생 갱신을 빠뜨리지 않는다. 정규화 트리거가 만들어야 하는 값이 있는데 UPDATE를 생략하지 않도록 실제 최종 행을 비교한다. 사용자 사실 변경의 이력·출처·복구는 보존한다.
- Phase 4 — 실패·경합·호환 검증. 같은 revision 수정/삭제 경합, 타 owner ID, 같은 mutation 응답 유실 후 재전송, 동일 내용의 별도 저장, 실제 자식 삭제, 복합 종목, 인입 출처 기록 편집, 복원 직후 편집, 중간 DML 실패를 실제 DB에서 검증한다. 실패하면 자식·revision·receipt·dirty 전체가 롤백돼야 한다. 값 비교 최적화가 권한·충돌 검사를 우회하지 않는지 검사한다.
- Phase 5 — 전후 결과·release 통합. 같은 fixture에서 비용을 다시 측정하고 정상 결과·ID·필수 이력·통계가 기존과 같은지 확인한다. forward migration을 populated DB에 적용해 원본 보존을 검증한다. 각 Phase의
npm run check, 최종 필수 precheck, 자기 PR의 Merge Check와 실제 release 병합까지 진행한다. 문서 결과와 코드 PR을 연결한다.
예상 효과·개선사항
| 개선 | 체감 대상 | 전→후 목표/확인 지표 | Phase |
|---|---|---|---|
| 무관한 자식 UPDATE 제거 | 기록을 자주 수정하는 사용자 | 세션 메모만 변경할 때 자식 쓰기: 현재 실측값→0 | 1~2 |
| 작은 변경의 쓰기 범위 축소 | 세트 수가 많은 기록 | 변경 영향 밖 자식 I/U/D: 현재 실측값→0 | 2~3 |
| 불필요 재정렬 제거 | 메모·무게만 바꾸는 사용자 | 순서 불변 저장의 위치 변경 쓰기: 현재 실측값→0 | 3 |
| 인덱스·트리거·WAL 부담 감소 | DB·저장 지연 | WAL bytes/저장, 트리거 호출, lock wait, save p95 전후 | 4~5 |
비율·지연 개선 목표치는 이번에 측정하지 않았으므로 정하지 않는다. 예상 효과는 물리 쓰기 감소이며 요청 payload 전체 검증이 O(변경행 수)가 된다는 약속은 하지 않는다.
완료조건
- [ ] 메모-only fixture의 자식 네 테이블 INSERT/UPDATE/DELETE가 모두 0이다. parent revision·영수증·기존 dirty 계약은 유지한다.
- [ ] 동일 내용의 새 논리 저장은 기존 계약의 revision·receipt·generation 결과를 유지하면서 자식 쓰기는 0이다. 같은 mutation 재전송은 기존 영수증을 재사용한다.
- [ ] 무게 한 칸·추가·삭제·재정렬 fixture마다 정당한 변경 행 목록을 독립적으로 정하고, 그 밖 행의 물리 쓰기는 0이다.
- [ ] 기존 ID/source·사용자 사실·타 owner 데이터·필수 변경 이력이 보존되고, 누락 필드/명시 null/숫자 정밀도/JSON 부가정보 의미가 바뀌지 않는다.
- [ ] 기존 guard와 실제 중간 실패·동시 수정·복원 계약을 통과한다.
- [ ] 데이터 migration으로 과거 사용자 원본을 일괄 UPDATE/DELETE하지 않는다.
리스크: 비교 대상 누락으로 필요한 저장을 생략하거나, 정규화/파생 트리거의 부수 효과를 누락할 수 있다. 그래서 값을 해시로만 비교하거나 트리거를 끄는 방식을 채택하지 않는다.
D11
기존 범위의 완료조건 보강
현재 제목 유지: [리팩터링 3-4] D11 — 통계 계산 통합·동치 검증·generation publication 전환
배정: 기존 Phase 3-4. 이미 D08에서 인계한 delta publish·계산 출처/공개 세대 분리의 완료조건을 문서에 명시한다. 기존 담당자의 이슈 본문·작업 Phase·PR은 이번에 수정하지 않는다. 다른 담당자의 PR·브랜치·진행 상태는 변경하지 않는다. 아래 절차는 작업 내용이며 이미 시작한 이슈의 Phase 번호를 임의로 다시 매기지 않는다.
목표
D05~D07의 증분 계산 결과가 실제 공개 테이블의 쓰기 감소로 이어지게 한다. 영향을 받지 않은 출력 행은 보존하면서, 사용자에게는 모든 필수 통계가 일관된 세대로 공개되게 한다.
범위
- 기존
compute_stats_projection_job_v1/publish_stats_projection_job_v1, 출력별 논리키·출처·세대·FK·조회 계약. - 현재 수치 계산기·checkpoint·worker lease·dirty scope 재사용. 같은 projector를 새로 만들지 않는다.
- D08이 인계한 변경행 발행과 행 계산 출처/전체 공개 generation 분리를 명시적으로 구현 범위에 포함한다.
applied_version등 기존 필드를 읽는 RPC·클라이언트·테스트를 대조하고 공개 DTO 호환을 유지한다. 기존 사용자 수준 발행 메타데이터를 우선 사용하며 필요한 근거 없이 새 범용 세대 시스템을 만들지 않는다.
작업절차
- 비용·의미 기준선: 기존 G04/D05/D06/D07 fixture를 이용해 계산 DML, temp 복사, JSON 직렬화, public DML, FK 검사, WAL, publish lock 시간을 나눠 측정한다. 출력 표별 논리키·수치 필드·출처 시각·세대 필드를 명시한다.
- 세대 의미 정리: 행이 실제 계산된 출처와 사용자 전체 통계가 검증·발행된 세대를 구분한다. 값이 그대로인 행의 과거 provenance가 잘못된 stale로 분류되지 않게 조회·무결성 검사·snapshot 규칙을 함께 맞춘다. 실제 source_updated_at 등 의미 있는 출처 변경을 비용 절감을 위해 무시하지 않는다.
- 차등 발행: 완성된 후보와 공개 상태를 논리키로 비교해 추가 키 INSERT, 실제 변경 키 UPDATE, 사라진 키 DELETE만 수행한다. 삭제 키는 전체 후보 또는 검증된 영향 범위에서 완전하게 계산한다. 가능한 범위에서 최종 발행 payload도 변경분과 삭제키 중심으로 구성한다. 계산에 필요한 전체 작업 사본까지 모두 없어졌다고 보고하지 않는다.
- 원자 발행: 모든 public 출력과 사용자 applied generation 변경을 하나의 트랜잭션으로 커밋한다. 새 dirty·옛 lease·동시 원본 삭제·순위 교환·FK 검사 실패가 있으면 기존 publication precondition과 재시도 규칙을 따른다. 부분별 커밋으로 최신 세대를 먼저 표시하지 않는다.
- 동치·비용 검증과 통합: 동일 canonical 입력에서 기존 full oracle와 수치·PR 근거·외부 DTO를 비교한다. 세대 메타데이터는 새로 명시한 의미대로 따로 검사한다. 실패/재시도/재시작/full rebuild/새 dirty/구형 scope를 실제 DB로 검증하고 precheck·자기 PR Merge Check·release 병합 증거를 남긴다.
예상 효과·개선사항
| 개선 | 체감 대상 | 전→후 목표/확인 지표 | 절차 |
|---|---|---|---|
| 전체 출력 DELETE→INSERT 제거 | 긴 이력 사용자·DB | 영향 없는 public 행 물리 쓰기: 현재 실측값→0 | 2~4 |
| 세대 번호 때문에 생기는 전체 UPDATE 제거 | 통계 갱신 전체 | 세대 전진만으로 동일 행 재작성: 발생→0 | 2~3 |
| 발행 비용 감소 | 저장 중 통계 갱신·worker | public DML/WAL/JSON bytes/lock wait/publish p95 전후 | 1~5 |
| 일관된 공개 상태 유지 | 모든 통계 화면 | 부분 실패 뒤 최신 세대 노출 0, 기존 계약의 동치 유지 | 4~5 |
완료조건
- [ ] 영향을 받지 않은 public 행은 새 세대가 발행돼도 물리 UPDATE/DELETE/INSERT가 0이다.
- [ ] 변경행 비교에서 provenance와 공개 세대의 의미를 구분하며 필요한 출처 변경은 보존한다.
- [ ] 숫자·정책·PR 근거·외부 DTO의 허용되지 않은 차이가 0이다.
- [ ] 중간 실패는 모든 공개 표와 applied generation을 이전 상태로 롤백한다.
- [ ] 새 dirty와 실패 범위가 보존되고 최신 generation을 앞질러 표시하지 않는다.
- [ ] 적법한 full rebuild가 유지되고 같은 writer 책임 안에서 동작한다.
- [ ] D08의 기존 발행 예산을 유지한다. 6초→3초 복귀를 이번 계획의 선결 목표로 삼지 않는다.
단순 UPSERT/IS DISTINCT FROM만 추가하는 방식은 기각한다. 모든 행의 generation 필드가 바뀌면 결국 전체 UPDATE가 남기 때문이다. 비교에서 세대 필드를 무작정 제외하는 방식도 조회·무결성 계약을 깨므로 기각한다.
R01
기존 범위의 완료조건 보강
목표: 새 원본 저장·공개 발행 구현이 실제 활성 경로가 되고 대체 경로가 함께 남지 않게 마감한다.
범위: 기존 R01의 controller/repository/mapper/projector 퇴역·호환 장부에 D14와 D11의 함수·호출자·작성자·테스트를 추가한다. 새로운 전수 감사 프로젝트는 만들지 않는다. R01의 기존 선행에 D14를 추가한다.
작업절차:
- 기존 G05·writer 장부에 실제 API→저장 함수→자식 writer 및 worker→publisher 호출 경로를 연결한다.
- 완료·계획·그룹 보드·가져오기·복구가 각자 의도된 엔진으로 진입하는지 기존 계약 시험에 대조한다. 원래 독립된 가져오기/복구 경로를 편의를 위해 강제로 합치지 않는다.
- 새 구현에 의해 대체돼 소비자가 없는 wrapper·함수·테스트만 제거한다. 사용 중인 구형 decoder·공개 RPC·정당한 full rebuild는 남기고 이유를 기록한다.
- 코드·테스트·정본 문서의 실제 적용 버전과 제거 조건을 맞추고 기존 R01 통합 검사를 완료한다. Phase 5의 여섯 최종 검증·출시 작업은 예정/미검증으로 남기며 아직 실행하지 않은 증거를 R01에서 완료 처리하지 않는다.
예상효과: 정상 경로가 오래된 전체 재작성으로 되돌아갈 여지를 줄이고 두 구현의 유지비를 없앤다. 확인 지표는 대체된 활성 호출 0, 미소유 writer 0, 보존한 호환 경로의 용도 명시다.
완료조건: D14·D11이 실제 활성 호출로 연결됨, 대체 구현 호출 0, 필요한 호환·full rebuild 유지, 기존 기능의 행동 검증 유지. 이미 병합된 D05~D07을 다시 리팩터링한 것으로 집계하지 않는다.
R04
기존 범위의 완료조건 보강
목표: 특정 함수의 숫자만 좋아진 것이 아니라 최종 릴리스에서 저장→계산→발행 전체 비용이 줄었는지 증명한다.
범위: 기존 1/4/10년·혼합 부하·여러 owner·같은 owner workload와 scripts/performance/ 도구 재사용. D12의 생략된 과거 추가 운영 측정을 다시 실행하는 작업으로 확대하지 않는다. 이번 최종 릴리스의 기존 R04/R05 검증 범위에서 측정한다.
작업절차:
- 비교 기준 SHA·DB 버전·같은 자원·fixture·warm/cold 상태·샘플 수를 고정한다. D11/D14 각각의 직전 기준과 최종 통합 후보를 구분해 기여도를 기록한다.
- 아래 사례를 실행하고 원본 쓰기/중간 계산/최종 public 쓰기를 분리 계측한다.
- 저장 RPC p95, 통계 반영 지연, queue age, lock wait, I/U/D 행 수, WAL, 직렬화 크기·시간, 읽기 버퍼를 수집한다. 계측 장치의 추가 비용을 분리하고 여러 반복의 분포를 보고한다.
- 통계 계산 중 사용자 저장, 여러 owner, 가져오기 병행, 과부하 후 큐 소진을 기존 혼합 부하에 연결한다.
- 기존 예산으로 합격 여부를 판단한다. 실패하면 D14·D11 또는 실제 원인 소유 작업으로 돌리고 예산을 올려 합격 처리하지 않는다. R05에 최종 후보와 결과를 인계한다.
| 사례 | 확인할 핵심 |
|---|---|
| 세션 메모만 수정 | 자식 쓰기 0, 기존 revision/receipt/generation 보존 |
| 같은 mutation 재전송 / 같은 내용 새 mutation | 멱등 재사용과 새로운 논리 저장을 구분 |
| 오늘 세트 한 개 무게·횟수 수정 | 영향 밖 원본·public 행 재작성 0 |
| 세트 추가·삭제·재정렬 | 필요한 형제 순서 변경·파생 삭제·키 충돌 처리 |
| 과거 기록 수정·날짜 이동·최댓값 삭제 | 정당한 suffix 재생과 old/new 기간·PR 전파 보존 |
| 복합 종목·기록 유형·체중 계수 변경 | 공유 세트 수·단위·파생 영향 정확성 |
| 계획→완료·그룹 보드 출처·인입 기록 편집 | 상태·출처·ID·정책 유지 |
| 저장/발행 중 취소·원본 삭제·새 dirty | 롤백·재시도·후속 세대 수렴 |
예상효과: 원본 쓰기 감소가 발행·인덱스·WAL 증가로 상쇄되지 않는지 확인한다. D06의 123→11 같은 부분 지표를 전체 개선율로 오인하지 않게 한다.
완료조건: 원본 보존·full 동치·기존 성능/freshness 예산 충족, D14/D11의 무관한 행 쓰기 0 증거, 과부하 뒤 backlog 감소, 개선과 악화 수치를 모두 공개. 임의의 “90% 빨라짐” 목표나 작은 fixture만으로 대규모 사용자를 지원한다는 주장은 하지 않는다.
R05
기존 범위의 완료조건 보강
목표: 저장·세대·publisher 변경을 실제 이전 버전 데이터와 구/신 클라이언트 조합에서 안전하게 적용할 수 있음을 증명한다.
범위: 기존 릴리스 전체 리허설에 D14/D11 변경을 포함한다. R02 저장 장애, R03 사본 복구, U06 UX 검증을 중복 이슈로 만들지 않고 각 증거를 같은 후보 SHA에 연결한다.
작업절차:
- R04와 기존 필수 선행을 통과한 동일 release 후보 및 실제 이전 버전의 populated 격리 DB를 고정한다.
- 이번 릴리스 전체 forward migration을 실행하고 원본 값·ID·source·자식 관계·과거 receipt/이력 보존을 비교한다.
- 실제 함수/스키마 변경 위치에 맞춰 중단·rollback/replay, pending·processing·computed·failed job과 구형 scope/checkpoint의 전이를 검증한다. 의도한 지원 조합과 지원하지 않는 조합을 구분한다.
- 구형 앱의 미전송 요청, 응답 유실 후 재전송, 새/옛 revision, 복구 후 재저장, full rebuild를 기존 R02/R03 시나리오와 연결한다.
- 허용되는 앱 rollback·DB forward-fix와 중단 조건을 기록하고 실제 staging 배포·필수 검증 증거를 묶어 R06으로 인계한다. Production DB를 직접 변경하지 않는다.
예상효과: 같은 결과를 내는 새 쓰기 경로로 이행하면서 원본 유실·중복 반영·부분 통계 공개를 방지한다. 운영 속도 향상과 별도로 전환 안전성을 증명한다.
완료조건: 필수 호환·복원·이관 시험 미실행 0, 원본·ID·출처의 비의도 변경 0, 부분 최신 세대 노출 0, 실패 job/dirty 유실 0, 정확한 후보와 되돌리기 범위 확인. 운영 배포는 기존 R06 절차와 승인 범위를 따른다.
공통 실행·마감 기준
구현 착수 전 최신 release와 해당 담당자의 기존 계획·go 범위를 대조한다. 이번에는 문서·이슈를 게시하며 7개 구현은 착수하지 않았다.
신규 D14는 이슈 내부 Phase 1~5로 보고한다. 기존 이슈는 자기 Phase 번호와 전체 선행을 보존하면서 위 보강 내용을 반영한다.
각 구현 Phase의
npm run check, 서버 변경의 격리 DB 검사·필요한 실제 browser 회귀, forward migration·원본 보존 증거를 남긴다.최종 clean·committed tree에서
npm run ci:precheck-local -- --release origin/release/v0.18.0, 자기 PR의npm run merge:request -- --pr <N>, Merge Check와 실제 release 병합까지 확인한다. precheck/Merge Check를 전체 full CI 통과로 보고하지 않는다.전체 검증과 두 승격·배포는 실행 시점 정본의 범위를 따르며 다른 담당자 큐·PR을 조작하지 않는다.
코드/문서 PR을 연결하고 Barbelic-docs의 총괄·G05·작성자·업데이트 기록을 해당 소유자가 갱신한다. 문서 추가만으로 구현·배포 완료를 집계하지 않는다.
2026-09-10 #1478의 와드업·관리자 관련 CASE·단위·컴포넌트·DB 검사는 자동 실행 대상에서 계속 제외한다. 관련 원래 제품 범위나 과거 증거는 삭제하지 않고, 제외를 통과로 보고하거나 이번 계획으로 자동 검사를 재활성화하지 않는다. 일반 사용자 fixture의 Auth Admin 호출은 제외 사유가 아니다. 관리자 타입·빌드는 필요 변경에서 유지한다. 현재 제외 범위.
제품 구현 PR은 앱
release/v0.18.0, 문서 PR은 문서 저장소 main을 사용한다. 앱 precheck → 자기 PR의 Merge Check → 실제 release 병합까지 수행하며 일반 Merge Check는 full CI를 실행하지 않는다. 최종 release→staging에서 full, staging→main에서 동일 tree의 유효한 full 기록과 배포·smoke를 확인한다. 현재 공통 규칙, 릴리스 절차.
5. 적용 결과
| 항목 | 전 → 후 / 이번 확인 범위 |
|---|---|
| 실행 작업 수 | 62 → 63 (신규 D14 하나) |
| Phase 4 | 6개 미게시 → 7개 게시·구현 미착수 |
| 전체 게시 | 50/62 → 57/63, Phase 5의 기존 6개는 미게시 |
| 기술적 직접 의존 | 186 → 191, 기존 의존 보존·순환/Phase 역전 없음 |
| 책임 배정 | 원본의 불변 자식 쓰기 D14, 통계 차등 발행 D11, 활성 경로 마감 R01, 전체 비용 R04, 실제 전환 R05 |
| 문서 검증 | check: 법률 4개 버전·332개 경로, VitePress build, artifact 31개 통과. 63개 카드/표·의존 및 원격 7개 이슈의 제목/OPEN/milestone/선행 대조 통과. 동시 main 변경(#50)의 인덱스 충돌은 양쪽 항목 보존으로 해결. 원격 검사·병합은 PR #49에 연결 |
| 운영 성능·데이터 변경 | 새 실측·앱 구현·DB 변경·배포 없음. 지연·WAL 절감률 미확인 |
6. 이번 개선으로 향상된 것
각 담당자가 원본 쓰기·계산·최종 발행 중 자신의 범위와 선행 결과를 확인하고 한 이슈씩 착수할 수 있다. D14의 무관한 자식 쓰기 0, D11의 무관한 공개 행 쓰기 0을 개별 완료조건으로 정하고 R04에서 전체 비용으로 확인하므로, 내부 계산만 빨라진 결과를 전체 저장 성능 향상으로 보고하지 않게 했다.
사용자 입력·기존 ID·복구·영수증·새 저장의 세대 규칙은 그대로 두고 물리 쓰기를 줄이는 계획이다. 실제 효과는 D14/D11 구현과 R04/R05의 같은 조건 전후 증거로 판단한다. 게시한 일곱 이슈를 구현·운영 반영 완료로 집계하지 않는다.