본문으로 건너뛰기

2.1 CoW 계층과 공유 단위

운영 크기의 데이터를 개발 환경에 제공할 때는 재사용 대상을 먼저 확인합니다. 새 환경이 원본의 무엇을 다시 사용하는지 살펴봅니다. 테이블이 동일하게 조회된다는 사실만으로 저장 방식을 판별하기는 어렵습니다. 파일 전체 복사인지, 블록 공유인지, 과거 버전 참조인지 확인해야 합니다. 이 차이는 생성 직후의 저장량과 변경 후의 공간 증가를 설명하는 기준입니다. 원본 의존성과 복구 절차를 설명하는 기준이기도 합니다.

이 장에서는 CoW를 적용하는 계층과 공유 단위를 나누어 살펴봅니다. 파일시스템, 블록 볼륨, page 버전, 트리 노드, 불변 파일을 비교합니다. 계층의 위아래는 성능 순위를 뜻하지 않습니다. 아래 분류와 측정 질문은 구현 자료에 근거한 분석 틀입니다. 제품 전체를 하나의 방식으로 영구 분류하는 대신 개별 구현을 분석합니다.

공유 단위와 생성 모드​

CoW 경로에서는 새 사본이 기존 저장 내용을 참조합니다. 변경에 필요한 새 내용은 별도로 기록합니다. ZFS는 snapshot과 clone 사이에서 기존 블록을 공유합니다. 보존된 참조에 필요한 이전 블록은 유지합니다. Aurora도 원본과 clone이 변경되지 않은 page를 공유한다고 설명합니다. 어느 쪽에서든 변경이 발생하면 새 공간을 사용합니다. 따라서 화면의 branch 개수와 함께 실제 저장 단위도 비교해야 합니다.

기준일 2026-09-30의 구현 비교는 다음과 같습니다. 표에는 공유 대상과 대표 경로만 담습니다. 각 경로를 선택할 이유와 확인할 조건은 이어지는 산문에서 설명합니다.

구현 계층대표 경로공유 대상
파일시스템/볼륨 관리자DBLab의 ZFS 또는 LVM하부 스토리지 블록
네트워크 블록 스토리지Xata Cloud의 XatastorZFS zvol의 블록
page 버전 저장소Neon의 데이터 포함 branch조상 timeline의 page 이력
버전 관리 트리Dolt내용 주소로 참조하는 트리 노드
불변 데이터 파일Snowflake 표준 테이블 clone기존 micro-partition

이 그림의 화살표는 제품 사이의 기술 상속을 뜻하지 않습니다. 분기 요청을 처리하는 경로를 분류한 것입니다. 예를 들어 같은 서비스가 빈 DB 생성과 backup 복원을 모두 제공할 수 있습니다. 이때 두 요청은 서로 다른 시험 대상으로 둡니다. 데이터 포함 여부를 먼저 맞추지 않고 응답 시간만 비교하면 문제가 생깁니다. 서로 다른 작업의 결과를 한 지표에 섞게 됩니다.

공유 단위와 사용자가 변경하는 단위도 구분합니다. SQL에서 한 행을 수정했다고 해서 그 행만큼의 바이트를 추가한 것은 아닙니다. DBA는 변경한 행 수, 저장량 지표, 보존 중인 사본을 함께 기록하도록 시험을 설계합니다. 어떤 저장 단위를 다시 기록하는지는 해당 구현의 근거로 판단합니다. 쓰기 증폭의 크기를 계산하려면 이 표 외에 추가 근거가 필요합니다.

파일시스템과 블록 볼륨​

DBLab은 ZFS의 CoW를 이용하고 LVM을 선택하는 경로도 제공합니다. DBLab의 PostgreSQL 환경과 하부 snapshot 기능을 구분하면 관리 책임이 드러납니다. 하부 스토리지는 공유 사본을 담당합니다. DBLab은 이를 PostgreSQL clone으로 제공하는 절차를 담당합니다. 4.0에서 도입한 명명된 branch는 snapshot을 가리킵니다. 따라서 branch 포인터와 접속 가능한 clone의 상태를 구분해 기록합니다.

