• **ํŒŒํ‹ฐ์…”๋‹(Partitioning)**์€ ํ•˜๋‚˜์˜ ํฐ ํ…Œ์ด๋ธ”์„ ๊ทœ์น™์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ๋ฌผ๋ฆฌ์  ์กฐ๊ฐ(partition)์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ธฐ๋ฒ•
  • **์ƒค๋”ฉ(Sharding)**์€ ํŒŒํ‹ฐ์…”๋‹์˜ ํŠน์ˆ˜ํ•œ ํ˜•ํƒœ๋กœ, ๋‚˜๋ˆˆ ์กฐ๊ฐ(shard)์„ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฌผ๋ฆฌ์  ์„œ๋ฒ„์— ๋ถ„์‚ฐ ์ €์žฅํ•˜๋Š” ์ˆ˜ํ‰ ํ™•์žฅ(horizontal scaling) ๊ธฐ๋ฒ•
  • ํ•ต์‹ฌ ์ฐจ์ด: ํŒŒํ‹ฐ์…”๋‹์€ ํ•œ ์„œ๋ฒ„ ์•ˆ์—์„œ ํ…Œ์ด๋ธ”์„ ์ชผ๊ฐœ๋Š” ๊ฒƒ, ์ƒค๋”ฉ์€ ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๊ฑธ์ณ ๋ฐ์ดํ„ฐ๋ฅผ ์ชผ๊ฐœ๋Š” ๊ฒƒ

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

ํ•œ ๋Œ€๋กœ ๋ฒ„ํ‹ฐ๋Š” ์ „๋žต์˜ ๋ฌผ๋ฆฌ์  ํ•œ๊ณ„

API ์‘๋‹ต์ด ๋А๋ ค์ง€๋ฉด ๊ฐ€์žฅ ๋จผ์ € ๋– ์˜ค๋ฅด๋Š” ํ•ด๊ฒฐ์ฑ…์€ Vertical Scaling โ€” ์„œ๋ฒ„์˜ CPU, RAM, ๋””์Šคํฌ๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์‹ค์ œ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์„œ๋น„์Šค๋Š” ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ์ถฉ๋ถ„ํžˆ ์˜ค๋ž˜ ๋ฒ„ํ‹ด๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ „๋žต์—๋Š” ์ฒœ์žฅ์ด ์žˆ๋‹ค.

์„œ๋ฒ„ 1๋Œ€์˜ ๋ฌผ๋ฆฌ์  ํ•œ๊ณ„:
- RAM: ์ตœ๋Œ€ ์ˆ˜ TB (๋น„์šฉ ๊ธ‰์ฆ)
- ๋””์Šคํฌ I/O: SSD๋„ ์ดˆ๋‹น ์ฒ˜๋ฆฌ๋Ÿ‰์— ์ƒํ•œ์„  ์กด์žฌ
- CPU: ์ฝ”์–ด ์ˆ˜ ๋Š˜๋ ค๋„ DB ์ฟผ๋ฆฌ๋Š” ๋ณ‘๋ ฌํ™”์— ํ•œ๊ณ„
- ๋น„์šฉ: 2๋ฐฐ ์„ฑ๋Šฅ โ‰  2๋ฐฐ ๊ฐ€๊ฒฉ, ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ๋น„์‹ธ์ง

์˜ˆ๋ฅผ ๋“ค์–ด, users ํ…Œ์ด๋ธ”์ด 1์–ต ๊ฑด์ด๊ณ  SELECT * FROM users WHERE name = 'ํ™๊ธธ๋™'์„ ์‹คํ–‰ํ•œ๋‹ค๊ณ  ํ•˜์ž. ์ธ๋ฑ์Šค๊ฐ€ ์žˆ์–ด๋„ 1์–ต ๊ฑด์˜ ์ธ๋ฑ์Šค ํŠธ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•ด์•ผ ํ•œ๋‹ค. ์ด ํ…Œ์ด๋ธ”์„ ์›”๋ณ„ 12๊ฐœ ํŒŒํ‹ฐ์…˜์œผ๋กœ ๋‚˜๋ˆ„๋ฉด, WHERE created_at = '2025-01' ์กฐ๊ฑด์ด ํ•จ๊ป˜ ์žˆ์„ ๋•Œ 833๋งŒ ๊ฑด๋งŒ ํƒ์ƒ‰ํ•˜๋ฉด ๋œ๋‹ค. ์„œ๋ฒ„๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ 12๋ฐฐ ๋นจ๋ผ์ง€๋Š” ์…ˆ์ด๋‹ค.

