PostgreSQL 데이터를 Parquet으로 S3에 저장하는 LTAP 아키텍처
운영 데이터베이스로 PostgreSQL을 사용하는 환경에서 데이터가 쌓일수록 분석 쿼리의 부담은 커진다. OLTP 목적으로 설계된 PostgreSQL에 집계·통계 쿼리가 뒤섞이면 운영 성능 저하는 피하기 어렵다. 이를 해결하기 위한 현실적인 접근 중 하나가 LTAP(Load, Transform, Analyze, Persist) 패턴이다. 핵심 아이디어는 PostgreSQL의 데이터를 컬럼형 포맷인 Parquet으로 변환해 S3에 적재하고, 분석 계층을 운영 DB로부터 완전히 분리하는 것이다.
이 구조는 전통적인 ETL 파이프라인과 유사해 보이지만, 저장 포맷과 쿼리 엔진의 선택에서 실용성이 크게 달라진다. Parquet은 컬럼 단위 압축과 predicate pushdown을 지원하기 때문에, 수억 건의 레코드를 다루는 분석 워크로드에서 행 기반 포맷 대비 I/O 비용을 현저히 줄일 수 있다.
아키텍처 흐름과 구성 요소
일반적인 LTAP 아키텍처는 다음 흐름으로 구성된다.
- Load: PostgreSQL의 변경 데이터를 CDC(Change Data Capture) 또는 배치 추출 방식으로 수집한다.
pg_logical또는 Debezium 같은 도구가 자주 활용된다. - Transform: 추출된 raw 데이터를 비즈니스 의미에 맞게 정제·변환한다. 필요에 따라 Apache Spark, dbt, 혹은 간단한 Python 스크립트가 사용된다.
- Analyze: S3에 적재된 Parquet 파일을 Amazon Athena, Trino, DuckDB 등의 쿼리 엔진으로 직접 조회한다. 별도의 데이터 웨어하우스 없이 S3를 스토리지 계층으로 삼는 레이크하우스 접근이다.
- Persist: 분석 결과나 집계 데이터를 다시 S3 또는 필요한 경우 별도 스토리지에 저장한다.
PostgreSQL
└─► CDC / Batch Extract
└─► Transform (Spark / dbt)
└─► S3 (Parquet, partitioned)
└─► Athena / Trino / DuckDB
파티셔닝 전략도 중요하다. 날짜·테넌트·도메인 기준으로 디렉터리를 나누면 쿼리 엔진이 불필요한 파일을 스캔하지 않아 비용과 속도 모두 개선된다.
실무에서 주의할 포인트
백엔드 개발자 입장에서 이 아키텍처를 도입할 때 자주 마주치는 문제가 있다.
첫째, 스키마 변화 대응이다. PostgreSQL 테이블에 컬럼이 추가·삭제되면 기존에 쌓인 Parquet 파일과 스키마가 불일치할 수 있다. Iceberg나 Delta Lake 같은 테이블 포맷을 도입하면 스키마 진화(schema evolution)를 관리하기 훨씬 수월해진다.
둘째, 데이터 지연(latency) 허용 범위다. CDC 기반이라도 실시간과 준실시간 사이에는 차이가 있다. 분석 요건이 수 분 이내의 최신 데이터를 요구한다면 파이프라인 설계가 복잡해지므로, 처음부터 SLA를 명확히 정의해야 한다.
셋째, 비용 가시성이다. S3 저장 비용은 저렴하지만 Athena 같은 서비스는 스캔 데이터 양 기준으로 과금된다. Parquet 압축과 파티셔닝을 제대로 적용하지 않으면 쿼리 비용이 예상보다 크게 증가할 수 있다.
-- Athena 예시: 파티션 필터를 명시해 스캔 범위를 제한
SELECT user_id, SUM(amount)
FROM sales_parquet
WHERE dt = '2024-06-01'
AND region = 'KR'
GROUP BY user_id;
정리
- PostgreSQL 운영 DB와 분석 워크로드를 분리하려면 Parquet + S3 기반의 LTAP 아키텍처가 실용적인 선택지다.
- 스키마 진화 문제를 사전에 고려해 Iceberg 등 테이블 포맷 도입 여부를 검토해야 한다.
- 파티셔닝과 압축을 올바르게 설계해야 쿼리 성능과 비용 효율을 동시에 확보할 수 있다.