5.1 PR별 Preview 운영
두 PR을 같은 staging DB에서 검토하려면 먼저 서로 미치는 영향을 구분해야 합니다. 각 PR의 migration과 시험 데이터가 그 대상입니다. 이 장에서는 PR마다 DB 환경을 배정하는 운영 구성을 제안합니다. 코드 배포부터 검토 종료까지 같은 작업 식별자로 추적합니다. 생성 성공에 더해 접속 준비와 migration 결과를 확인합니다. 사용 중인 코드 버전과 삭제 완료도 각각 확인합니다.
Preview에 필요한 데이터 범위도 먼저 정합니다. 화면과 API의 기본 동작 시험에는 schema와 seed를 검토합니다. 특정 데이터 분포가 필요한 시험에는 데이터 포함 사본을 검토합니다. 모든 PR에 운영 데이터 전체를 제공하는 규칙을 기본값으로 두지 않습니다. 아래의 제품 설명과 공개 사례를 제외한 절차는 이 장의 운영 설계 제안입니다. 수명 관리, 부하 시험, 실패 대응 절차가 이에 해당합니다.
적용 계층과 제품
데이터 준비 방식의 구분
Supabase의 기본 branch는 schema, Edge Functions, 설정을 준비합니다. 운영 데이터와 Storage object는 포함하지 않습니다. Dashboard의 Include data는 별도 선택입니다. 이 옵션에는 PITR add-on이 필요합니다. 데이터 포함 여부에 따라 디스크와 compute 비용도 달라집니다. 따라서 기본 preview와 데이터 포함 preview의 원가를 구분해 계산합니다. 이 옵션이 있다는 사실만으로는 내부 복사가 CoW인지 알 수 없습니다.
PlanetScale은 엔진 계열을 구분합니다. Vitess의 deploy request는 schema 변경을 검토하고 배포하는 절차입니다. Preview의 업무 데이터를 운영 DB로 머지하는 일반 기능으로 설명하지 않습니다. PlanetScale Postgres의 일반적인 새 branch는 빈 DB입니다. schema와 data가 모두 없는 상태입니다. backup에서 복원하는 경로는 둘을 포함합니다. Postgres branch는 Vitess의 schema 배포 절차와 구분해 다룹니다.
데이터 포함 PostgreSQL 환경에는 Neon의 page 버전 기반 분기를 검토합니다. Xata도 후보이지만 상용 Xatastor와 OSS의 스토리지 구성을 구별합니다. 상용 Xatastor는 ZFS zvol 기반 경로를 사용합니다. OSS의 모든 StorageClass에서 같은 복사 방식이 동작하는지는 미확인입니다. 제품 선택 후에는 지원 모드와 원본 식별자를 생성 요청의 입력으로 남기도록 제안합니다. 제공할 데이터 범위도 함께 남깁니다.
Neon의 구체적인 Actions 연결은 PR마다 Branch 실습에서 다룹니다. 그 절차는 PR 이벤트에 생성과 삭제를 연결하는 예제입니다. 여기서는 Action의 입력이나 요금제 숫자를 반복하지 않습니다. 같은 수명을 다른 플랫폼에 적용할 때 필요한 상태 확인과 책임 분담을 설명합니다.
공개 고객 사례의 범위
Superwall은 GitHub Actions와 PlanetScale API를 연결했습니다. 이 연결로 새 PR마다 branch를 자동 생성하는 흐름을 공개했습니다. Branching과 deploy requests를 개발 절차에 사용한 사례입니다. 고객 인터뷰를 포함한 공급사 자료이므로 신뢰도는 보통입니다. 이 사례는 Vitess 계열의 개발 환경 자동화 근거로 사용합니다. 애플리케이션의 paywall 표시량을 branch 생성량으로 옮겨 쓰지 않습니다. Superwall 사례
Soshi는 Supabase branching으로 환경을 구분했다고 설명합니다. 구분한 환경은 개발, staging, production입니다. 실명 고객의 도입을 소개한 공급사 자료이므로 신뢰도는 보통입니다. PR마다 preview를 만든 수량과 자동 정리 정책은 사례 미확인입니다. 환경 분리 도입과 PR별 수명 자동화를 서로 다른 증거로 취급합니다. Soshi 사례
운영 DB에 주는 부하
부하 시험은 기준 데이터 준비와 PR 실행을 나누어 설계합니다. 외부 운영 DB에서 기준 사본을 수집한다면 초기 읽기와 전송량을 별도로 기록합니다. 갱신 주기도 기록합니다. WAL을 전달하는 경로를 선택했다면 전송과 보존 상태도 관찰합니다. 준비된 기준 사본에서 PR별 환경을 만드는 단계는 별도 생성 작업으로 집계합니다. 운영 DB에서 데이터를 다시 가져오는 단계와 구분합니다.
PR 실행에서는 SQL 접속 준비 시간과 첫 시험 쿼리의 시간을 구분해 기록합니다. migration 시간과 검토 중 compute 실행 시간도 따로 기록합니다. Neon의 비용 설명도 compute, 데이터 저장과 복구 이력 등을 구별합니다. 분기 메타데이터를 준비한 시각만으로 preview 사용까지 걸린 시간을 대표하지 않습니다. 애플리케이션의 준비 완료 확인을 마지막 측정 지점으로 정하도록 제안합니다.
동시 PR 시험에는 개수뿐 아니라 변경 종류를 반영합니다. 읽기 위주의 PR 여러 개를 실행하는 시나리오를 준비합니다. 인덱스 생성 또는 대량 데이터 변경을 수행하는 PR 여러 개는 별도로 실행합니다. 운영 응답 시간과 시험 환경의 자원 사용량을 같은 시간축으로 비교합니다. 공유 스토리지의 경합 여부는 측정 결과로 판단합니다. 데이터 쓰기 격리만으로 성능 격리까지 보장한다고 가정하지 않습니다.
정리 비용도 사용 기간에 포함합니다. PR 종료 시점과 compute 종료 시점을 각각 남기도록 제안합니다. branch 삭제 확인 시점도 따로 남깁니다. 사용량이 줄어드는지는 제품의 청구 지표로 확인합니다. PR이 닫혔다는 사실만으로 비용 집계를 끝내지 않습니다. 조사 목적으로 남긴 환경은 예외 보존 목록에 따로 표시합니다.
흔한 실패
다음 항목은 공개 고객사의 장애 이력이 아닌 사전 검증용 실패 시나리오입니다. 먼저 생성 요청이 성공했으나 응답을 받지 못한 경우를 시험합니다. 재시도 시 중복 생성을 막도록 저장소와 PR 식별자를 조회 키로 사용합니다. 생성 후 받은 실제 branch ID를 기록합니다. 동일 PR의 후속 작업은 기록된 ID와 소유 정보를 대조하도록 설계합니다. 이름만 재계산하는 방식은 피합니다.
접속 정보 오배포도 별도로 시험합니다. Preview 애플리케이션의 DB 연결이 운영 endpoint를 가리키는지 확인합니다. 운영 endpoint에 연결되면 branch를 준비한 의미가 사라집니다. 배포 전 허용 대상 목록과 실제 endpoint를 비교하는 절차를 제안합니다. migration도 같은 대상을 사용하는지 확인합니다. Supabase는 branch별 API 자격증명을 제공합니다. 이 사실과 배포 작업이 올바른 자격증명을 주입했는지는 별도로 확인합니다.
커밋 갱신 과정에서는 이전 코드의 시험 결과와 새 코드의 화면이 섞인 상황을 재현합니다. 시험 결과에 코드 commit과 migration checksum을 함께 표시합니다. 검토 대상 commit이 바뀌면 기존 통과 상태를 그대로 사용하지 않도록 제안합니다. 기준 데이터를 갱신했다면 데이터 시점도 바뀐 실행으로 기록합니다. 실패한 환경을 최신 부모 상태로 자동 초기화하기 전에 조사 자료 보존 여부를 결정합니다.
정리 작업의 실패는 성공한 시험과 별개로 관리합니다. 생성 후 migration이 실패한 경우와 검토 중 PR이 닫힌 경우를 각각 시험합니다. 삭제 요청의 결과를 알 수 없는 경우도 시험합니다. 실패 로그에는 자격증명을 남기지 않습니다. 작업 ID, branch ID, 마지막 상태를 남깁니다. 정리 재시도는 삭제 대상이 해당 PR의 환경인지 대조한 뒤 실행하도록 제안합니다.
운영 정책 제안
명명과 상태 기록
명명 규칙은 preview-저장소-PR번호를 제안합니다. 예를 들어 preview-orders-pr123은 사람이 목적을 확인하는 표시명으로 사용합니다. 저장소 이름의 충돌이나 변경에 대비해 저장소의 고유 ID를 별도 필드로 보관합니다. PR 번호와 branch ID도 별도 필드로 보관합니다. 소유 팀, 요청자, 원본 식별자를 같은 레코드에 기록합니다. 데이터 기준 시점, 만료 시각, 비용 태그도 함께 기록합니다.
운영 상태는 생성 요청, 접속 준비, migration 완료로 나누어 기록하도록 제안합니다. 이후 상태는 검토 가능, 정리 대기, 삭제 확인으로 구분합니다. API 응답을 받았다는 이유만으로 검토 가능 상태를 부여하지 않습니다. 작업 중단 후에도 담당자가 완료 단계를 판단하도록 상태별 마지막 확인 시각을 남깁니다. 실패 사유도 함께 남깁니다. 제품이 제공하는 상태를 확인하고 관리 시스템에서 필요한 부분을 보완합니다.
TTL과 quota
TTL은 PR 상태와 독립된 만료 시각으로 설정하는 정책을 제안합니다. 구체적인 기간은 팀의 검토 소요 시간과 데이터 민감도에 맞춰 정합니다. 이 기간을 제품의 보장값으로 제시하지 않습니다. PR 종료는 즉시 정리 조건으로 사용합니다. TTL은 이벤트 누락에 대비한 별도 조건으로 사용합니다. 만료 연장에는 소유자, 사유, 새 종료일을 요구하는 구성을 권합니다. 예외에도 반드시 기간을 정하도록 합니다.
Quota는 팀별 보유 branch 수, 동시 생성 수, 활성 compute를 나누어 설정합니다. 변경 저장량도 별도로 설정합니다. 대형 migration을 수행하는 작업에는 별도 동시 실행 한도를 제안합니다. 한도에 도달하면 운영 DB로 시험을 우회하지 않습니다. 대기 상태와 부족한 자원을 표시합니다. 담당자는 기록을 보고 방치된 환경 정리, 실행 순서 조정, 한도 변경 중 무엇을 할지 결정합니다.
삭제 재시도와 정기 대조 작업도 제안합니다. 열린 PR 목록과 실제 환경 목록을 비교해 소유자를 찾지 못한 환경을 확인합니다. 폐기 대상은 검토 후 정리합니다. 종료된 PR에 환경이 남아 있으면 삭제 상태를 추적합니다. 운영 반영은 검토한 코드와 migration 파일의 배포 절차로 연결합니다. preview에서 변경한 업무 데이터를 운영에 자동 복사하는 단계는 추가하지 않습니다.
도식
다음 sequenceDiagram은 제품 공통 API 명세가 아닌 운영 수명 제안입니다. 정상 검토와 실패 후 정리를 함께 표시합니다. 만료 점검은 PR 이벤트를 처리하는 작업과 분리합니다. 시험이 실패해도 branch 식별 정보는 정리 작업에 전달합니다.
도식의 완료 조건은 검토 주소 발급과 삭제 확인 두 곳에 둡니다. 전자는 개발자가 사용할 준비가 되었는지 확인합니다. 후자는 환경의 운영 책임을 종료해도 되는지 확인합니다. 두 조건의 지연과 실패를 각각 집계합니다. 이를 바탕으로 생성 속도 개선 작업과 정리 누락 방지 작업을 구분해 배정합니다.