일반 파일 복사와 PostgreSQL 기동을 연결하는 조건도 확인해야 합니다. PostgreSQL 공식 문서는 실행 중인 cluster의 snapshot 보존 조건을 제시합니다. 필요한 WAL과 tablespace를 포함한 일관된 범위를 요구합니다. 스토리지 명령이 성공했다는 사실만으로 이 조건의 충족을 판정하지 않습니다. 파일 배치를 먼저 확인합니다. 실제 기동 조건은 일관된 분기점과 복구에서 별도로 검증합니다.

Xata Cloud의 Xatastor는 PostgreSQL 아래에 compute 측 XFS를 둡니다. NVMe-oF로 storage 측 ZFS zvol을 노출합니다. compute에서 보이는 파일시스템과 실제 CoW를 담당하는 저장 구조는 위치가 다릅니다. 이 구성을 단순히 XFS 기반 또는 네트워크 기반이라고만 적으면 ZFS의 역할이 빠집니다. 구조도에는 compute와 storage의 경계를 표시합니다. 양쪽 구성 요소도 각각 적어야 합니다.

Xata OSS는 별도 경로입니다. 공개 설명은 CloudNativePG와 OpenEBS의 로컬 또는 Mayastor 경로를 제시합니다. Xatastor는 공개 범위에 포함하지 않습니다. 각 StorageClass의 실제 clone이 CoW인지 전체 복사인지 일괄 판정한 결과는 미확인입니다. 따라서 OSS 설치 결과는 Cloud의 동작과 구분해 확인합니다. 사용한 버전과 StorageClass를 시험 기록에 남깁니다.

DBLab과 Xata를 검토할 때는 PostgreSQL 호환성과 저장소 공유를 독립된 항목으로 둡니다. DBLab은 수집 방식에 맞는 major version과 extension 바이너리 준비가 필요합니다. Xata의 무수정 PostgreSQL 설명을 Aurora 같은 다른 블록 공유 제품까지 확대하지 않습니다. 기존 온프레미스 대안 노트는 구성과 실습을 참고하는 용도로 연결합니다. 현재 기능 판정에는 이 장에 명시한 제품별 조건을 적용합니다.

Page 버전과 조상 참조​

Neon의 데이터 포함 branch는 부모 timeline의 분기 LSN과 조상 관계를 사용합니다. 자식의 읽기에 필요한 page 버전이 자식 이력에 없으면 조상에서 찾습니다. 이때 부모가 분기 후에 기록한 변경은 자식의 상태에 섞지 않습니다. 공유 대상은 특정 시점의 page를 재구성하는 이력입니다. 사용자가 보는 독립된 DB와 저장 파일의 독립성은 구분합니다.

이 차이를 설명하기 위해 부모에서 분기한 뒤 두 환경이 같은 테이블을 수정한다고 가정합니다. 읽기 결과를 대조할 때는 테이블 이름과 함께 요청한 branch와 시점을 기록합니다. 자식에서 보이지 않는 부모 변경은 분기 의미에 따른 결과인지 판정합니다. 별도 동기화를 기대했던 요구와의 차이인지도 구분합니다.

Pageserver의 layer 구성, page 재구성, 조상 탐색은 별도 문서에서 자세히 다룹니다. Neon 아키텍처와 Timeline과 Branch 내부를 참고합니다. 여기서는 저장 이력의 공유와 compute 준비를 서로 다른 작업으로 다룹니다. 이력 참조가 성립해도 접속이나 첫 쿼리 성능까지 준비되었다고 추론하지 않습니다. 이를 구분하도록 측정 경계를 나눕니다.

또한 page 버전이라는 분류만으로 모든 PostgreSQL 기능과 운영 도구의 호환성을 판단하지 않습니다. 제품 비교에는 저장 구조 설명과 함께 실제 엔진 및 배포 조건을 별도로 적습니다. 공유 방식은 데이터가 어디에서 오는지 설명합니다. 업무 SQL의 호환성이나 운영 장애의 범위는 직접 검증해야 합니다.

트리 노드와 불변 파일​

