ποΈ E-Commerce μ±μ μν νμ₯ κ°λ₯ν μΉ΄ν κ³ λ¦¬ μμ€ν μ€κ³
Source: Dev.to

eβcommerce μ ν리μΌμ΄μ μ ꡬμΆν λ, μΉ΄ν κ³ λ¦¬λ μ²μμ κ°λ¨ν΄ 보μ λλ€ β μ ν μκ° μ¦κ°νκ³ λΉμ¦λμ€μμ λ€μμ μꡬν λκΉμ§:
- νμ μΉ΄ν κ³ λ¦¬
- μ€μ²© λ©λ΄
- λΈλ λν¬λΌ
- SEOβμΉνμ μΈ URL
- μμ¬μ΄ μ¬μ λ ¬
μ΄ READMEλ μ€μ μμ€ν μμ μ¬μ©λλ νμ₯ κ°λ₯νκ³ νλ‘λμ βμ€λΉλ μΉ΄ν κ³ λ¦¬ μ€κ³λ₯Ό κ³Όλν μμ§λμ΄λ§ μμ΄ μ€λͺ ν©λλ€.
μΌλ°μ μΈ μ€μ
Many apps start with separate tables:
categories
sub_categories
sub_sub_categories
This breaks immediately when:
- you need more depth β λ κΉμ κ³μΈ΅μ΄ νμν λ
- the hierarchy changes β κ³μΈ΅ κ΅¬μ‘°κ° λ³κ²½λ λ
- queries become complex β μΏΌλ¦¬κ° λ³΅μ‘ν΄μ§ λ

