๋ณธ ๋ฌธ์๋ ์ค์ ์ฑ๋ฅ ์ธก์ ์ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ต์ ํ์ ์บ์ฑ ์ ๋ต์ ํจ๊ณผ๋ฅผ ๊ฒ์ฆํ๋ ์คํ์ ์ํ ๋์์ธ ๋ฌธ์์ ๋๋ค.
- ๋ฌธ์ ๋ฐฐ๊ฒฝ: URL ๋จ์ถ๊ธฐ์ ํต์ฌ ๋ณ๋ชฉ์ ๋จ์ถ ์ฝ๋ โ ์๋ณธ URL ์กฐํ ์ฑ๋ฅ์ ๋๋ค.
- ์คํ ๋ชฉํ: ๋์ผํ ์ํฌ๋ก๋์์ ์ธ๋ฑ์ค์ ์บ์ฑ์ ์ฑ๋ฅ ๊ฐ์ ํจ๊ณผ๋ฅผ k6๋ก ์ธก์
- ํ์ฌ ๊ฐ์ ํธ๋ํฝ: 1,000 DAU ร 10ํ/์ผ โ 10,000/์ผ โ ํ๊ท ~0.12 RPS (์คํ์ฉ ์๊ท๋ชจ)
- ์ค์ฝํ: ๋จ์ถ ์ฝ๋ ์กฐํ ๊ฒฝ๋ก ์ต์ ํ (DB ์ธ๋ฑ์ค + Redis ์บ์)
- ๋น์ค์ฝํ: ๋จ์ถ URL ์์ฑ ์๊ณ ๋ฆฌ์ฆ, CDN/์ฃ์ง ์ต์ ํ
- Goals
- ๊ฐ ์ต์ ํ ๋จ๊ณ๋ณ ์๋ต ์๊ฐ ์ธก์ (p95, p99)
- ์บ์ ํํธ์จ 90%+ ๋ฌ์ฑ (์บ์ ๋จ๊ณ)
- ๋จ๊ณ๋ณ ์ฑ๋ฅ ๊ฐ์ ์จ ์ ๋์ ์ธก์
- Non-Goals
- ํ๋ก๋์ ๋ ๋ฒจ ํธ๋ํฝ ์ฒ๋ฆฌ (60๋ง RPS)
- CDN/์ฃ์ง ์ปดํจํ ๊ตฌํ
- ๊ณ ๊ฐ์ฉ์ฑ/์ฅ์ ๋ณต๊ตฌ
- ์ฌ์ฉ์๋
http://localhost:8080/api/v1/urls/{shortUrl}๋ก ์ ์ - Phase 1: Spring Boot โ PostgreSQL (์ธ๋ฑ์ค ์์)
- Phase 2: Spring Boot โ PostgreSQL (์ธ๋ฑ์ค ์์)
- Phase 3: Spring Boot โ Redis โ PostgreSQL (์บ์ + ์ธ๋ฑ์ค)
- GET
/api/v1/urls/{shortUrl}: ์ฝ๋๋ก ๋ฆฌ๋ค์ด๋ ํธ ์ํ (302) - POST
/api/v1/urls: ์๋ณธ URL โ ๋จ์ถ ์ฝ๋ ์์ฑ
- GET
/api/v1/urls/baseline/{shortUrl}: Phase 1 - DB ์ง์ ์กฐํ (์ธ๋ฑ์ค ์์) - GET
/api/v1/urls/indexed/{shortUrl}: Phase 2 - ์ธ๋ฑ์ค ํ์ฉ ์กฐํ - GET
/api/v1/urls/cached/{shortUrl}: Phase 3 - Redis ์บ์ ์ฐ์ ์กฐํ
-
url_mapping_baseline: Phase 1์ฉ (์ธ๋ฑ์ค ์์)id(PK, Auto Increment)short_url(varchar, unique) โ ์ธ๋ฑ์ค ์์ (Full Table Scan)original_url(varchar, 2000์)
-
url_mapping_indexed: Phase 2์ฉ (์ธ๋ฑ์ค ์์)id(PK, Auto Increment)short_url(varchar, unique) โ B-tree ์ธ๋ฑ์ค ์์ (Index Scan)original_url(varchar, 2000์)- ์ธ๋ฑ์ค:
idx_short_url_indexedonshort_url
- URL ์์ฑ ์: 2๊ฐ ํ ์ด๋ธ์ ๋์ ์ ์ฅ (๋์ผํ shortUrl, originalUrl)
- Phase๋ณ ์กฐํ: ๊ฐ๊ฐ ๋ค๋ฅธ ํ ์ด๋ธ์์ ์กฐํํ์ฌ ์ฑ๋ฅ ์ฐจ์ด ์ธก์
- ์บ์ ๋ ์ด์ด: Phase 3์์ Redis ์บ์ ์ถ๊ฐ (ํ ์ด๋ธ์ indexed ์ฌ์ฉ)
- ์ํคํ ์ฒ: Spring Boot โ PostgreSQL
- ํน์ง: ๊ฐ์ฅ ๋จ์ํ ๊ตฌํ, DB ์ง์ ์กฐํ
- ์์ ์ฑ๋ฅ: 50-200ms per request (Full table scan)
- ๋ชฉ์ : ๊ธฐ์ค ์ฑ๋ฅ ์ธก์
- ์ํคํ ์ฒ: Spring Boot โ PostgreSQL (with index)
- ์ต์ ํ:
short_url์ปฌ๋ผ์ B-tree ์ธ๋ฑ์ค ์ถ๊ฐ - ํน์ง: O(log n) ์กฐํ ์๊ฐ
- ์์ ์ฑ๋ฅ: 10-50ms per request (5-10x ๊ฐ์ )
- ๋ชฉ์ : ์ธ๋ฑ์ฑ ํจ๊ณผ ๊ฒ์ฆ
- ์ํคํ ์ฒ: Spring Boot โ Redis โ PostgreSQL
- ์บ์ ์ ๋ต:
- ํค ํฌ๋งท:
url:{shortCode} - TTL: 15๋ถ (๋จ์ผ ์ ์ฑ ์ผ๋ก ๋จ์ํ)
- ์๋น์ : LRU (Redis ๊ธฐ๋ณธ)
- ํค ํฌ๋งท:
- ํน์ง: O(1) ์บ์ ์กฐํ, DB ํด๋ฐฑ
- ์์ ์ฑ๋ฅ: 1-5ms per request (100x ๊ฐ์ )
- ์บ์ ํํธ์จ ๋ชฉํ: 90%+
- ์๋น์ ์ ์ฑ : Redis LRU (์ต๊ทผ ์ฌ์ฉ ์ฐ์ )
- TTL ์ ๋ต: 15๋ถ ๊ณ ์ (๋จ์ํ๋ ์ ์ฑ )
- ์ผ๊ด์ฑ: Read-only ์ํฌ๋ก๋๋ก ์บ์ ๋ฌดํจํ ์ต์ํ
- ๋ชจ๋ํฐ๋ง: ํํธ์จ, ๋ฏธ์ค์จ ์ค์๊ฐ ์ถ์
- ํ ์คํธ ์๋๋ฆฌ์ค: ๋์ผํ 1,000๊ฐ ๋จ์ถ URL์ ๋ํ ๋ฐ๋ณต ์กฐํ
- ๋ถํ ํจํด: 10 VU ร 30์ด (์ด 300ํ ์์ฒญ)
- ์ธก์ ์งํ:
- Response time (avg, p95, p99)
- Requests per second
- Error rate
- Throughput
| Phase | Architecture | Expected p95 | Expected RPS | Cache Hit Rate |
|---|---|---|---|---|
| 1 | DB Only | 100-200ms | ~10-20 | N/A |
| 2 | DB + Index | 20-50ms | ~50-100 | N/A |
| 3 | Redis + DB | 5-20ms | ~200-500 | 90%+ |
- Phase 1: Baseline ์ธก์ (ํ์ฌ ์ฑ๋ฅ)
- Phase 2: Phase 1 ๋๋น 5x ์ด์ ์ฑ๋ฅ ๊ฐ์
- Phase 3: Phase 1 ๋๋น 20x ์ด์ ์ฑ๋ฅ ๊ฐ์ , ์บ์ ํํธ์จ 90%+
- ์๋ต ์๊ฐ: p95, p99, ํ๊ท
- ์ฒ๋ฆฌ๋: RPS, ์ด ์์ฒญ ์
- ์บ์ ํจ์จ: ํํธ์จ, ๋ฏธ์ค์จ
- ์๋ฌ์จ: HTTP 4xx/5xx ๋น์จ
- Docker Desktop (Compose v2)
- PostgreSQL 16, Redis 7(alpine). Spring Boot ์ฑ์ ์ถํ
api์๋น์ค๋ก ์ถ๊ฐ ์์ .
deploy.resources.limits.memory๋ Swarm ์ฉ ํ๋์ ๋๋ค. ๋ก์ปฌ Compose์์ ๊ฐ์ ํ๋ ค๋ฉดdocker compose --compatibility up๋๋ ์๋น์ค๋ณmem_limit(๋ ๊ฑฐ์) ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.- JVM(์คํ๋ง) ์ปจํ
์ด๋๋
-XX:+UseContainerSupport -XX:MaxRAMPercentage=<N>๋ก ์ปจํ ์ด๋ ๋ฉ๋ชจ๋ฆฌ ํ๋๋ฅผ ์ธ์ง์์ผ์ผ OOM์ ํผํ ์ ์์ต๋๋ค.
# ๋ชจ๋ ์๋น์ค ์คํ (Spring Boot + ๋ชจ๋ํฐ๋ง)
docker compose --compatibility up -d
# ๋๋ ๋ชจ๋ํฐ๋ง๋ง ์คํ
docker compose --compatibility up -d prometheus grafana node-exporter postgres-exporter cadvisor- Dashboard ID:
4701(JVM Micrometer) - Spring Boot 3.x ํธํ
- Dashboard ID:
11074(Node Exporter for Prometheus Dashboard)
- Dashboard ID:
9628(PostgreSQL Database) - Dashboard ID:
455(PostgreSQL Overview)
- Dashboard ID:
763(Redis Dashboard) - Dashboard ID:
11835(Redis Exporter)
- Dashboard ID:
2587(k6 Performance Testing) - ์ฉ๋: k6 ์ฑ๋ฅ ํ ์คํธ ๊ฒฐ๊ณผ ์๊ฐํ
- ๋ฐ์ดํฐ์์ค: InfluxDB (k6 ๋ฉํธ๋ฆญ)
- Grafana ์ ์: http://localhost:3000
- ์ข์ธก ๋ฉ๋ด โ Dashboards โ + New โ Import
- Import via grafana.com ํญ ์ ํ
- Dashboard ID ์
๋ ฅ (์:
4701,2587) - Load โ Prometheus ๋๋ InfluxDB ๋ฐ์ดํฐ์์ค ์ ํ โ Import