Dolt의 Prolly tree는 노드를 내용 주소로 저장하고 버전 사이에서 같은 노드를 공유합니다. 고정 길이 값의 갱신에서는 변경한 leaf와 root까지의 참조 경로가 달라집니다. 값의 길이나 chunk 경계가 달라지는 변경에는 재청킹이 개입합니다. 따라서 모든 수정이 정확히 하나의 leaf만 새로 쓴다고 단정하지 않습니다. 저장 공간의 공유를 설명하는 단위는 행 자체보다 트리 노드에 가깝습니다.

Dolt의 데이터 머지는 cell 단위 변경을 고려합니다. 따라서 저장 단위와 충돌 판정 단위를 분리해서 설명해야 합니다. 여러 행을 담은 노드를 새로 기록하더라도 해당 행 전체의 논리 충돌을 뜻하지는 않습니다. 반대로 저장 공간을 적게 추가하는 변경이어도 머지 검토가 필요한 경우가 있습니다. 동일 cell에 상충하는 수정이 생기는 경우입니다. 구체적인 예는 Merge와 운영 반영에서 다룹니다.

Snowflake의 표준 테이블 clone은 기존 micro-partition을 공유합니다. 변경 시에는 새 micro-partition을 기록합니다. 이 장에서는 그 저장 경로를 불변 데이터 파일 공유로 분류합니다. PostgreSQL의 page나 Dolt의 노드와 같은 물리 단위로 환산하지 않습니다. Snowflake 문서는 hybrid table에 다른 저장 비용 조건을 명시합니다. 따라서 이 설명의 적용 범위도 표준 테이블로 제한합니다.

트리와 파일을 공유한다는 사실은 시험 설계의 출발점입니다. 업무에서 중요한 값이 무엇인지 먼저 정합니다. 해당 값을 변경했을 때 새로 기록하는 저장량과 읽기 시간을 각각 관찰합니다. 큰 객체의 일부 변경, 반복 갱신, 오래 보존하는 사본을 별도 시나리오로 둡니다. 그러면 생성 직후의 작은 증가량을 넘어 사용 기간의 비용을 평가하는 것이 가능합니다. 이 시나리오들은 제품 성능을 검증하기 위한 제안입니다. 기존 측정 결과를 제시한 것은 아닙니다.

빈 DB와 복사 경로의 분리​

PlanetScale Postgres의 일반 새 branch는 부모 schema와 data가 없는 빈 DB입니다. backup에서 생성하는 경로는 schema와 data를 포함합니다. 각 branch는 자체 스토리지를 갖고 부모를 지속적으로 복제하지 않습니다. 두 경로는 초기 상태와 준비 작업이 다릅니다. 따라서 CoW 비교표에 포함할지는 제품 이름의 branch만으로 판단할 수 없습니다.

Supabase의 기본 branch는 운영 데이터를 제외하고 schema, Edge Functions와 설정을 준비합니다. 대시보드의 Include data 옵션에는 PITR add-on 조건이 붙습니다. 데이터를 포함하는 옵션이 있다는 사실만으로 내부 저장 공유 방식까지 확인된 것은 아닙니다. 이 장에서는 기본 경로와 데이터 포함 경로를 구분합니다. 미확인인 내부 구현은 미확인으로 유지합니다.

외부 원본에서 논리 복사로 기준 DB를 준비하는 설계도 있습니다. 그 기준 DB에서 CoW clone을 제공하는 설계는 별도로 평가해야 합니다. 이 경우 비교 기록을 수집 단계와 분기 단계로 나누는 방법을 제안합니다. 이후 clone이 빨리 준비되더라도 초기 데이터 수집과 갱신 시간은 별도로 기록합니다. 수집 주기와 기준 데이터 시점을 함께 적어 시험 환경의 최신성을 판단합니다.

도입 검토서는 생성 모드, 공유 계층, 공유 단위, 원본 식별자, 분기 기준을 한 요청에 대응시켜 작성합니다. 그런 다음 필요한 데이터가 모두 포함되었는지 검증하고 SQL 준비 시간을 측정합니다. 이 순서로 비교하면 저장 구조의 차이를 준비 시간과 복구 조건으로 연결할 수 있습니다. 제품의 다른 생성 모드를 서로 바꾸어 설명하는 오류도 줄입니다.

참고​