데이터 베이스/설계 2편, 실무에서 반드시 마주치는 9가지 설계 패턴

Ch07. 동적 설계 EAV - EAV 패턴

webmaster 2026. 7. 27. 21:50

EAV는 Entity-Attribute-Value의 약자로, 데이터를 저장하는 특별한 방식이다.

 

전통적인 테이블 구조 vs EAV 구조

전통적인 테이블 구조

DROP TABLE IF EXISTS product_phone;
CREATE TABLE product_phone (
	product_id BIGINT PRIMARY KEY,
	name VARCHAR(200),
	screen_size VARCHAR(20),
	battery_capacity VARCHAR(20),
	camera_pixels VARCHAR(20),
	ram VARCHAR(20),
	storage VARCHAR(20)
);

INSERT INTO product_phone VALUES
(1, 'Galaxy S24', '6.2인치', '4000mAh', '50MP', '8GB', '256GB'),
(2, 'iPhone 15', '6.1인치', '3349mAh', '48MP', '6GB', '128GB');

쿼리 결과

  • 이 방식은 익숙하고 직관적이다.
  • 하지만 새로운 속성(예: 5G지원여부)을 추가하려면 "ALTER TABLE"로 컬럼을 추가해야 한다.

EAV 구조

EAV 방식에서는 속성 이름과 값을 열(Column)이 아니라 행(row)으로 저장한다.

-- product와 연관된 기존 테이블
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS furniture;
DROP TABLE IF EXISTS book;
DROP TABLE IF EXISTS clothing;
DROP TABLE IF EXISTS electronics;
DROP TABLE IF EXISTS product_attribute;
DROP TABLE IF EXISTS product;

-- Entity: 상품
CREATE TABLE product (
	product_id BIGINT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(200) NOT NULL,
	created_at DATETIME NOT NULL
);

-- Attribute-Value: 상품의 속성과 값
CREATE TABLE product_attribute (
	attribute_id BIGINT PRIMARY KEY AUTO_INCREMENT,
	product_id BIGINT NOT NULL,
	attr_name VARCHAR(100) NOT NULL,
	attr_value VARCHAR(500),
	FOREIGN KEY (product_id) REFERENCES product(product_id)
);

-- 데이터 입력
INSERT INTO product (product_id, name, created_at) VALUES
(1, 'Galaxy S24', NOW()),
(2, 'iPhone 15', NOW());

INSERT INTO product_attribute (product_id, attr_name, attr_value) VALUES
(1, 'screen_size', '6.2인치'),
(1, 'battery_capacity', '4000mAh'),
(1, 'camera_pixels', '50MP'),
(1, 'ram', '8GB'),
(1, 'storage', '256GB'),
(2, 'screen_size', '6.1인치'),
(2, 'battery_capacity', '3349mAh'),
(2, 'camera_pixels', '48MP'),
(2, 'ram', '6GB'),
(2, 'storage', '128GB');

 

product

SELECT * FROM product;

쿼리 결과

product_attribute

SELECT * FROM product_attribute ORDER BY product_id, attr_name;

쿼리 결과

  • 속성이 컬럼이 아니라 행으로 저장되어 있다. 이것이 EAV 패턴의 핵심이다.

EAV의 이름 이해하기

EAV는 세 가지 요소로 구성된다.

  • Entity(엔티티): 속성을 가지는 주체 (예: 상품, 사용자, 주문)
  • Attribute(속성): 엔티티가 가지는 특성의 이름 (예: screen_size, battery_capacity)
  • Value(값): 해당 속성의 실제 값 (예: 6.2인치, 4000mAh)

전통적인 테이블에서는 Attribute가 컬럼명이 되고, Value가 셀의 값이 된다. EAV에서는 Attribute와 Value 모두 데이터로 저장된다. 컬럼과 값이 모두 데이터로 저장되는 것이다.

 

EAV의 핵심 특징

EAV 패턴의 가장 중요한 특징은 스키마의 유연성이다.

 

새로운 속성 추가가 자유롭다

INSERT INTO product_attribute (product_id, attr_name, attr_value) VALUES
(1, 'supports_5g', 'Y'),
(2, 'supports_5g', 'Y');
  • 5G 지원 여부 속성을 추가하고 싶다면? 그냥 새로운 행을 INSERT하면 된다.
  • 테이블 구조 변경 없이 새로운 속성이 추가되었다.

엔티티마다 다른 속성을 가질 수 있다

INSERT INTO product_attribute (product_id, attr_name, attr_value) VALUES
(1, 's_pen_support', 'N'),
(1, 'samsung_dex', 'Y');
  • Galaxy S24에만 있는 속성을 추가할 수도 있다.
  • iPhone에는 없는 속성이지만 문제없이 저장된다.

 

Galaxy S24의 속성 조회

SELECT p.name, pa.attr_name, pa.attr_value
FROM product p
JOIN product_attribute pa ON p.product_id = pa.product_id
WHERE p.product_id = 1
ORDER BY pa.attr_name;

쿼리 결과

 

iPhone 15의 속성 조회

SELECT p.name, pa.attr_name, pa.attr_value
FROM product p
JOIN product_attribute pa ON p.product_id = pa.product_id
WHERE p.product_id = 2
ORDER BY pa.attr_name;

쿼리 결과