ํ•œ ๋Œ€๋กœ ๋ชป ๋ฒ„ํ‹ฐ๋Š” ์ˆœ๊ฐ„์ด ์˜ค๋Š” ์ด์œ 

๋ฌธ์ œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์„ ํ˜•์œผ๋กœ ๊ณ„์† ์ฆ๊ฐ€ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ์˜ค๋Š˜ 1์–ต ๊ฑด์œผ๋กœ ์ถฉ๋ถ„ํ•œ ์„œ๋ฒ„๊ฐ€ ๋‚ด๋…„์—๋Š” 3์–ต ๊ฑด์„ ๊ฐ๋‹นํ•ด์•ผ ํ•œ๋‹ค. ์„œ๋ฒ„ ์—…๊ทธ๋ ˆ์ด๋“œ ๋น„์šฉ์€ ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ์ฆ๊ฐ€ํ•˜์ง€๋งŒ, ์ƒค๋”ฉ์€ ์ €๋ ดํ•œ ์„œ๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฑฐ์˜ ์„ ํ˜•์ ์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

flowchart LR
    subgraph Vertical["Vertical Scaling (ํ•œ ๋Œ€ ๊ฐ•ํ™”)"]
        direction TB
        V1["1์–ต ๊ฑด: ์›” 100๋งŒ ์›"] --> V2["3์–ต ๊ฑด: ์›” 500๋งŒ ์›"]
        V2 --> V3["10์–ต ๊ฑด: ์›” 3,000๋งŒ ์›"]
        V3 --> V4["30์–ต ๊ฑด: ???<br/>๋ฌผ๋ฆฌ์  ํ•œ๊ณ„"]
    end

    subgraph Horizontal["Horizontal Scaling (์ƒค๋”ฉ)"]
        direction TB
        H1["1์–ต ๊ฑด: ์„œ๋ฒ„ 1๋Œ€<br/>์›” 100๋งŒ ์›"] --> H2["3์–ต ๊ฑด: ์„œ๋ฒ„ 3๋Œ€<br/>์›” 300๋งŒ ์›"]
        H2 --> H3["10์–ต ๊ฑด: ์„œ๋ฒ„ 10๋Œ€<br/>์›” 1,000๋งŒ ์›"]
        H3 --> H4["30์–ต ๊ฑด: ์„œ๋ฒ„ 30๋Œ€<br/>์›” 3,000๋งŒ ์›"]
    end

์„ฑ๋Šฅ ๋ง๊ณ ๋„ ํ•œ ๋Œ€๊ฐ€ ์œ„ํ—˜ํ•œ ์ด์œ 

์„œ๋ฒ„๊ฐ€ ํ•œ ๋Œ€๋ฉด, ๊ทธ ํ•œ ๋Œ€๊ฐ€ ์ฃฝ์œผ๋ฉด ์„œ๋น„์Šค ์ „์ฒด๊ฐ€ ๋ฉˆ์ถ˜๋‹ค. ์ƒค๋”ฉ๋œ ํ™˜๊ฒฝ์—์„œ๋Š” Shard 2๊ฐ€ ์ฃฝ์–ด๋„ Shard 1, 3์˜ ์œ ์ €๋Š” ์ •์ƒ์ ์œผ๋กœ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์•ฑ์—์„œ โ€œ์ผ๋ถ€ ๊ธฐ๋Šฅ์ด ์ผ์‹œ์ ์œผ๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹คโ€๋ผ๋Š” ๋ถ€๋ถ„ ์žฅ์•  ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง€๋Š” ๊ฒƒ์ด๋‹ค.

์ •๋ฆฌ: ๋‹จ๊ณ„์  ์ ‘๊ทผ

