1.4 선택 기준과 흔한 오판
branching 제품을 고를 때 기능 목록을 나열해도 큰 도움이 되지 않습니다. 대부분의 제품이 "branch", "instant", "copy-on-write"라는 같은 단어를 쓰기 때문입니다. 대신 자기 팀의 상황을 묻는 질문 몇 개를 먼저 정합니다. 그런 다음 제품이 각 질문에 어떻게 답하는지 확인하는 편이 빠릅니다. 이 장에서는 그 질문들과 각 질문에서 어긋나기 쉬운 지점을 정리합니다.
질문 1: branch에 데이터가 들어 있어야 하는가
가장 먼저 갈리는 지점입니다. 마이그레이션 소요 시간을 재거나 실행 계획을 확인하거나 사고 복구를 연습하려면 실제 크기의 데이터가 필요합니다. 데이터가 필요하고 생성 속도와 thin storage까지 중요하다면 copy-on-write 제품이 우선 후보입니다. 해당 제품은 Neon, Xata, DBLab, Aurora clone, Tiger fork입니다. 데이터 포함 여부만 따지면 PlanetScale의 backup/PITR 복원 branch나 Supabase의 include data 옵션도 가능합니다. 다만 이들은 물리 복사 방식이므로 생성 시간과 저장 공간이 크기에 비례합니다.
반대로 PR마다 빈 데이터베이스에 마이그레이션을 적용하고 통합 테스트만 실행한다면 데이터가 없어도 됩니다. Supabase나 PlanetScale의 branch가 이 목적에 맞습니다. CI에서 매번 새 PostgreSQL 컨테이너를 실행하는 것으로 충분한 경우도 많습니다. 데이터 없는 branch에 copy-on-write 스토리지를 추가하면 비용만 늘어납니다.
중간 선택지는 schema-only branch입니다. Neon은 schema만 복제한 branch를 지원합니다. 이 branch는 copy-on-write 자식이 아니라 독립된 root branch입니다. 따라서 부모에서 reset하는 기능은 사용할 수 없고, 플랜별 root branch 개수 제한에 걸립니다. "schema-only"라는 이름만 보고 자식 branch와 같은 성질을 기대하면 운영 중 예상과 다른 동작을 겪습니다.
질문 2: 운영 데이터를 개발자에게 보여 주어도 되는가
데이터를 포함한 branch는 운영 데이터의 사본입니다. 개인정보, 결제 정보, 접근 토큰이 그대로 들어 있습니다. branch를 만들기 쉬워지면 운영 데이터가 개발 환경으로 퍼지는 속도도 빨라집니다. 규제 대상 데이터를 다루는 팀은 다음 중 하나를 골라야 합니다.
- anonymization 절차를 branch 생성 직후에 자동으로 실행한다
- schema-only branch에 합성 데이터를 채운다
- 운영 branch 접근 권한을 소수에게만 주고, 그들이 anonymized branch를 만들어 배포한다
Neon 문서는 schema-only branch의 용도로 "무작위화 또는 anonymized 데이터를 채우는" 흐름을 안내합니다. 어느 방법을 택하든 branch 생성 권한과 접근 권한을 코드 저장소 권한과 같은 수준으로 설계해야 합니다. 이 문제는 4.5 Schema-only Branch와 민감 데이터에서 절차로 다룹니다.
질문 3: 과거 시점이 얼마나 필요한가
과거 시점에서 branch를 만들려면 그 시점까지의 history가 남아 있어야 합니다. history를 오래 보관할수록 저장 비용이 늘어납니다. Neon은 이 보존 범위를 history window라는 프로젝트 설정으로 관리합니다. Free는 최대 6시간 또는 변경량 1 GB 중 먼저 도달하는 범위로 제한합니다. Launch는 최대 7일, Scale은 최대 30일로 제한합니다. Tiger Cloud의 --to-timestamp fork는 복구 가능 범위 안에서만 동작합니다. Aurora clone은 최신 복구 가능 시점을 사용하는 것이 기본입니다.
판단이 갈리는 지점은 "언제 사고를 알아채는가"입니다. 잘못된 DELETE를 실행한 직후 알아차리면 6시간으로 충분합니다. 하지만 배치가 잘못된 값을 쓴 사실을 며칠 뒤 발견하는 경우가 실제로 더 많습니다. 사고를 발견하기까지 걸린 평균 시간을 먼저 측정해야 합니다. 그런 다음 그 시간을 넘는 보존 범위를 고르거나 별도 백업으로 보완해야 합니다.
질문 4: branch당 비용이 어떻게 계산되는가
스토리지는 delta만 늘어나지만 compute는 branch마다 필요합니다. 비용은 두 축으로 나뉩니다.
| 항목 | 늘어나는 조건 | 줄이는 장치 |
|---|---|---|
| 스토리지 | 계보 전체의 고유 변경 블록, history 보존 기간, branch 수명 | 오래된 branch 삭제, 보존 범위 축소 |
| compute | branch에 붙은 인스턴스 수와 가동 시간 | scale-to-zero, 만료 시각 지정 |
| 운영 인력 | branch 수명 관리, 권한 관리 | 자동 삭제, CI 연동 |
Neon은 scale-to-zero와 branch 만료 시각 지정으로 두 축을 모두 관리합니다. scale-to-zero는 유휴 compute를 기본 5분 뒤 정지합니다. Xata도 scale-to-zero를 제공합니다. 반면 Aurora clone은 clone마다 DB 인스턴스를 연결해야 합니다. provisioned 인스턴스는 자동으로 정지하지 않습니다. Aurora Serverless v2는 지원 버전에서 최소 용량을 0 ACU로 설정할 수 있습니다. 이 경우 유휴 시 자동 pause하고 연결 시 resume합니다. 온프레미스의 ZFS clone은 스토리지 비용이 거의 없습니다. 다만 PostgreSQL 프로세스는 운영자가 직접 시작하고 정지해야 합니다. 이 계산은 6.1 비용 모델에서 수치로 확인합니다.
질문 5: 나중에 빠져나오기 쉬운가
copy-on-write를 위해 데이터베이스를 수정한 제품은 그만큼 lock-in이 커집니다. Neon은 PostgreSQL 소스에 패치를 유지하며, 그중 일부는 WAL 레코드 형식을 바꿉니다. Neon 저장소 문서는 heap WAL 레코드에 t_cid 필드를 추가한 변경을 명시합니다. 이 변경으로 Neon WAL 형식은 vanilla PostgreSQL과 호환되지 않습니다. 물리 replication이나 WAL 아카이브를 그대로 다른 PostgreSQL로 옮길 수 없습니다. 데이터를 빼내려면 논리 복제나 dump를 사용해야 합니다. 또한 Neon은 메이저 버전을 제자리에서 올리지 않습니다. 새 프로젝트를 만들어 마이그레이션하는 방식을 안내합니다.
파일시스템이나 블록 계층에서 copy-on-write를 하는 제품은 데이터 디렉터리가 표준 PostgreSQL 형식이므로 이탈이 쉽습니다. DBLab의 clone은 일반 PostgreSQL 데이터 디렉터리입니다. Xata 위의 PostgreSQL도 vanilla 빌드입니다. Dolt 계열은 반대 극단입니다. 데이터를 빼내려면 SQL로 export해야 하며, branch history는 함께 가져갈 수 없습니다.
질문 6: 오픈소스가 어디까지인가
"오픈소스"라는 말도 공개 범위를 확인해야 합니다.
| 제품 | 공개 | 비공개 |
|---|---|---|
| Neon | pageserver, safekeeper, compute 이미지, 패치된 PostgreSQL | control plane (프로젝트, branch 관리 API) |
| Xata | SQL gateway, branch operator, 인증, CLI, scale-to-zero 플러그인 | Xatastor 스토리지 엔진, 멀티 리전 배포 |
| DBLab Engine | 엔진 전체 (Apache 2.0) | 유료 지원과 콘솔 |
| Dolt / Doltgres | 엔진 전체 (Apache 2.0) | DoltHub 호스팅 서비스 |
Neon을 자체 호스팅하려면 공개된 구성 요소를 조합해야 합니다. control plane 역할도 직접 만들어야 합니다. 저장소의 docker-compose 예제는 storage controller 없이 동작합니다. 또한 실행 중인 compute를 재구성하는 수단이 없다고 밝힙니다. 학습에는 충분하지만 팀이 사용하는 서비스로 운영하기에는 필요한 부분이 많이 빠져 있습니다. Xata OSS는 구성 요소가 더 잘 갖춰져 있습니다. 다만 스토리지 엔진이 비공개이므로 오픈소스 버전의 성능 특성은 상용 버전과 다를 가능성이 있습니다.
질문 7: 온프레미스에서 돌아가야 하는가
규정이나 네트워크 때문에 클라우드 서비스를 사용할 수 없다면 후보가 크게 줄어듭니다. 남는 것은 ZFS 직접 구성, DBLab Engine, Xata OSS, Neon 자체 호스팅, Dolt 계열입니다. 이 가운데 현재 운영 중인 PostgreSQL을 유지한 채 함께 사용할 수 있는 선택지는 ZFS 직접 구성과 DBLab Engine입니다. 나머지를 선택하면 데이터베이스를 새 스택으로 이전해야 합니다. Part V에서 각 방법의 요구 인프라와 운영 부담을 실제 절차로 비교합니다.
도입 순서 제안
한 번에 제품을 정하기보다 단계를 나누는 편이 실패 비용이 낮습니다. 첫 단계는 현재 운영 중인 PostgreSQL 옆에 thin clone을 구성해 보는 것입니다. 스테이징 서버 한 대에 ZFS를 구성하고 pg_basebackup으로 복제합니다. 그런 다음 clone에서 마이그레이션 리허설을 하면 팀이 branching에서 실제로 얻는 가치가 드러납니다. 이 단계에서 "과거 시점 분기가 필요하다", "PR마다 자동으로 만들어져야 한다" 같은 요구가 구체화됩니다.
두 번째 단계에서는 그 요구를 기준으로 제품을 고릅니다. 자동화와 API가 중요하면 DBLab Engine 또는 클라우드 서비스가 후보입니다. 과거 임의 시점과 서버리스 compute가 중요하면 Neon 계열이 후보로 남습니다. 데이터 머지가 필요하면 Dolt 계열이 후보로 남습니다. 세 번째 단계에서는 권한, anonymization, 만료 정책을 코드로 고정합니다. 그 뒤에 팀 전체에 공개해야 합니다. 이 순서를 건너뛰고 branch 생성을 먼저 허용하면 아래 문제를 한꺼번에 만납니다.
자주 나오는 오해
branch를 replica로 오해하는 문제는 1.1에서 다뤘습니다. 그 밖에 도입 뒤 드러나는 오해를 몇 가지 정리합니다.
branch 수를 통제하기 어렵습니다. branch는 만들기 쉬우면 삭제하지 않게 됩니다. 만료 시각을 기본으로 지정해야 합니다. CI가 만든 branch는 CI가 삭제하도록 해야 합니다.
부모 branch가 바쁠 때 자식 branch의 읽기 성능이 영향을 받는지는 제품마다 다릅니다. Neon은 branch가 부모의 성능에 영향을 주지 않는다고 설명합니다. 그러나 스토리지를 공유하는 구조에서는 pageserver 부하도 공유됩니다. 실제 워크로드로 측정해야 합니다.
extension과 버전 호환성도 확인해야 합니다. 데이터베이스를 수정한 제품은 지원하는 extension 목록이 정해져 있습니다. 최신 메이저 버전의 도입이 늦어질 수도 있습니다. 필요한 extension의 지원 여부를 도입 전에 확인합니다.
마지막으로 branching은 백업을 대체하지 않습니다. 같은 스토리지의 history를 공유하는 구조이기 때문입니다. 스토리지 계층의 장애나 계정 삭제 같은 시나리오에는 별도 백업이 필요합니다. 어떤 제품 문서도 이 점을 크게 다루지 않지만 설계 문서에는 반드시 적어야 합니다.
연습 문제
- 위 일곱 질문에 대한 팀의 답을 한 줄씩 적고, 그 답으로 후보 제품을 두 개 이하로 줄여 봅니다.
- 사고를 발견하기까지 걸린 평균 시간을 최근 사례로 추정하고, Neon 플랜별 history window와 비교합니다. 부족하면 어떤 백업 정책으로 보완할지 적습니다.
- Neon의 WAL 형식 비호환이 실제 이탈 시나리오(다른 PostgreSQL로 이전)에서 어떤 절차를 강제하는지 정리합니다. 논리 복제와 dump 두 경로의 장단도 정리합니다.