PostgreSQL을 사용하다 보면 복잡한 쿼리를 반복해서 사용할 일이 많아집니다. 이때 뷰(View)나 물리화 뷰(Materialized View)를 활용하면 쿼리를 깔끔하게 정리하고 재사용할 수 있습니다. 이번 글에서는 PostgreSQL에서 View와 Materialized View의 차이점, 장단점, 그리고 실무 적용 방법에 대해 정리해보았습니다.
View란?
View(뷰)는 하나 이상의 테이블이나 다른 뷰에 대한 쿼리를 저장해 놓은 가상의 테이블입니다. 데이터를 직접 저장하지 않고, 정의된 SQL 쿼리 결과를 보여주는 역할을 합니다.
View의 장점
- 복잡한 쿼리 재사용: 자주 사용하는 조인, 조건 등을 미리 정의해서 깔끔하게 쓸 수 있습니다.
- 보안 강화: 민감한 컬럼을 제외한 일부만 노출하는 뷰를 만들어 사용 권한을 제한할 수 있습니다.
- 추상화 제공: 테이블 구조를 숨기고 사용자는 뷰를 통해 원하는 정보만 쉽게 조회할 수 있습니다.
- 유지보수 용이: 쿼리 로직 변경 시 뷰 정의만 수정하면 됩니다.
View의 단점
- 성능 이슈: 데이터를 매번 원본 테이블에서 조회하기 때문에, 특히 중첩된 뷰에서는 성능이 떨어질 수 있습니다.
- 쓰기 제한: 대부분의 뷰는
INSERT
,UPDATE
,DELETE
가 불가능합니다. - 디버깅 어려움: 중첩된 뷰가 많아질수록 쿼리 추적이 어려워질 수 있습니다.
Materialized View란?
**Materialized View(물리화 뷰)**는 View와 비슷하지만, 쿼리 결과를 디스크에 저장한다는 점에서 다릅니다. 즉, 매번 쿼리를 실행하지 않아도 되므로 성능상 이점이 큽니다.
Materialized View 생성 방법
CREATE MATERIALIZED VIEW 뷰이름 AS
SELECT ...
FROM ...
WHERE ...
WITH DATA;
WITH DATA
: 쿼리 실행 결과를 즉시 저장 (기본값)WITH NO DATA
: 쿼리 구조만 만들고 데이터는 저장하지 않음
조회
SELECT * FROM 뷰이름;
일반 테이블처럼 조회 가능합니다.
갱신(REFRESH)
REFRESH MATERIALIZED VIEW 뷰이름;
- 원본 테이블이 변경되더라도 Materialized View는 자동으로 갱신되지 않기 때문에 수동으로
REFRESH
명령을 실행해야 합니다.
동시에 읽기 허용하며 갱신하려면?
REFRESH MATERIALIZED VIEW CONCURRENTLY 뷰이름;
단, 이 경우 뷰에 인덱스가 있어야 하며, WITH DATA
로 생성된 뷰여야 합니다.
인덱스 생성
CREATE INDEX idx_name ON 뷰이름(컬럼);
Materialized View에도 인덱스를 생성할 수 있어 성능 최적화에 도움이 됩니다.
일반 View vs Materialized View 비교
항목 | 일반 View | Materialized View |
---|---|---|
데이터 저장 | 없음 | 있음 |
성능 | 느릴 수 있음 | 빠름 |
실시간성 | 최신 | 갱신 필요 |
쓰기 가능성 | 제한적 | 불가 |
인덱스 생성 | 불가 | 가능 |
갱신 방식 | 자동 | 수동 (REFRESH 필요) |
실무에서의 활용 팁
- 실시간 데이터가 필요한 경우: 일반 View 사용
- 데이터를 자주 조회하지만 변경이 적은 경우: Materialized View로 캐싱처럼 활용
- 집계, 조인, 필터가 많은 쿼리: Materialized View로 성능 개선
- Materialized View 자동 갱신: PostgreSQL에는 자동 갱신 기능이 없으므로,
pg_cron
,pgAgent
, 리눅스cron
등을 통해 주기적으로REFRESH
명령 실행
마무리
PostgreSQL의 View와 Materialized View는 각각의 특성과 장단점이 뚜렷합니다. 단순히 쿼리를 정리하고 재사용하는 데에는 일반 View가 적합하지만, 반복적인 집계나 성능 개선이 필요한 상황이라면 Materialized View를 고려하는 것이 좋습니다. 실제 프로젝트에서는 두 가지를 적절히 병행하여 사용하는 것이 가장 이상적입니다.
반응형