๋Œ€๋ถ€๋ถ„์˜ ์„œ๋น„์Šค๋Š” ์ด ์ˆœ์„œ๋กœ ์ง„ํ–‰๋œ๋‹ค:

  1. ์ธ๋ฑ์Šค ์ตœ์ ํ™” โ†’ ์ฟผ๋ฆฌ ์ž์ฒด๋ฅผ ๋น ๋ฅด๊ฒŒ (๊ฐ€์žฅ ๋จผ์ €, ๊ฐ€์žฅ ์ €๋ ด)
  2. Vertical Scaling โ†’ ์„œ๋ฒ„ ์ŠคํŽ™ ์—…๊ทธ๋ ˆ์ด๋“œ (๊ฐ„๋‹จํ•˜์ง€๋งŒ ๋น„์šฉ ์ฆ๊ฐ€)
  3. ํŒŒํ‹ฐ์…”๋‹ โ†’ ํ•œ ์„œ๋ฒ„ ์•ˆ์—์„œ ํ…Œ์ด๋ธ” ๋ถ„ํ•  (์šด์˜ ๋ณต์žก๋„ ๋‚ฎ์Œ)
  4. Replication โ†’ ์ฝ๊ธฐ ์ „์šฉ ๋ณต์ œ๋ณธ์œผ๋กœ ์ฝ๊ธฐ ๋ถ€ํ•˜ ๋ถ„์‚ฐ
  5. ์ƒค๋”ฉ โ†’ ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ ๋ถ„์‚ฐ (์ตœํ›„์˜ ์ˆ˜๋‹จ, ์šด์˜ ๋ณต์žก๋„ ๋†’์Œ)

์ƒค๋”ฉ์ด ์ตœํ›„์˜ ์ˆ˜๋‹จ์ธ ์ด์œ ๋Š”, ํ•œ๋ฒˆ ๋„์ž…ํ•˜๋ฉด cross-shard JOIN, ๋ถ„์‚ฐ ํŠธ๋žœ์žญ์…˜, ๋ฐ์ดํ„ฐ ์žฌ๋ฐฐ์น˜ ๋“ฑ ์šด์˜ ๋ณต์žก๋„๊ฐ€ ๊ธ‰๊ฒฉํžˆ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. โ€œํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ ์•ˆ ํ•˜๋Š” ๊ฒŒ ์ตœ์„ ์ด์ง€๋งŒ, ํ•ด์•ผ ํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ํ•ด์•ผ ํ•˜๋Š”โ€ ๊ธฐ์ˆ ์ด๋‹ค.

AS-IS

flowchart TD
    Client[ํด๋ผ์ด์–ธํŠธ ์•ฑ] --> API[API ์„œ๋ฒ„]
    API --> DB[(๋‹จ์ผ DB ์„œ๋ฒ„<br/>users ํ…Œ์ด๋ธ”: 1์–ต ๊ฑด)]

    style DB fill:#ffcccc

    DB --> Problem["๋ฌธ์ œ:<br/>- SELECT ์ฟผ๋ฆฌ ์ˆ˜ ์ดˆ ์†Œ์š”<br/>- ๋””์Šคํฌ I/O ํฌํ™”<br/>- ๋ฐฑ์—…์— ๋ช‡ ์‹œ๊ฐ„<br/>- ์„œ๋ฒ„ ํ•œ ๋Œ€๊ฐ€ ์ฃฝ์œผ๋ฉด ์ „์ฒด ์žฅ์• "]

TO-BE (ํŒŒํ‹ฐ์…”๋‹)

flowchart TD
    Client[ํด๋ผ์ด์–ธํŠธ ์•ฑ] --> API[API ์„œ๋ฒ„]
    API --> DB[(DB ์„œ๋ฒ„ 1๋Œ€)]

    DB --> P1[users_2024<br/>3์ฒœ๋งŒ ๊ฑด]
    DB --> P2[users_2025<br/>4์ฒœ๋งŒ ๊ฑด]
    DB --> P3[users_2026<br/>3์ฒœ๋งŒ ๊ฑด]

    style DB fill:#ccffcc

    Note["ํ•œ ์„œ๋ฒ„ ์•ˆ์—์„œ ํ…Œ์ด๋ธ”๋งŒ ๋ถ„ํ• <br/>โ†’ ์ฟผ๋ฆฌ ์‹œ ํ•„์š”ํ•œ ํŒŒํ‹ฐ์…˜๋งŒ ์Šค์บ”"]

TO-BE (์ƒค๋”ฉ)

