[Database] MySQL 실습(8) - VIEW : 가상테이블 + 연습문제

우유·2026년 2월 3일

[Cloud] Database

목록 보기
11/28

8. VIEW : 가상테이블


1) VIEW를 한 문장으로

VIEW는실제 데이터를 저장하지 않는“SELECT 결과를 이름 붙여 저장한 가상 테이블”이다.


2) 왜 VIEW가 필요한가?

실무 SQL은 점점 이렇게 변한다 👇

SELECT ...
FROM orders o
JOIN customers c ON ...
JOIN payments p ON ...
WHERE ...

문제점:

  • 길다
  • 복잡하다
  • 매번 다시 써야 한다
  • 실수하기 쉽다

👉 VIEW는 이 문제를 해결한다


3) VIEW의 기본 구조

CREATE VIEW view_name AS
SELECT ...
FROM ...
WHERE ...;

4) 기본 예제: 주문 + 고객 + 결제 VIEW

4-1) VIEW 생성

CREATE VIEW v_order_summary AS
SELECT
  o.order_id,
  o.ordered_at,
  o.status        AS order_status,
  o.total_amount,

  c.customer_id,
  c.name          AS customer_name,
  c.email,

  p.payment_id,
  p.method        AS payment_method,
  p.status        AS payment_status
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id
LEFT JOIN payments p ON p.order_id = o.order_id;

4-2) VIEW 사용

SELECT *
FROM v_order_summary
WHERE order_status = 'PAID'
ORDER BY ordered_at DESC;
  • 마치 테이블처럼 사용

5) VIEW vs 테이블

구분VIEW테이블
데이터 저장
실제 공간없음있음
최신성항상 최신데이터 시점
생성 목적가독성/보안데이터 저장
성능원본 쿼리 영향인덱스 영향
  • VIEW는 “저장”이 아니라 “표현”

6) VIEW와 보안

요구사항

“운영자는 고객 이름은 보되,

이메일/전화번호는 못 보게 하자”


VIEW로 해결

CREATE VIEW v_customer_public AS
SELECT
  customer_id,
  name,
  status,
  created_at
FROM customers;

권한 부여

GRANT SELECT ON v_customer_public TO 'report_user'@'%';
REVOKE SELECT ON customers FROM 'report_user'@'%';
  • 테이블 직접 접근 차단 + 필요한 컬럼만 공개

    데이터베이스 선택이 안되어있다면 VIEW이름 앞에 데이터베이스를 명시해줘야한다.


7) VIEW와 DML (INSERT / UPDATE / DELETE)

7-1) VIEW로 조회 (항상 가능)

SELECT * FROM v_order_summary;

7-2) VIEW로 UPDATE 가능한 경우 (제한적)

가능 조건(단순 VIEW):

  • 단일 테이블 기반
  • 집계(GROUP BY) 없음
  • DISTINCT 없음
UPDATE v_customer_public
SET status = 'SUSPENDED'
WHERE customer_id = 5;
  • 내부적으로 원본 테이블 UPDATE

7-3) 대부분의 복잡한 VIEW는 읽기 전용

-- JOIN + 집계 VIEW
UPDATE v_order_summary SET total_amount = 0;

❌ 실패 (대부분 DB에서)

  • VIEW는 기본적으로 읽기 전용으로 생각

8) VIEW와 성능 (중요한 오해)

❌ “VIEW를 쓰면 성능이 좋아진다”

⭕ “VIEW는 성능을 바꾸지 않는다”

이유

  • VIEW는 쿼리 저장
  • 실행 시 원본 쿼리 그대로 수행

성능은 인덱스/쿼리에 달려 있음


9) VIEW vs 서브쿼리 vs CTE

구분VIEW서브쿼리CTE
재사용제한적
가독성
저장
권한 제어
  • 보안/공용 로직 → VIEW
  • 일회성 계산 → CTE/서브쿼리

10) VIEW 관리 명령

VIEW 조회

SHOW FULL TABLES WHERE Table_type = 'VIEW';

VIEW 정의 확인

SHOW CREATE VIEW v_order_summary;

VIEW 수정

CREATE OR REPLACE VIEW v_order_summary AS
SELECT ...

VIEW 삭제

DROP VIEW v_order_summary;

연습문제

VIEW 생성/활용 연습문제

뷰는 “생성 5문제 + 활용 5문제” 형태로 구성

Q1. (생성) 고객 기본정보 뷰 v_customers_active 를 생성하시오.
조건: status='ACTIVE' / 컬럼: customer_id, email, name, created_at

create view v_customers_active as
select customer_id, email, name, created_at
from customers
where status = 'ACTIVE';

Q2. (생성) 주문+고객 조합 뷰 v_orders_customer 를 생성하시오.
컬럼: order_id, customer_id, customer_name, status, ordered_at, total_amount

create view v_orders_customer as
select o.order_id, o.customer_id, c.name as customer_name, o.status,o.ordered_at, o.total_amount
from orders o
join customers c on c.customer_id = o.customer_id;

Q3. (생성) 주문상세 확장 뷰 v_order_items_detail 을 생성하시오.
(order_items + products)
컬럼: order_id, order_item_id, product_id, product_name, category, quantity, unit_price, line_amount

create view v_order_items_detail as
select oi.order_id, oi.order_item_id, p.product_id, p.name as product_name, p.category, oi.quantity, oi.unit_price, oi.line_amount
from order_items oi
join products p on p.product_id = oi.product_id;

Q4. (생성) 결제 포함 주문 뷰 v_paid_orders 를 생성하시오.
(orders + payments)
컬럼: order_id, status as order_status, method, paid_amount, paid_at, payment_status

create view v_paid_orders as
select p.order_id, o.status as order_status, p.method, p.paid_amount, p.paid_at, p.status as payment_status
from orders o
join payments p on o.order_id = p.order_id;

Q5. (생성) 고객별 누적 구매액 뷰 v_customer_total_spend 를 생성하시오.
(orders + customers)
컬럼: customer_id, customer_name, total_spend, order_cnt

create view v_customer_total_spend as
select c.customer_id, c.name as customer_name, sum(o.total_amount) as total_spend, count(o.order_id) as order_cnt
from customers c
left join orders o on c.customer_id = o.customer_id
group by c.customer_id, customer_name;

Q6. (활용) v_customers_active에서 가입일 최신 5명을 조회하시오.

select * 
from v_customers_active
order by created_at desc
limit 5;

Q7. (활용) v_orders_customer에서 최근 14일 주문만 조회하시오. (정렬: ordered_at DESC)

select *
from v_orders_customer
where ordered_at >= now() - interval 14 day
order by ordered_at desc;

Q8. (활용) v_order_items_detail에서 category='DEVICE' 상품의 총 판매수량을 조회하시오.
(출력: product_id, product_name, total_qty)

select product_id, product_name, sum(quantity) as total_qty
from v_order_items_detail
where category = 'DEVICE'
group by product_id, product_name;

Q9. (활용) v_paid_orders에서 결제수단별 결제합계를 조회하시오. (출력: method, total_paid)

select method, sum(paid_amount) as total_paid
from v_paid_orders
group by method;

Q10. (활용) v_customer_total_spend에서 total_spend TOP 5를 조회하시오.

select * from v_customer_total_spend
order by total_spend desc
limit 5;
profile
Front-end Developer, Cloud Engineer

0개의 댓글