가끔 SQL 쿼리가 너무 길고 복잡해지고, 계속 반복해서 쓰게 될 때가 있어. 예를 들어, 학생들의 평균 점수랑 수강 과목 수로 리포트를 만들 때, 똑같은 서브쿼리를 다섯 번이나 써야 할 수도 있지. 이런 거 계속 복붙하지 말고, 뷰 — 즉 VIEW를 쓰는 게 훨씬 좋아.
VIEW는 “저장된 쿼리” 같은 거야. 이름을 붙여서 테이블처럼 쓸 수 있어. 실제 데이터를 저장하는 게 아니라 쿼리 구조만 저장하는 거지.
이게 특히 유용한 경우는 이런 때야:
- SQL 코드를 더 읽기 쉽게 만들고 싶을 때;
- 복잡한 쿼리를 여러 번 재사용하고 싶을 때;
- 사용자한테 기술적인 디테일을 숨기고 싶을 때;
- 접근 권한을 나누고 싶을 때 (필요한 데이터만 보여주기).
VIEW는 어떻게 동작해?
뷰를 만든다는 건 SELECT 쿼리로 가짜 테이블을 만드는 거야. 예를 들어:
CREATE VIEW student_avg_grades AS
SELECT
s.student_id,
s.name,
AVG(g.grade) AS avg_grade
FROM
students s
JOIN
grades g ON s.student_id = g.student_id
GROUP BY
s.student_id, s.name;
이제 student_avg_grades를 그냥 테이블처럼 쓸 수 있어:
SELECT * FROM student_avg_grades WHERE avg_grade > 4.5;
대학교 예시
학생, 수강 과목, 점수를 자주 분석한다고 해보자. 각 학생별로 요약 리포트를 만들어야 한다고 치자:
- 이름,
- 수강 과목 수,
- 평균 점수.
이걸 한 번에 다 하려고 하면 쿼리가 엄청 길고 읽기 힘들어져. 그래서 단계별로 쪼개서 먼저 뷰(VIEW) 두 개 만들고, 그걸 합치는 게 훨씬 편해.
students 테이블
| id | name |
|---|---|
| 1 | Alex Lin |
| 2 | Anna Song |
| 3 | Maria Chi |
| 4 | Dan Seth |
enrollments 테이블
| student_id | course_id | grade |
|---|---|---|
| 1 | 1 | 90 |
| 1 | 2 | 85 |
| 2 | 2 | 88 |
| 2 | 3 | 91 |
| 3 | 1 | 75 |
| 3 | 3 | NULL |
- 뷰: 수강 과목 수
이 뷰는 각 학생이 몇 과목을 듣는지 세어줘:
CREATE VIEW student_course_count AS
SELECT
student_id,
COUNT(*) AS course_count
FROM
enrollments
GROUP BY student_id;
결과:
| name |
|---|
| Alex Lin |
| Anna Song |
| Maria Chi |
- 뷰: 평균 점수 이건 학생별 평균 점수야 (점수가 없으면 NULL이고, 평균에 영향 안 줘):
CREATE VIEW student_avg_grade AS
SELECT
student_id,
AVG(grade) AS avg_grade
FROM
enrollments
WHERE grade IS NOT NULL
GROUP BY student_id;
- 이
VIEW들 사용하기
SELECT
s.name,
c.course_count,
a.avg_grade
FROM
students s
LEFT JOIN student_course_count c ON s.student_id = c.student_id
LEFT JOIN student_avg_grade a ON s.student_id = a.student_id;
이제 쿼리가 깔끔하고 이해하기 쉬워졌지. 그리고 유지보수도 훨씬 쉬워.
VIEW의 업데이트 가능성
뷰는 보통 데이터를 저장하지 않아 — 그냥 쿼리 “껍데기”일 뿐이야. 그래도 데이터를 업데이트할 때도 쓸 수 있는데, VIEW가 몇 가지 조건을 만족해야 해 (예를 들어 JOIN, GROUP BY, 집계 함수, 서브쿼리 없이).
업데이트 가능한 뷰 예시:
CREATE VIEW active_students AS
SELECT * FROM students WHERE active = true;
이제 이렇게 할 수 있어:
UPDATE active_students SET name = '이반 페트로프' WHERE student_id = 2;
근데 VIEW가 복잡하면 (예: JOIN이나 GROUP BY가 있으면) 읽기 전용이 돼. 업데이트하려면 INSTEAD OF 트리거를 써야 하는데, 이건 좀 더 고급 내용이야.
VIEW를 삭제하거나 수정하는 방법
삭제:
DROP VIEW student_avg_grade;
수정:
CREATE OR REPLACE VIEW student_avg_grade AS
SELECT student_id, ROUND(AVG(grade), 2) AS avg_grade
FROM grades
GROUP BY student_id;
예시: VIEW가 특히 유용한 경우
- 리포트 만들기
하나의 VIEW에 하나의 로직만! report_enrollments_by_month, report_payments_by_year 이런 식으로 만들 수 있어.
- 접근 권한 나누기
개인정보 없이 제한된 데이터만 보여주는 VIEW를 만들어서, 그 뷰에만 접근 권한을 주면 돼.
- 재사용
서브쿼리를 복붙하지 말고, VIEW로 이름 붙여서 쓰자.
팁
- 이름을 알아보기 쉽게 짓자:
view_avg_scores_by_group,active_users_view이런 식이면 읽기 편해. VIEW안에 또VIEW안에 또VIEW이런 식으로 체인 만들지 마 — 이해하기도 어렵고 디버깅도 힘들어져.- 성능도 신경 써야 해: PostgreSQL은
VIEW를 쿼리할 때마다 다시 계산해.MATERIALIZED VIEW가 아니면 말이야.
VIEW는 PostgreSQL에서 제일 쉽고 편한 도구 중 하나야. 새로운 걸 배울 필요도 없고, 그냥 이렇게 생각하면 돼: “이 쿼리 저장해두고 테이블처럼 쓰면 안 될까?” 쿼리가 너무 길어지면, 거의 무조건 VIEW로 만드는 게 좋아.
GO TO FULL VERSION