flowchart TD
    Client[ํด๋ผ์ด์–ธํŠธ ์•ฑ] --> API[API ์„œ๋ฒ„ / Router]

    API --> S1[(Shard 1<br/>์„œ๋ฒ„ A<br/>user_id 1~33M)]
    API --> S2[(Shard 2<br/>์„œ๋ฒ„ B<br/>user_id 33M~66M)]
    API --> S3[(Shard 3<br/>์„œ๋ฒ„ C<br/>user_id 66M~100M)]

    style S1 fill:#cce5ff
    style S2 fill:#cce5ff
    style S3 fill:#cce5ff

    Note["์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ ๋ถ„์‚ฐ<br/>โ†’ ์ฝ๊ธฐ/์“ฐ๊ธฐ ๋ถ€ํ•˜๋ฅผ ๋‚˜๋ˆ”"]

ํŒŒํ‹ฐ์…”๋‹ vs ์ƒค๋”ฉ: ํ•ต์‹ฌ ๋น„๊ต

๊ตฌ๋ถ„ํŒŒํ‹ฐ์…”๋‹ (Partitioning)์ƒค๋”ฉ (Sharding)
๋ฐ์ดํ„ฐ ์œ„์น˜ํ•œ ์„œ๋ฒ„ ์•ˆ์—์„œ ํ…Œ์ด๋ธ” ๋ถ„ํ• ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ ๋ถ„์‚ฐ
๋ชฉ์ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ ํ–ฅ์ƒ, ๊ด€๋ฆฌ ํŽธ์˜์ˆ˜ํ‰ ํ™•์žฅ(horizontal scaling)
๋ณต์žก๋„์ƒ๋Œ€์ ์œผ๋กœ ๋‚ฎ์Œ (DB๊ฐ€ ์•Œ์•„์„œ ๋ผ์šฐํŒ…)๋†’์Œ (๋ผ์šฐํ„ฐ, ์ƒค๋“œ ํ‚ค ๊ด€๋ฆฌ ํ•„์š”)
์žฅ์•  ์˜ํ–ฅ์„œ๋ฒ„ 1๋Œ€ ์ฃฝ์œผ๋ฉด ์ „์ฒด ์˜ํ–ฅ์ผ๋ถ€ ์ƒค๋“œ๋งŒ ์˜ํ–ฅ (๋‚˜๋จธ์ง€ ์ •์ƒ)
JOINํŒŒํ‹ฐ์…˜ ๊ฐ„ JOIN ์ž์œ ๋กœ์›€์ƒค๋“œ ๊ฐ„ JOIN ๋งค์šฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ถˆ๊ฐ€
ํ™•์žฅ ํ•œ๊ณ„์„œ๋ฒ„ 1๋Œ€์˜ ๋ฌผ๋ฆฌ์  ํ•œ๊ณ„์„œ๋ฒ„ ์ถ”๊ฐ€๋กœ ๊ฑฐ์˜ ๋ฌดํ•œ ํ™•์žฅ

ํŒŒํ‹ฐ์…”๋‹ 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•

1. Range Partitioning (๋ฒ”์œ„ ๊ธฐ๋ฐ˜)

ํŠน์ • ์ปฌ๋Ÿผ์˜ ๊ฐ’ ๋ฒ”์œ„๋กœ ๋‚˜๋ˆˆ๋‹ค. ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ์— ๊ฐ€์žฅ ์ ํ•ฉ.

-- ๋‚ ์งœ ๋ฒ”์œ„๋กœ ํŒŒํ‹ฐ์…”๋‹
CREATE TABLE orders (
    order_id    int,
    order_date  date,
    amount      int
) PARTITION BY RANGE (order_date);
 
-- 2025๋…„ 1์›” ํŒŒํ‹ฐ์…˜
CREATE TABLE orders_2025_01 PARTITION OF orders
    FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');
 
-- 2025๋…„ 2์›” ํŒŒํ‹ฐ์…˜
CREATE TABLE orders_2025_02 PARTITION OF orders
    FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');

