본문 바로가기
dev/db

MySQL - View

by wlrn566 2026. 4. 20.

프로젝트의 백엔드 기능 구현 중 꽤 많은 테이블을 JOIN해서 데이터를 가져와야 하는 일이 있었다.

NestJS를 이용하지만, ORM을 사용하지 않고 직접 쿼리를 작성하고 있는데, 이 쿼리문이 너무 크고 가독성이 떨어짐에 따라 유지보수 차원에서도 힘들다고 생각이 되었다.

 

해당 테이블 구조를 반정규화를 하려고 했지만, 기간이 제한적이고 데이터가 꽤 많아 리스크가 컸다.

그래서 View를 사용해 보았다.


View?

여러 테이블을 기반으로 만들어지는 가상 테이블 이다. 데이터를 물리적으로 저장하고 있지 않고, 조회용으로 많이 쓰인다.

해당 View를 조회하면, 미리 정의된 SELECT 문을 실행하여 결과를 보여준다.

즉, 쿼리 텍스트만 저장되고 사용자가 조회를 하면 해당 쿼리가 실행되는 것이다.

 

장점

  • 여러 테이블을 JOIN하는 쿼리문을 단순하게 할 수 있다.
    • JOIN을 여러개 하는 쿼리가 있다면 View를 사용했을때, SELECT * FROM view_test 라고 바로 사용가능하다.
  • 한번 View 쿼리를 만들어 놓으면 다른 쿼리문에서 재사용이 가능하다.
  • 필요한 데이터만 추출해 만들 수 있으므로, 민감한 데이터는 숨길 수 있다. 즉, 노출시켜야 하는 데이터만 모아두는 테이블로 사용할 수 있다.

단점

  • View 자체는 인덱스를 가질 수 없다. 즉, 호출될 때마다 원본 테이블에서 데이터를 새로 가져오므로 조회 성능이 떨어질 수도 있다.
    • 인덱스를 걸면 DB는 해당 데이터를 물리적으로 저장해 둔다. 하지만 View는 물리적으로 존재하지 않는 가상 테이블이기 때문에 CREATE INDEX 같은 명령어를 직접 사용할 수 없다.
    • 만약 테이블을 5개를 가지고 View를 만든다면, 매번 View를 조회할 때 해당 테이블들을 항상 새롭게 조회한다. 하지만 원본 테이블의 인덱스 컬럼을 잘 사용한다면 빠르게 조회가 가능하다.
  • 집계 함수(SUM, COUNT 등) 가 들어간 View는 데이터 수정이 불가능 하다.
    • 일반적으로 View는 "읽기 전용 (Read-Only)"으로 사용한다. 데이터 무결성과 관리 측면에서 안전하다.
    • 특정 조건이 만족 된다면, 수정이 가능하기도 한다.

 


View 생성

CREATE VIEW v_order AS
SELECT 
    o.id AS order_id,
    u.nickname AS customer_name,
    p.product_name,
    o.order_date,
    d.status AS delivery_status,
    (o.quantity * p.price) AS total_price
FROM orders AS o
JOIN users AS u ON o.user_id = u.id
JOIN products AS p ON o.product_id = p.id
JOIN delivery AS d ON o.id = d.order_id;

 

여기서 total_price에 대해 설명이 필요하다.

만약 집계함수 (SUM, COUUNT, AVG 등)이 사용되었다면 원본 테이블과의 1:1 매칭이 깨지므로, "읽기 전용"이 되버린다.

하지만 total_price 같이 행 하나마다 수행되는 계산 (*, /, + 등) 은 개별 행마다 계산이 되므로 가능하다. 1:1이 여전하므로 수정도 가능할 것이다.


View 조회

SELECT * FROM v_order;

 

이 단순한 쿼리문 안에 여러 테이블들이 JOIN되어 있다.

만약 WHERE 절을 추가 했을 경우, 원본 테이블에서 인덱스가 걸린 컬럼이라면 조회가 빠르다.


View 삭제

DROP VIEW IF EXISTS v_order;

 

해당 View가 존재할 경우에만 삭제한다.

View는 언제든지 자유롭게 만들었다가 삭제를 하더라도 원본 테이블의 데이터는 유지된다.

View가 삭제되었지만 만약 백엔드에서 해당 View를 사용해서 조회를 하고 있다면 에러가 나므로 철저히 확인해야 한다.


 

View를 사용하게 되니, 거대했던 쿼리문도 매우 간단해졌다.

하지만 View를 만들기 위해 JOIN이 잘못되었을 경우 (데이터가 많아짐 등) 정확하게 확인이 어려웠다.

그래서 항상 View를 만들기 전에, EXPLAIN 또는 SELECT COUNT등을 직접 날려서 확인하는 습관을 가져야겠다..