# PostgreSQL 18에서 즉시 데이터베이스 복제 구현

> Clean Markdown view of GeekNews topic #25294. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=25294](https://news.hada.io/topic?id=25294)
- GeekNews Markdown: [https://news.hada.io/topic/25294.md](https://news.hada.io/topic/25294.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2025-12-24T09:46:28+09:00
- Updated: 2025-12-24T09:46:28+09:00
- Original source: [boringsql.com](https://boringsql.com/posts/instant-database-clones/)
- Points: 1
- Comments: 1

## Topic Body

- PostgreSQL 18은 **파일 복제 전략(FILE_COPY)** 과 **파일 시스템 클론 기능**을 결합해 데이터베이스를 거의 즉시 복제할 수 있음  
- 새로운 설정값 **`file_copy_method = clone`** 을 사용하면 XFS, ZFS, APFS 등 **현대적 파일시스템의 복제 기능(FICLONE)** 을 활용 가능  
- 벤치마크 결과, 6GB 데이터베이스 복제 시 기존 **WAL_LOG 방식은 약 67초**, 클론 방식은 **0.2초 수준**으로 단축됨  
- 복제된 데이터베이스는 **초기에는 동일한 물리 블록을 공유**하지만, 쓰기 작업 시 **copy-on-write**로 분리됨  
- 단, **활성 연결이 없는 상태에서만 복제 가능**하며, **단일 파일시스템 내에서만 작동**하는 제약 존재  

---
### PostgreSQL의 템플릿 기반 복제 구조
- PostgreSQL은 `CREATE DATABASE dbname` 명령 시 내부적으로 **`template1` 데이터베이스를 복제**해 새 데이터베이스를 생성  
  - 이는 `CREATE DATABASE dbname TEMPLATE template1` 과 동일한 동작  
- `template1` 대신 다른 데이터베이스를 지정할 수 있어, **사용자 정의 템플릿**을 활용한 복제 가능  
- PostgreSQL 18에서는 이 템플릿 시스템을 **즉시 복제 가능한 구조**로 확장  

### CREATE DATABASE ... STRATEGY
- PostgreSQL 15부터 `CREATE DATABASE ... STRATEGY` 매개변수가 도입되어 **복제 방식 선택** 가능  
  - 기본값은 `WAL_LOG`로, **Write-Ahead Log를 통한 블록 단위 복제** 수행  
  - 이 방식은 **I/O 부하를 줄이고 동시성 지원**을 개선하지만, 대용량 복제 시 속도가 느림  
- `STRATEGY=FILE_COPY`를 지정하면 **기존 파일 복사 방식**으로 되돌릴 수 있으며, PostgreSQL 18에서는 이를 기반으로 **새로운 복제 옵션** 추가  

### FILE_COPY와 file_copy_method
- PostgreSQL 18의 `file_copy_method` 설정은 **운영체제 수준의 파일 복제 방식**을 제어  
  - 기본값은 `copy`이며, 모든 바이트를 읽고 새 위치에 기록  
  - `clone`으로 변경하면 **파일시스템의 클론 기능(FICLONE)** 을 사용해 **즉시 복제 및 추가 공간 소모 없음**  
- 지원 파일시스템: **XFS, ZFS, APFS, FreeBSD ZFS**  
- 설정 절차  
  - 해당 파일시스템 위에 PostgreSQL 클러스터 구성  
  - `file_copy_method = clone` 설정 후 재로드  

### 벤치마크 결과
- 약 6GB 크기의 테스트 데이터베이스(`source_db`) 생성 후 두 가지 방식 비교  
  - `WAL_LOG` 방식: 67,000ms (약 67초)  
  - `FILE_COPY` + `clone` 방식: 212ms  
- 동일한 데이터 크기에서 **약 300배 이상 속도 향상** 확인  
- 복제된 데이터베이스(`fast_clone`)는 **추가 디스크 공간을 거의 사용하지 않음**  

### 복제된 데이터의 동작 원리
- `file_copy_method = clone` 사용 시, **파일시스템 메타데이터만 복제**되어 두 데이터베이스가 **동일한 물리 블록을 공유**  
- PostgreSQL이 보고하는 데이터베이스 크기는 논리적 크기(약 6GB)로 동일  
- 쓰기 작업 발생 시 **copy-on-write(COW)** 가 작동하여 해당 페이지가 분리됨  
  - 수정된 행이 포함된 페이지  
  - 새 튜플이 기록되는 페이지  
  - 인덱스 페이지 및 FSM, visibility map 페이지 등  
- VACUUM 실행 시에도 추가적인 페이지 분리 발생  

### XFS에서의 공유 블록 검증
- `filefrag -v` 명령으로 **두 데이터베이스의 물리 블록 공유 여부** 확인  
  - 초기 상태에서는 모든 extents가 `shared`로 표시  
  - 일부 행을 업데이트하면 첫 40블록(약 160KB)이 분리되어 **서로 다른 물리 주소**로 변경  
  - 나머지 extents는 여전히 공유 상태 유지  

### 주의사항 및 제약
- **복제 시 원본 데이터베이스에 활성 연결이 없어야 함**  
  - 이는 PostgreSQL의 제약이며, 파일시스템 문제는 아님  
  - 실서비스 환경에서는 **별도의 템플릿 데이터베이스**를 사용하는 것이 일반적  
- **단일 파일시스템 내에서만 복제 가능**  
  - 여러 테이블스페이스가 서로 다른 마운트 포인트에 있을 경우, 일반 복사로 대체됨  
- **클라우드 관리형 서비스(AWS RDS, Google Cloud SQL 등)** 에서는 파일시스템 접근이 불가하므로 이 기능 사용 불가  
  - 자체 VM이나 베어메탈 환경에서는 완전한 제어 가능  

### 결론
- PostgreSQL 18의 **`file_copy_method = clone`** 기능은 **운영체제 수준의 클론 기능을 직접 활용**해  
  **대용량 데이터베이스 복제 시간을 극적으로 단축**  
- 테스트, 개발, 학습 환경에서 **즉시 복제 및 리셋 가능한 데이터베이스 워크플로우** 구현 가능  
- 단, **활성 연결 제약과 파일시스템 단일성**을 고려한 운영 설계 필요

## Comments



### Comment 48201

- Author: neo
- Created: 2025-12-24T09:46:28+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46363360) 
- 기다릴 수 없거나 **PG18**의 완전한 인스턴스 격리가 필요한 사람들을 위해, 나는 **ZFS 스냅샷**을 이용해 즉시 브랜칭하는 도구 **Velo**를 만들었음  
  어떤 PostgreSQL 버전에서도 작동하며, 각 브랜치는 독립된 컨테이너와 포트를 가짐  
  100GB DB 기준 약 2~5초면 생성 가능함  
  PG18 방식과의 차이는, 단일 인스턴스를 공유하지 않고 완전한 서버 격리를 제공한다는 점임  
  [GitHub 링크](https://github.com/elitan/velo)
  - 다른 댓글에서 **Claude Code** 사용에 대한 불만이 있었지만, GitHub 페이지의 데모 영상을 보고 흥미롭게 느꼈음
  - 요즘 대부분의 소프트웨어가 **AI 에이전트**의 도움을 받아 작성되는데, 왜 불평이 나오는지 모르겠음. 접근 방식이 흥미로움
  - 나도 비슷한 걸 **btrfs**로 프로토타입 해보려던 참이었음
  - “너”라는 표현이 흥미롭다고 생각했는데, 표절했다는 말이 있어서 좀 놀랐음

- 예전에 회사가 **RDS**로 마이그레이션할 때 비슷한 시스템을 직접 구축했음  
  프로덕션 마이그레이션 중 자주 문제가 생겨서, 이를 방지하기 위해 다음 단계를 자동화했음  
  1) RDS DB를 복제하거나 백업에서 새 인스턴스를 생성  
  2) ARN으로부터 CNAME 또는 퍼블릭 IP 추출  
  3) 앱의 DB 연결 설정에 반영  
  4) 가짜 프로덕션 환경에서 마이그레이션 실행  
  이 과정 덕분에 로컬이나 CI에서는 잡히지 않던 **프로덕션 특유의 버그**를 많이 잡을 수 있었음  
  이후 간단한 **Ruby 스크립트**로 자동화했고, 아직도 그 스크립트를 사용 중이라고 들었음
  - 나도 그런 “데이터 특이성 때문에 프로덕션에서만 실패하는 마이그레이션” 버그를 정말 싫어함. 몇 번은 그 때문에 릴리스를 취소한 적도 있음