νμ₯ κ°λ₯ν μ루μ (λ¨μΌ μΉ΄ν κ³ λ¦¬ ν μ΄λΈ)
νλμ ν μ΄λΈμ μ¬μ©νκ³ μ체 μ°Έμ‘°λ₯Ό μ€μ ν©λλ€.
CREATE TABLE categories (
id UUID PRIMARY KEY, -- or BIGINT
name VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL,
parent_id UUID REFERENCES categories(id),
level INT NOT NULL,
path VARCHAR(500) NOT NULL,
sort_order INT DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
μ΄ κ΅¬μ‘°λ 무μ ν μ€μ²©μ μ§μνλ©° μΏΌλ¦¬κ° κΉλν©λλ€.
κ³μΈ΅ ꡬ쑰 μλ λ°©μ
μμ ꡬ쑰
Electronics
βββ Mobiles
βββ Smartphones
βββ Feature Phones
μ μ₯λ λ°μ΄ν°
| id | name | parent_id | level | path | sort_order |
|---|---|---|---|---|---|
| 1 | Electronics | NULL | 0 | 1 | 1 |
| 2 | Mobiles | 1 | 1 | 1/2 | 1 |
| 3 | Smartphones | 2 | 2 | 1/2/3 | 1 |
| 4 | Feature Phones | 2 | 2 | 1/2/4 | 2 |
Source: β¦
νλ μΈλΆ μ€λͺ (μ€μ λΆλΆ)
1οΈβ£ slug β URLβμΉνμ μΈ μλ³μ
μ¬λ¬κ·Έλ URLμ μ¬μ©λλ μ½κΈ° μ¬μ΄ λ¬Έμμ΄μ λλ€.
"Smart Phones" β "smart-phones"
μ¬μ© μ:
/category/electronics/mobiles/smartphones
μ¬λ¬κ·Έκ° μ€μν μ΄μ
- SEO μΉνμ
- μμ μ μΈ URL
- ID λ ΈμΆ λ°©μ§
2οΈβ£ level β μΉ΄ν
κ³ λ¦¬ κΉμ΄
levelμ μΉ΄ν
κ³ λ¦¬κ° μΌλ§λ κΉμμ§ λνλ
λλ€.
level 0 = μ΅μμ μΉ΄ν
κ³ λ¦¬
level 1 = νμ μΉ΄ν
κ³ λ¦¬
level 2 = νμβνμ μΉ΄ν
κ³ λ¦¬
μ‘΄μ¬ μ΄μ
- ννμ΄μ§μ μ΅μμ μΉ΄ν κ³ λ¦¬λ§ νμ
- μ΅λ κΉμ΄ μ ν
- κ°λ¨ν νν°λ§
쿼리 μμ
SELECT * FROM categories WHERE level = 0;
3οΈβ£ path β μ 체 κ³μΈ΅ ꡬ쑰 (Materialized Path)
pathλ λ£¨νΈ β νμ¬ λ
ΈλκΉμ§μ μ 체 κ³λ³΄λ₯Ό μ μ₯ν©λλ€.
Electronics β Mobiles β Smartphones
path = "1/2/3"
κ°λ ₯ν μ΄μ
- μ¬κ· μμ΄ μ 체 μλΈνΈλ¦¬ μ‘°ν κ°λ₯
- λΈλ λν¬λΌμ μ½κ² μμ±
- SEO URL μμ±μ νμ©
쿼리 μμ
SELECT * FROM categories WHERE path LIKE '1/2/%';
4οΈβ£ sort_order β νμ μμ μ μ΄ (κ³μΈ΅ ꡬ쑰μ 무κ΄)
sort_orderλ UIμμ μΉ΄ν
κ³ λ¦¬κ° νμλλ μμλ₯Ό μ μ΄ν©λλ€.
- μμ κ²½μ° β μμΈ‘ λΆκ°λ₯ν μμ
- μμ κ²½μ° β λΉμ¦λμ€κ° μ μν μμ
쿼리 μμ
SELECT * FROM categories ORDER BY sort_order ASC;
μ¬μ© μ©λ
- λ€λΉκ²μ΄μ λ° μμ μ§μ
- μ£Όμ μΉ΄ν κ³ λ¦¬ κ°μ‘°
- μμ¦λ³ μ¬λ°°μ΄
μ level + pathλ₯Ό ν¨κ» μ¬μ©νλμ?
| μ¬μ© μ¬λ‘ | level | path |
|---|---|---|
| μ΅μμ νν°λ§ | β | β |
| μ΅λ κΉμ΄ κ²μ¦ | β | β |
| νμ νΈλ¦¬ 쿼리 | β | β |
| λΈλ λν¬λΌ | β | β |
| SEO URL | β | β |
κ·Έλ€μ μ€λ³΅μ΄ μλλΌ μλ‘ λ€λ₯Έ λ¬Έμ λ₯Ό ν΄κ²°ν©λλ€.
μ ν μ°κ΄μ±
μ νμ μΌλ°μ μΌλ‘ leaf categoryμ μν©λλ€.
CREATE TABLE products (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL,
price NUMERIC(10,2) NOT NULL,
category_id UUID REFERENCES categories(id)
);
μ΅μ’ κΆμ₯ μ¬ν
- β
λ¨μΌ
categoriesν μ΄λΈ - β
ꡬ쑰λ₯Ό μν
parent_id - β
κΉμ΄ λ‘μ§μ μν
level - β
λΉ λ₯Έ μ‘°νλ₯Ό μν
path - β
κΉλν URLμ μν
slug - β
UI μ μ΄λ₯Ό μν
sort_order
μ΄ μ€κ³λ μ€ννΈμ MVPμμ λκ·λͺ¨ λ§μΌνλ μ΄μ€λ‘ μ€ν€λ§ λ³κ²½ μμ΄ νμ₯λ©λλ€.
μΈν°λ·° ν μ€ μμ½
νμ₯ κ°λ₯ν μΉ΄ν κ³ λ¦¬ μμ€ν μ 무ν κΉμ΄λ₯Ό μ§μνκ³ , λΉ λ₯Έ μ½κΈ°, κΉλν URL, UIβμ μ΄ μ λ ¬μ μν΄ μ체 μ°Έμ‘° ν μ΄λΈκ³Ό 물리νλ κ²½λ‘λ₯Ό μ¬μ©ν©λλ€.