ํด๋ผ์ด์–ธํŠธ ๊ด€์ ์—์„œ ๋ณด๋ฉด: SELECT * FROM orders WHERE order_date = '2025-01-15' ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด๋ฉด, DB๊ฐ€ ์ž๋™์œผ๋กœ orders_2025_01 ํŒŒํ‹ฐ์…˜๋งŒ ์Šค์บ”ํ•œ๋‹ค. ๋‚˜๋จธ์ง€ 11๊ฐœ์›”์น˜ ๋ฐ์ดํ„ฐ๋Š” ์•„์˜ˆ ๋ณด์ง€ ์•Š๋Š”๋‹ค. ์ด๊ฒƒ์„ Partition Pruning์ด๋ผ ํ•œ๋‹ค.

2. List Partitioning (๋ชฉ๋ก ๊ธฐ๋ฐ˜)

ํŠน์ • ์ปฌ๋Ÿผ์˜ ๊ฐ’ ๋ชฉ๋ก์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค. ์ง€์—ญ, ์นดํ…Œ๊ณ ๋ฆฌ ๋“ฑ ์ด์‚ฐ์ ์ธ ๊ฐ’์— ์ ํ•ฉ.

CREATE TABLE users (
    user_id  int,
    country  text,
    name     text
) PARTITION BY LIST (country);
 
CREATE TABLE users_kr PARTITION OF users
    FOR VALUES IN ('KR');
CREATE TABLE users_us PARTITION OF users
    FOR VALUES IN ('US');
CREATE TABLE users_jp PARTITION OF users
    FOR VALUES IN ('JP');

3. Hash Partitioning (ํ•ด์‹œ ๊ธฐ๋ฐ˜)

์ปฌ๋Ÿผ ๊ฐ’์— ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜์—ฌ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„๋ฐฐํ•œ๋‹ค. ๋ฒ”์œ„๋‚˜ ๋ชฉ๋ก์œผ๋กœ ๋‚˜๋ˆ„๊ธฐ ์–ด๋ ค์šธ ๋•Œ ์‚ฌ์šฉ.

CREATE TABLE sessions (
    session_id  int,
    user_id     int,
    data        text
) PARTITION BY HASH (user_id);
 
-- 4๊ฐœ๋กœ ๊ท ๋“ฑ ๋ถ„ํ•  (modulus 4, remainder 0~3)
CREATE TABLE sessions_p0 PARTITION OF sessions
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE sessions_p1 PARTITION OF sessions
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE sessions_p2 PARTITION OF sessions
    FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE sessions_p3 PARTITION OF sessions
    FOR VALUES WITH (MODULUS 4, REMAINDER 3);

์ƒค๋”ฉ 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•

1. Range-Based Sharding (๋ฒ”์œ„ ๊ธฐ๋ฐ˜)

ํŒŒํ‹ฐ์…”๋‹์˜ Range์™€ ๊ฐ™์€ ์›๋ฆฌ์ด์ง€๋งŒ, ๊ฐ ๋ฒ”์œ„๊ฐ€ ๋‹ค๋ฅธ ์„œ๋ฒ„์— ์ €์žฅ๋œ๋‹ค.

Shard 1 (์„œ๋ฒ„ A): user_id 1 ~ 1,000,000
Shard 2 (์„œ๋ฒ„ B): user_id 1,000,001 ~ 2,000,000
Shard 3 (์„œ๋ฒ„ C): user_id 2,000,001 ~ 3,000,000

๋‹จ์ : ์‹ ๊ทœ ๊ฐ€์ž…์ž๊ฐ€ ๊ณ„์† Shard 3์—๋งŒ ๋ชฐ๋ฆฌ๋Š” ํ•ซ์ŠคํŒŸ(hotspot) ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ.

2. Hash-Based Sharding (ํ•ด์‹œ ๊ธฐ๋ฐ˜)

Shard Key์— ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜์—ฌ ์–ด๋А ์„œ๋ฒ„์— ์ €์žฅํ• ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.

shard_number = hash(user_id) % ์„œ๋ฒ„_์ˆ˜

์˜ˆ: hash(12345) % 3 = 1  โ†’ Shard 2 (์„œ๋ฒ„ B)
    hash(67890) % 3 = 0  โ†’ Shard 1 (์„œ๋ฒ„ A)

์žฅ์ : ๋ฐ์ดํ„ฐ๊ฐ€ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„์‚ฐ๋จ. ๋‹จ์ : ์„œ๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ(๋ฆฌ์ƒค๋”ฉ) ๋Œ€๋ถ€๋ถ„์˜ ๋ฐ์ดํ„ฐ ์žฌ๋ฐฐ์น˜ ํ•„์š”.