- **템플릿 클로닝** 전략이 설정 가능하다는 걸 이번에 처음 알았음  
  나는 **Neon**을 이용해 실시간 통합 환경을 만들었고, 내 **Golang 프로젝트 [pgtestdb](https://github.com/peterldowns/pgtestdb)** 에서는 각 테스트마다 완전한 스키마 마이그레이션이 적용된 Postgres DB를 생성함  
  예전에 스타트업에서 **btrfs**로 즉시 스테이징 DB를 만드는 걸 본 적 있는데, 비슷한 아이디어가 반복 등장하는 게 흥미로움  
  이런 **빠른 복제와 테스트**는 Postgres와 Sqlite의 큰 장점이며, Clickhouse나 MySQL에서도 가능했으면 좋겠음

- 요즘 **PostgreSQL**이 거의 모든 SQL 용도를 커버하는 만능 DB가 된 것 같음  
  게다가 **무료**임  
  이제 굳이 다른 SQL DB를 쓸 이유가 있을까 궁금함
  - Postgres는 훌륭하지만, **MySQL**은 마스터-마스터 복제가 더 쉽고, **MongoDB**는 지리적 분산과 샤딩이 간단함  
    **Clickhouse**는 분석용으로 훨씬 빠르고, **Cassandra** 같은 DB는 쓰기 중심 워크로드에 유리함  
    즉, 각 DB마다 여전히 강점이 있음
  - “모든 걸 잘한다”는 표현은 과장임  
    데이터가 많아지면 **성능 저하**나 **마이그레이션 문제**가 생김  
    내 경우, 기본 파티셔닝 성능이 떨어져서 직접 커스텀 파티션을 구현해야 했음
  - Postgres는 여전히 **MVCC 구현 방식**(copy-on-write)이 비효율적임  
    이 선택이 부하가 커질 때 여러 부정적 영향을 줌
  - 예전에는 **MySQL/InnoDB**가 업데이트 중심 워크로드에서 더 나았음  
    [Uber의 블로그 글](https://www.uber.com/blog/postgres-to-mysql-migration/)에서도 다뤘던 주제임  
    그래도 클라우드 환경에서는 Postgres를 가장 신뢰함
  - Postgres에는 아직 **Vitess** 수준의 성숙한 대체재가 없음  
    그래서 대규모 **OLTP 배포**에서는 여전히 MySQL이 주로 쓰임 (예: YouTube, Uber)

- **불변 데이터 구조(HAMT)** 를 이용하면 파일시스템 종류와 상관없이 즉시 클론이 가능한 DB를 만들 수 있음  
  이론이라고 말했지만 실제로 구현해봤음  
  왜 이런 **HAMT 기반 DB**가 더 많지 않은지 이해가 안 됨
  - 나는 **ClickHouse**의 작성자인데, ClickHouse도 불변 데이터 파트를 사용해 테이블 복제를 지원함  
    [관련 문서 링크](https://clickhouse.com/docs/sql-reference/statements/create/table#with-a-schema-and-data-cloned-from-another-table)
  - **Datomic**에도 이런 클로닝 기능이 내장되어 있는지 궁금함. 예전부터 써보고 싶었지만 실제 앱을 만들기엔 아직 마음의 준비가 안 됨

- **Postgres v15**에서 WAL_LOG가 기본으로 바뀐 걸 몰랐음  
  병렬 CI 테스트 환경에서는 **FILE_COPY** 전략으로 되돌리는 게 더 합리적임  
  예전 프로젝트 [integresql](https://github.com/allaboutapps/integresql)에 관련 이슈를 올렸음

- 로컬에서 Postgres 기반 앱을 테스트하기 위한 간단한 **GUI 도구 [pgtt](https://github.com/BenjaminFaal/pgtt)** 를 만든 적 있음  
  개발 환경 설정을 훨씬 단순화해줌
  - README만 봐서는 잘 모르겠는데, 템플릿을 **스냅샷처럼** 다루는 구조인지 궁금함  
    SQL 마이그레이션 반복 작업에 도움이 될 것 같음
  - README에 **GUI 스크린샷**이 있으면 좋겠고, **Docker 링크**가 깨져 있음

- 블로그의 다른 글들도 읽어봤는데 전반적으로 훌륭함  
  특히 **Postgres의 range 타입**을 처음 알게 되었음
  - range 타입은 **시간/날짜 구간 겹침 계산** 같은 데서 정말 유용함

- **MariaDB**에서도 이런 기능이 있는지 궁금함  
  테스트마다 DB를 초기 상태로 되돌리는 게 느려서 고민 중임  
  프로덕션에서 MariaDB를 쓰기 때문에 DB를 바꾸긴 어려움  
  Postgres 쪽이 더 좋아 보이긴 함
  - 각 테스트를 **트랜잭션 세션** 안에서 실행하고, 끝날 때 롤백하면 빠르게 초기 상태로 복원 가능함  
    이 방식이 꽤 효율적임
  - DB를 재시작해도 괜찮다면 **LVM**이나 **btrfs 스냅샷**을 파일시스템 레벨에서 사용하는 것도 방법임

- **AWS**에서도 유사한 기능을 지원함  
  [Aurora 클론 문서](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Clone.html)
  - Aurora의 클론은 스토리지 레벨에서 **copy-on-write**로 동작하지만, 여전히 새 클러스터를 프로비저닝해야 해서 약 10분 정도 걸림  
    통합 테스트용으로는 비현실적임
  - Aurora는 **클러스터 단위** 복제이고, 여기서 논의된 건 **데이터베이스 단위** 복제임
