같은 조인 쿼리를 보고서마다 복사해 붙이다 보면 "이 긴 SELECT를 이름 하나로 부를 수 없을까?" 하는 생각이 듭니다. 데이터베이스 뷰(View)가 바로 그 해답입니다. 뷰는 쿼리에 이름을 붙여 저장해 둔 가상 테이블입니다. 실제 데이터를 따로 복제하지 않고, 조회 시점에 정의된 SELECT를 실행해 결과를 보여줍니다. 테이블처럼 보이지만 그 안엔 데이터가 아니라 쿼리가 들어 있습니다.
뷰의 핵심 개념
| 구분 | 일반 테이블 | 뷰(View) |
|---|---|---|
| 저장 대상 | 실제 데이터 행 | 쿼리 정의(SELECT문) |
| 디스크 사용 | 데이터만큼 차지 | 거의 없음(정의만) |
| 조회 시점 | 저장된 행 반환 | 매번 쿼리 실행 |
| 최신성 | 그 자체가 원본 | 항상 원본 테이블 기준 최신 |
뷰는 원본 테이블을 가리키는 창문에 가깝습니다. 원본 데이터가 바뀌면 뷰의 결과도 자동으로 바뀝니다. 별도 동기화가 필요 없다는 뜻입니다.
예시로 보는 뷰
여러 테이블을 조인해 "활성 회원의 주문 요약"을 자주 조회한다고 합시다. 매번 이 쿼리를 쓰는 대신 뷰로 묶습니다.
CREATE VIEW active_order_summary AS
SELECT u.id, u.name, COUNT(o.id) AS order_count, SUM(o.amount) AS total
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE u.status = 'active'
GROUP BY u.id, u.name;
이제 복잡한 조인 대신 한 줄로 조회합니다.
SELECT * FROM active_order_summary WHERE total > 100000;
뷰는 이렇게 세 가지 효과를 줍니다. 첫째, 복잡한 쿼리를 단순화합니다. 둘째, 민감한 컬럼을 빼고 노출해 보안 경계를 만듭니다(예: 급여 테이블에서 사번·부서만 보이는 뷰). 셋째, 여러 곳에서 같은 로직을 쓰니 일관성이 생깁니다.
뷰의 한계
뷰가 만능은 아닙니다. 조회할 때마다 내부 쿼리가 다시 실행되므로, 무거운 조인 뷰를 자주 부르면 성능이 나빠집니다. 또 집계(GROUP BY)나 조인이 들어간 뷰는 대개 INSERT/UPDATE가 불가능합니다. 어느 원본 행을 바꿔야 할지 모호하기 때문입니다.
| 상황 | 권장 |
|---|---|
| 자주 쓰는 복잡한 조회를 단순화 | 일반 뷰 |
| 무거운 집계를 반복 조회(최신성 양보 가능) | 구체화 뷰(Materialized View) |
| 컬럼 단위 접근 제어 | 뷰로 컬럼 제한 |
| 행을 직접 수정해야 함 | 원본 테이블 직접 사용 |
성능이 중요한데 데이터가 자주 안 바뀐다면, 결과를 실제로 저장해 두는 구체화 뷰를 검토합니다. 단, 원본이 바뀌어도 자동 갱신되지 않아 주기적 REFRESH가 필요합니다.
요점 정리
- 뷰는 데이터를 복제하지 않고 쿼리에 이름을 붙인 가상 테이블이다.
- 복잡한 쿼리 단순화, 컬럼 단위 보안, 로직 일관성에 강하다.
- 매 조회마다 재실행되므로 성능 주의, 집계·조인 뷰는 수정이 제한된다.
뷰를 직접 만들어 보고 일반 뷰와 구체화 뷰의 성능 차이를 실행 계획으로 확인하는 실습은 데이터베이스 트랙에서 회원가입 없이 무료로 할 수 있습니다.