3. Directory-Based Sharding (๋””๋ ‰ํ† ๋ฆฌ ๊ธฐ๋ฐ˜)

๋ณ„๋„์˜ lookup table๋กœ โ€œ์ด ๋ฐ์ดํ„ฐ๋Š” ์–ด๋А ์„œ๋ฒ„์—?โ€๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

Lookup Table:
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ user_id  โ”‚ shard   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 12345    โ”‚ Shard 1 โ”‚
โ”‚ 67890    โ”‚ Shard 2 โ”‚
โ”‚ ...      โ”‚ ...     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๊ฐ€์žฅ ์œ ์—ฐํ•˜์ง€๋งŒ, lookup table ์ž์ฒด๊ฐ€ ๋‹จ์ผ ์žฅ์•  ์ง€์ (SPOF)์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

Shard Key ์„ ํƒ์ด ์ค‘์š”ํ•œ ์ด์œ 

Shard Key๋Š” โ€œ์–ด๋–ค ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ๋‚˜๋ˆŒ ๊ฒƒ์ธ๊ฐ€โ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์ปฌ๋Ÿผ์ด๋‹ค. ์ž˜๋ชป ๊ณ ๋ฅด๋ฉด ํŠน์ • ์„œ๋ฒ„์— ๋ถ€ํ•˜๊ฐ€ ๋ชฐ๋ฆฌ๋Š” ํ•ซ์ŠคํŒŸ์ด ๋ฐœ์ƒํ•œ๋‹ค.

์ข‹์€ Shard Key์˜ ์กฐ๊ฑด 3๊ฐ€์ง€:

์กฐ๊ฑด์˜๋ฏธ๋‚˜์œ ์˜ˆ
๋†’์€ Cardinality๊ฐ€๋Šฅํ•œ ๊ฐ’์˜ ์ข…๋ฅ˜๊ฐ€ ๋งŽ์•„์•ผ ํ•จgender (M/F ๋‘ ๊ฐ€์ง€๋ฟ)
๊ท ๋“ฑํ•œ Frequency๊ฐ ๊ฐ’์˜ ์ถœํ˜„ ๋นˆ๋„๊ฐ€ ๋น„์Šทํ•ด์•ผ ํ•จcountry (ํ•œ๊ตญ ์œ ์ € 90%๋ฉด ํ•œ ์ƒค๋“œ์— ๋ชฐ๋ฆผ)
๋น„๋‹จ์กฐ์  ๋ณ€ํ™”์‹œ๊ฐ„์— ๋”ฐ๋ผ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋ฉด ์•ˆ ๋จcreated_at (์ตœ์‹  ์ƒค๋“œ๋งŒ ๋œจ๊ฑฐ์›Œ์ง)

ํด๋ผ์ด์–ธํŠธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฒด๊ฐํ•˜๋Š” ์˜ํ–ฅ

์ƒค๋”ฉ๋œ DB๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์„œ๋น„์Šค์˜ API๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์•Œ์•„์•ผ ํ•  ์ :

1. ์ •๋ ฌ/ํŽ˜์ด์ง€๋„ค์ด์…˜์ด ๋А๋ ค์งˆ ์ˆ˜ ์žˆ์Œ

ํด๋ผ์ด์–ธํŠธ: GET /users?sort=created_at&page=3

โ†’ ์„œ๋ฒ„๋Š” ๋ชจ๋“  ์ƒค๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ํ•ฉ์นœ ํ›„ ์ •๋ ฌํ•ด์•ผ ํ•จ
โ†’ ๋‹จ์ผ DB๋ณด๋‹ค ์‘๋‹ต์ด ๋А๋ฆด ์ˆ˜ ์žˆ์Œ

2. Cross-Shard ์กฐํšŒ์˜ ์ œ์•ฝ

ํด๋ผ์ด์–ธํŠธ: GET /users/123/friends (user 123์˜ ์นœ๊ตฌ ๋ชฉ๋ก)

