고성능 소셜 API를 Bun & ElysiaJS로 $5 VPS에서 구축한 방법 (분당 3.6천 요청 처리)
Source: Dev.to
목표
마이크로‑소셜 API—Twitter와 같은 피드, 팔로우, 좋아요를 처리할 수 있는 백엔드 서비스를 비용을 크게 들이지 않고 만들고 싶었습니다.
- 예산: 월 $5 – $20
- 성능: 300 ms 이하 지연 시간
- 규모: 동시 부하를 처리할 수 있어야 함 (스트레스 테스트)
대부분의 튜토리얼은 Hello World만 보여줍니다. 이 글에서는 저렴한 VPS에서 25명의 동시 사용자가 Hello World에 접근했을 때 무슨 일이 일어나는지(스포일러: 서버가 다운됩니다)를 보여주고, 이를 어떻게 해결했는지 설명합니다.
스택 🛠️
- 런타임: Bun
- 프레임워크: ElysiaJS (가장 빠른 Bun 프레임워크)
- 데이터베이스: PostgreSQL (Dokploy 사용)
- ORM: Drizzle (경량·타입‑안전)
- 호스팅: Dokploy이 적용된 VPS (Docker Compose)
“오 이런” 순간 🚨
첫 번째 버전을 배포했을 때는 정상적으로 동작했습니다. 그 뒤 k6을 이용해 25명의 가상 사용자가 다양한 피드를 탐색하도록 부하 테스트를 실행했습니다.
k6 run tests/stress-test.js
결과
✗ http_req_failed................: 86.44%
✗ status is 429..................: 86.44%
서버가 다운된 것은 아니었지만, 거의 모든 요청을 거부하고 있었습니다.
진단
처음엔 Traefik(리버스 프록시) 때문이라고 생각했습니다. 코드를 파고들어 보니 범인은 나 자신이었습니다.
// src/index.ts
// OLD CONFIGURATION
.use(rateLimit({
duration: 60_000,
max: 100 // 💀 1분당 100 요청... IP당 전역?
}))
스트레스 테스트(그리고 대부분의 NAT된 사무실)에서는 모든 요청이 단일 IP에서 발생했기 때문에, 사실상 자신을 DDOS하고 있던 셈이었습니다.
해결 방법 🔧
1. Rate Limiter 튜닝
제한을 2,500 req/min으로 올렸습니다. 이는 남용을 방지하면서도 정상적인 대량 트래픽(또는 로드밸런서)을 허용합니다.
// src/index.ts
.use(rateLimit({
duration: 60_000,
max: 2500 // 표준적인 신뢰성 API에 훨씬 적합
}))
2. 데이터베이스 연결 풀링
PostgreSQL 기본 풀 크기는 보통 작습니다(예: 10~20). 내 VPS는 4 GB RAM을 가지고 있으며, PostgreSQL은 연결당 메모리를 필요로 하지만 그 정도는 필요하지 않습니다. 풀 크기를 80 연결로 늘렸습니다.
// src/db/index.ts
const client = postgres(process.env.DATABASE_URL, {
max: 80
});
3. Docker를 이용한 수평 확장
Node/Bun은 단일 스레드입니다. 하나의 컨테이너는 하나의 CPU 코어만 효율적으로 사용합니다. 내 VPS는 2 vCPU를 가지고 있으므로 docker-compose.dokploy.yml에 replicas 지시자를 추가했습니다.
api:
build: .
restart: always
deploy:
replicas: 2 # 코어당 하나씩!
Traefik이 두 컨테이너 사이를 자동으로 로드밸런싱해 주어 처리량이 즉시 두 배가 됩니다.
최종 결과 🟢
다시 k6을 실행합니다:
k6 run tests/stress-test.js
성과
✓ checks_succeeded...: 100.00%
✓ http_req_duration..: p(95)=200.45ms
✓ http_req_failed....: 0.00% (excluding auth checks)
오류 0개, 저렴한 VPS에서도 약 200 ms 지연을 기록했습니다.
교훈
사이드 프로젝트에 Kubernetes가 필요하지 않습니다. 병목 현상이 어디에 있는지 이해하면 됩니다:
- 애플리케이션 레이어: Rate limit을 확인하세요.
- 데이터베이스 레이어: 연결 풀을 확인하세요.
- 하드웨어: 모든 코어를 활용하세요(복제본).
API를 직접 사용해 보고 싶다면 Micro‑Social API가 RapidAPI에 공개되어 있습니다:
https://rapidapi.com/ismamed4/api/micro-social
행복한 코딩 되세요! 🚀