최상위 10_Wiki/Topic_*였던 4개 카테고리 폴더를 10_Wiki/Topics/Topic_* 로 재배치.
콘텐츠 변경 없음(순수 폴더 이동) — Topics/ 하위 나머지 폴더는 이미 지난 커밋에서
전부 정리된 상태(잔존 항목은 에이전트 운영 상태 및 사용자가 보존을 요청한
업데이트0615/무제 3.canvas 뿐).
-- ❌ 직접 NOT NULL — 대형 테이블 long lock
ALTERTABLEordersALTERCOLUMNstatusSETNOTNULL;-- ✅ 단계별
-- 1) DEFAULT + NOT VALID CHECK
ALTERTABLEordersADDCONSTRAINTorders_status_chkCHECK(statusISNOTNULL)NOTVALID;-- 2) 기존 행 backfill
UPDATEordersSETstatus='pending'WHEREstatusISNULL;-- 3) constraint validate (read lock 만)
ALTERTABLEordersVALIDATECONSTRAINTorders_status_chk;-- 4) 진짜 NOT NULL (Postgres 12+ — fast path)
ALTERTABLEordersALTERCOLUMNstatusSETNOTNULL;ALTERTABLEordersDROPCONSTRAINTorders_status_chk;
Index 추가 — CONCURRENTLY (Postgres)
CREATEINDEXCONCURRENTLYidx_users_emailONusers(email);-- write block 안 함. 단 transaction 안에서는 못 씀.
큰 테이블 backfill — batch
-- 한 번에 1000행씩
DO$$DECLAREbatchINT:=1000;BEGINLOOPWITHidsAS(SELECTidFROMordersWHEREnew_fieldISNULLLIMITbatchFORUPDATESKIPLOCKED)UPDATEordersSETnew_field=compute(id)WHEREidIN(SELECTidFROMids);EXITWHENNOTFOUND;PERFORMpg_sleep(0.1);ENDLOOP;END$$;
🤔 의사결정 기준
변경
안전
Column 추가 (nullable)
✅ 즉시
Column 추가 + DEFAULT (Postgres 11+)
✅ — fast path
NOT NULL 추가
expand-contract
Column rename
expand-contract
Type change (varchar → text)
보통 안전 — but 큰 테이블이면 점검
Type change (int → bigint)
expand-contract
Drop column
expand-contract — 코드 먼저 안 쓰게
Index 추가
CONCURRENTLY
FK 추가
NOT VALID + VALIDATE
❌ 안티패턴
schema 변경과 코드 변경 한 deploy: 둘이 정확히 동시 시작 못 함. 한 쪽만 적용된 짧은 시간 = 사고.
online migration 없는 큰 테이블 ALTER: 수십 분 lock → 다운타임.
rollback 계획 없음: 새 코드 + 새 schema deploy 후 문제 → 옛 코드 + 새 schema 인스턴스 발생 → 사고. expand-contract 면 자연 롤백.
production 에 직접 SQL: history / review 없음. migration tool (Flyway / Prisma migrate / golang-migrate / dbmate) 사용.
migration 안에 비즈니스 로직: 한 트랜잭션에 무거운 변환. 별도 backfill batch.
trigger 가 영구 남음: contract 단계에서 trigger 제거 잊음.
dev 에서만 테스트: 데이터 양이 다름. staging with prod-size dataset 검증.
🤖 LLM 활용 힌트
"schema 변경 = expand-migrate-contract 3 deploy" 강제.