โ†’ user 123์€ Shard 1์— ์žˆ์ง€๋งŒ
โ†’ ์นœ๊ตฌ๋“ค์€ Shard 1, 2, 3์— ํฉ์–ด์ ธ ์žˆ์Œ
โ†’ ์—ฌ๋Ÿฌ ์ƒค๋“œ๋ฅผ ๋™์‹œ์— ์กฐํšŒํ•ด์•ผ ํ•จ (fan-out query)
โ†’ ์‘๋‹ต ์ง€์—ฐ ๊ฐ€๋Šฅ

3. ์ผ๊ด€์„ฑ(Consistency) ์ด์Šˆ

ํด๋ผ์ด์–ธํŠธ: POST /transfer (A โ†’ B ์†ก๊ธˆ)

โ†’ A์˜ ์ž”์•ก์€ Shard 1, B์˜ ์ž”์•ก์€ Shard 2
โ†’ ๋‘ ์„œ๋ฒ„์— ๊ฑธ์นœ ํŠธ๋žœ์žญ์…˜์ด ํ•„์š” (๋ถ„์‚ฐ ํŠธ๋žœ์žญ์…˜)
โ†’ ์‹คํŒจ ์‹œ ๋ถ€๋ถ„๋งŒ ๋ฐ˜์˜๋  ์ˆ˜ ์žˆ์Œ
โ†’ ํด๋ผ์ด์–ธํŠธ๋Š” "์ฒ˜๋ฆฌ ์ค‘" ์ƒํƒœ๋ฅผ ๋‹ค๋ฃฐ ์ค€๋น„ ํ•„์š”

4. ํŠน์ • API๋งŒ ๋А๋ฆฐ ์ด์œ 

GET /user/123          โ†’ Shard Key๋กœ ๋ฐ”๋กœ ์ฐพ์Œ โ†’ ๋น ๋ฆ„ (ms)
GET /users?name=ํ™๊ธธ๋™  โ†’ ๋ชจ๋“  ์ƒค๋“œ ์Šค์บ” ํ•„์š” โ†’ ๋А๋ฆผ (์ดˆ)

Shard Key๊ฐ€ ์•„๋‹Œ ์ปฌ๋Ÿผ์œผ๋กœ ๊ฒ€์ƒ‰ํ•˜๋ฉด, ๋ชจ๋“  ์ƒค๋“œ๋ฅผ ๋‹ค ๋’ค์ ธ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Scatter-Gather ํŒจํ„ด์ด ๋˜์–ด ๋А๋ ค์ง„๋‹ค.

์–ธ์ œ ํŒŒํ‹ฐ์…”๋‹? ์–ธ์ œ ์ƒค๋”ฉ?

flowchart TD
    A{ํ…Œ์ด๋ธ”์ด ๋„ˆ๋ฌด ํฐ๊ฐ€?} -->|Yes| B{ํ•œ ์„œ๋ฒ„๋กœ ๊ฐ๋‹น ๊ฐ€๋Šฅ?}
    A -->|No| Z[ํ˜„์žฌ ๊ตฌ์กฐ ์œ ์ง€]
    B -->|Yes| C[ํŒŒํ‹ฐ์…”๋‹์œผ๋กœ ์ถฉ๋ถ„]
    B -->|No| D{์ฝ๊ธฐ/์“ฐ๊ธฐ ๋ถ€ํ•˜<br/>๋ถ„์‚ฐ์ด ํ•„์š”ํ•œ๊ฐ€?}
    D -->|Yes| E[์ƒค๋”ฉ ๋„์ž…]
    D -->|No| F[Replication์œผ๋กœ<br/>์ฝ๊ธฐ ๋ถ„์‚ฐ]

์ผ๋ฐ˜์ ์œผ๋กœ ํŒŒํ‹ฐ์…”๋‹์„ ๋จผ์ € ์ ์šฉํ•˜๊ณ , ๊ทธ๋ž˜๋„ ํ•œ๊ณ„์— ๋„๋‹ฌํ•˜๋ฉด ์ƒค๋”ฉ์œผ๋กœ ํ™•์žฅํ•œ๋‹ค. ์ƒค๋”ฉ์€ ์šด์˜ ๋ณต์žก๋„๊ฐ€ ํฌ๊ฒŒ ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ ์ตœํ›„์˜ ์ˆ˜๋‹จ์— ๊ฐ€๊น๋‹ค.

์ฐธ๊ณ  ๋ฌธ์„œ