PostgreSQL을 설계할 때 흔히 마주하는 고민이 있습니다. 신규 데이터베이스를 만들 것인가, 기존 DB에 스키마를 추가할 것인가, 혹은 테이블스페이스를 활용할 것인가? 이번 글에서는 각 선택지가 어떤 의미를 가지며, PaaS(PostgreSQL 17 기준) 환경에서는 어떻게 접근해야 할지 정리해보겠습니다.


1. 신규 데이터베이스(DB)를 만들 때

강한 경계(격리)가 필요할 때 유리합니다.

  • 백업/복구 라이프사이클 분리: 서비스별로 서로 다른 PITR(시점복구) 정책, 장기 보관 요구가 있을 때.
  • 보안 경계: 팀, 벤더, 운영주체가 달라 권한을 완전히 분리해야 할 때.
  • 인코딩/Collation 차이: DB 생성 시 지정 가능하므로 서로 다른 로케일이 필요할 때.
  • 확장(Extensions) 충돌 방지: 특정 DB만 PostGIS, pgvector 같은 확장을 쓸 때.
  • 교차 조인 불필요: PostgreSQL은 DB 간 조인이 불가능(단, FDW/dblink는 예외)하기 때문에 완전 독립 워크로드라면 DB 분리가 깔끔.

단점: DB 단위로 커넥션 풀을 따로 잡아야 하고, 운영 복잡성이 증가.


2. 같은 DB 안에서 스키마를 추가할 때

느슨한 경계가 필요한 경우 적합합니다.

  • 교차 조인/외래키/트랜잭션 가능: 스키마는 같은 DB 안 네임스페이스이므로 서로 참조 가능.
  • 권한 제어: 스키마 단위 USAGE/CREATE + 오브젝트 권한으로 팀별 격리 가능.
  • 운영 단순화: 백업, Autovacuum, 모니터링을 한 DB 단위에서 일괄 관리.
  • 커넥션 풀 효율: 여러 스키마를 같은 커넥션에서 다룰 수 있음.

주의: 같은 DB의 자원(WAL, Autovacuum, 통계)을 공유하므로 한 스키마의 대량 작업이 다른 스키마에 영향을 줄 수 있음.


3. 테이블스페이스를 고려할 때

테이블스페이스는 특정 테이블이나 인덱스를 다른 물리적 스토리지에 저장하기 위한 논리 단위입니다.

  • Hot/Cold 데이터 분리: 최근 데이터는 고성능 스토리지, 과거 파티션은 저렴한 스토리지.
  • 특정 인덱스 분리: 랜덤 I/O가 많은 인덱스를 IOPS 높은 볼륨에 배치.
  • 임시 작업: TEMP 테이블스페이스를 분리해 쿼리 스필 I/O 격리.

⚠️ PaaS(PostgreSQL on Cloud SQL, Azure Database 등)에서는 사용자 정의 테이블스페이스 생성이 제한되는 경우가 많습니다. 이 경우 스토리지 티어 선택, 파티셔닝, 인덱스 전략으로 대체해야 합니다.


4. 의사결정 체크리스트

  • 조인/트랜잭션 필요 여부 → 필요하면 스키마, 불필요하면 DB.
  • 백업/복구 단위 → 서로 다른 정책 필요하면 DB 분리.
  • 보안 경계 → 강한 격리 필요 시 DB, 팀 내부 구분은 스키마.
  • 확장/Collation 차이 → DB 단위 분리 필요 여부 확인.
  • PaaS 제약 → 테이블스페이스 지원 여부 확인, 대안은 파티셔닝/스토리지 티어.

5. 설계 예시

  • 공통 서비스 + 분석: 하나의 DB에서 core, ops, bi 스키마로 분리.
  • 외부 벤더 운영 모듈: 별도 DB 생성, 네트워크 레벨 접근 제어.
  • 로그/이벤트: 최근 파티션은 빠른 스토리지, 과거 파티션은 저렴 스토리지. (PaaS에서 테이블스페이스 제한 시 파티셔닝으로 대체)
-- (1) 신규 DB 생성
CREATE DATABASE appdb TEMPLATE template1
  LC_COLLATE 'en_US.utf8' LC_CTYPE 'en_US.utf8';

-- (2) 스키마 분리
CREATE SCHEMA core AUTHORIZATION app_owner;
CREATE SCHEMA ops  AUTHORIZATION ops_owner;

GRANT USAGE ON SCHEMA core TO app_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA core TO app_role;

-- (3) (옵션) 테이블스페이스 예시 (온프렘/자유로운 환경일 때)
-- CREATE TABLESPACE fast_ts LOCATION '/mnt/fast';
-- CREATE TABLESPACE cold_ts LOCATION '/mnt/cold';

-- (4) 파티션 예시
CREATE TABLE logs (
  id bigserial, ts timestamptz NOT NULL, data jsonb, PRIMARY KEY (id, ts)
) PARTITION BY RANGE (ts);

결론

  • DB 분리: 강한 경계(보안, 백업, 확장 차이).
  • 스키마 분리: 느슨한 경계(조인 필요, 운영 단순화).
  • 테이블스페이스: 스토리지 I/O 최적화(단, PaaS 제약 고려).

PostgreSQL 17 기반 PaaS 환경에서는 스키마 중심의 설계가 일반적이고, DB/테이블스페이스 분리는 보안·복구·성능 요구사항에 따라 선택적으로 활용하는 것이 좋습니다.


 

+ Recent posts