
상품은 여러가지 상태에 대한 정보가 필요하다. 설명, 특징, 사양 등에 대한 정보는 언제든지 다른 컬럼으로 대체할 수 있으며, 그 외 판매자정보, 매장 정보, 배송 정보 등 필요한 정보들이 많다. 이는 다른 테이블에 존재하는 것들과 KEY 값으로 연결되어있다.
그렇다면 설명, 특징, 사양은 어떻게 구성할 수 있을까?
일단 컬럼에 제한을 두게 되면 나중에 여러 특성들이 추가될 때마다 컬럼을 추가해야하는 문제가 생길 가능성이 크다.
그래서 생각한 결과는
설명이라는 key- value 형태의 JSON 컬럼안에 그대로 저장 할 것이다.
다만, 큰 자유도를 주지 않기 위해 형식을 지정할 예정이다. 그리고 너무 일관성이 없으면 안되니까 상품 종류에 따라서 특성에 대한 건 Domain에서 제어를 하는 것이 좋을 것 같다.
위 생각대로 DB를 구성하면 아래와 같이 잡을 수 있다.

위 내용대로 구성하기까지의 흐름은 아래와 같다.
1. 고민했던 배경
• 동적 데이터 처리:
제품마다 설명, 특징, 사양 등 정형화되지 않은 정보들이 다양하게 존재합니다.
→ JSON 컬럼을 사용하여 key-value 형태로 동적 데이터를 저장하고, 도메인에서 상품 종류에 따라 형식을 제어하도록 결정했습니다.
• 제품 상태와 판매 프로세스:
• 제품 상태:
신제품은 여러 대가 있을 수 있고, 중고 제품은 개별적으로 관리되어야 합니다.
• 판매 진행 상태:
판매 과정(주문, 결제, 배송 등)이 복잡해지면 상품 테이블에 포함시키기보다는 별도의 도메인으로 분리하는 것이 좋다는 결론에 도달했습니다.
• 판매자와 매장 정보:
같은 제품이라도 판매자나 매장이 달라질 수 있으므로, 이러한 정보는 개별 아이템(ProductItem) 수준에서 관리하는 것이 유연성을 높인다는 판단에 이르렀습니다.
2. 최종 테이블 구성
제품 카탈로그(ProductCatalog) 테이블
제품 모델의 공통 정보를 저장하는 테이블로,
제품 이름, 종류, 그리고 동적 속성(설명, 특징, 사양 등)을 JSON 컬럼으로 관리합니다.
CREATE TABLE IF NOT EXISTS product_catalog (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
product_type VARCHAR(50) NOT NULL, -- 예: guitar, drum 등
attributes JSON NOT NULL, -- 설명, 특징, 사양 등 동적 데이터
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
제품 개별 아이템(ProductItem) 테이블
실제 판매되는 개별 제품(아이템) 정보를 관리하며,
각 아이템은 제품 카탈로그와 연결되어 있고, 개별 판매자 및 매장 정보를 포함합니다.
CREATE TABLE IF NOT EXISTS product_item (
id BIGINT NOT NULL AUTO_INCREMENT,
product_catalog_id BIGINT NULL, -- 제품 카탈로그와 연결 (비어있을 수 있음 ex 특정할 수 없는 중고제품)
seller_id BIGINT NOT NULL, -- 판매자 정보 (user 테이블 FK)
store_id BIGINT NOT NULL, -- 매장 정보 (store 테이블 FK)
condition ENUM('NEW', 'USED') NOT NULL, -- 제품 상태: 신제품(NEW) / 중고(USED)
stock_quantity INT NOT NULL, -- 신제품은 여러 대, 중고는 보통 1대
PRIMARY KEY (id),
FOREIGN KEY (product_catalog_id) REFERENCES product_catalog(id)
-- 판매자와 매장에 대한 FK 제약 조건은 user, store 테이블에 따라 추가
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 설계 요약 및 장점
• 동적 속성 관리:
JSON 컬럼(attributes)을 통해 제품마다 달라지는 설명, 특징, 사양 등을 유연하게 저장할 수 있으며, 도메인 로직에서 제품 종류별로 검증 및 변환을 수행할 수 있습니다.
• 카탈로그와 개별 아이템 분리:
• ProductCatalog: 제품 모델의 공통 정보를 관리하여 조회나 검색 시 빠른 응답을 제공합니다.
• ProductItem: 실제 판매되는 개별 제품의 상태(신제품/중고), 판매자, 매장, 재고 정보를 관리함으로써 복잡한 비즈니스 요구사항(예: 중고 거래, 개별 아이템 관리 등)에 대응합니다.
• 확장성과 유지보수:
테이블을 적절히 분리함으로써, 각 도메인의 책임이 명확해지고 향후 복잡한 판매 프로세스(주문, 결제, 배송 등)를 별도의 도메인으로 분리해 관리하기 용이해집니다.
이처럼 설계하면, 다양한 제품 정보를 유연하게 처리하면서도, 성능 최적화와 유지보수 측면에서 클린 아키텍처 원칙을 잘 준수할 수 있습니다.
feat. Chat GPT...
고민한 흐름을 이렇게 정리해주니까 간편하다니...
근데 이렇게 만들고 나니까 제품상세정보는 적는 사용자마다 다 다를 수 있다는 생각이 든다. -> 그래서 product_item에도 attributes 컬럼을 추가해줬다. ProductCatalog는 기본 특성이고, ProductItem의 attributes는 사용자가 지정한 특성이다. 우선순위를 정해서 사용자가 지정한 특성이 있으면 보여주도록 하는 방식을 채택할 예정이다.
그리고 악기 특성 상 카탈로그에 들어갈 수 없는 것들도 많기 때문에 ProductItem은 반드시 Product Catalog의 값을 가질 필요는 없다.
그러나 도메인은 조금 다르게 구성했다.

바로 Product라는 Domain이 존재하는 것이다.
Product Catalog든, Product Item이든 결국 Product를 보여주기 위한 것이기 때문에 'Product'라는 도메인이 반드시 필요하고 판단된다. 그러나 ProductCatalog와 ProductItem이 각각 가지게 되는 행위도 꽤 있을 것으로 보아서 3개를 만들었다.
차후에 Product만 남길 수 도 있기는 하다.
그리고 프로젝트를 만들면서 조금 드는 생각이, 익숙한 언어를 선택할 껄 그랬다. 아무래도 시간이 한정적인데 익숙하지 않은 언어인 코틀린으로 하려다보니 조금 더 늦어지게 되는 듯 하다. 어느 순간 JAVA로 교체가 될 수 있다.
'PROJECT' 카테고리의 다른 글
week2-2: User JPA Repository 만들기 (0) | 2025.03.03 |
---|---|
week2-1: Spring Security 비활성화 및 Swagger 적용, User 테이블 만들기 (0) | 2025.02.24 |
week1-1: 요구사항 나열해보기 feat. 도메인 주도 개발 (0) | 2025.02.22 |
Week 1: 사이드프로젝트를 시작해보자 with AI (0) | 2025.02.21 |
[SpringBoot] WebSecurityConfigurerAdapter 지원 불가 (6) | 2022.04.05 |