ADR-03: API와 Worker 서비스 분리
| Date | Author | Repos |
|---|---|---|
| 2024-12-17 | @KubrickCode | web, collector |
Context
문제 상황
장기 실행 분석 작업을 수행하는 시스템은 근본적인 아키텍처 과제에 직면한다: 실행 시간이 예측 불가능한 작업을 처리하면서 동시에 사용자에게 빠른 응답을 제공해야 하는 것.
분석 워크로드의 핵심 특성:
- 불확정적 실행 시간: 입력 크기에 따라 수초~수분까지 처리 시간 변동
- 리소스 집약적: 분석 중 높은 CPU, 메모리, I/O 사용
- 상충하는 요구사항: 사용자는 빠른 API 응답을 기대하지만 분석은 시간 소요
모놀리식의 딜레마
API와 분석을 단일 서비스에서 실행하면 여러 문제 발생:
| 문제 | 영향 |
|---|---|
| 리소스 경쟁 | 분석 작업이 API 핸들러의 CPU/메모리 점유 |
| 장애 전파 | Worker OOM 크래시 시 전체 서비스 다운 |
| 비효율적 스케일링 | 분석만 필요해도 전체 서비스 확장 필요 |
| 배포 결합 | API 변경 시에도 분석 코드 재배포 필요 |
| Cold Start 오버헤드 | 바이너리 크기 증가로 시작 시간 지연 |
핵심 질문
반응성 있는 API 상호작용과 리소스 집약적 백그라운드 처리를 모두 요구하는 시스템을 어떻게 설계해야 하는가?
Decision
API 서비스와 Worker 서비스를 독립적으로 배포 가능한 단위로 분리한다.
아키텍처:
- API 서비스: HTTP 요청 처리, 입력 검증, 작업 큐잉, 결과 반환
- Worker 서비스: 큐잉된 작업 처리, 분석 수행, 결과 저장
- 통신: 작업 분배용 메시지 큐
- 데이터: 결과 저장용 공유 데이터베이스
Options Considered
Option A: 서비스 분리 (선택됨)
User → API Service → Queue → Worker Service → Database
↓ ↓
(enqueue) (process & store)장점:
- API와 Worker 각각의 부하에 따른 독립적 스케일링
- 장애 격리 - Worker 크래시가 API 가용성에 영향 없음
- 리소스 최적화 - Worker에만 고메모리 인스턴스 할당 가능
- 배포 독립성 - Worker 재배포 없이 API 업데이트 가능
- 명확한 관심사 분리와 코드베이스
단점:
- 운영 복잡성 - 두 서비스 모니터링 및 배포 필요
- 통신 오버헤드 - 큐 시스템 의존성
- 디버깅 복잡성 - 분산 시스템 추적 필요
- 인프라 비용 - 큐 시스템(PostgreSQL)이 추가 의존성
Option B: 모놀리식 서비스
User → Single Service (API + Worker in-process)장점:
- 단순한 배포와 운영
- 내부 통신 네트워크 오버헤드 없음
- 단일 프로세스로 디버깅 용이
- 낮은 인프라 비용 (단일 서비스)
단점:
- 스케일링 비효율 - 전체 서비스 확장 필요
- 장애 전파 - 분석 OOM이 API 종료 유발
- 리소스 경쟁 - 분석이 API 응답 지연 유발
- 배포 결합 - 모든 변경에 전체 재배포 필요
- 컨테이너 이미지 크기 증가로 Cold Start 시간 증가
Option C: Serverless 함수
User → API Service → Serverless Function (analysis)장점:
- 자동 스케일링 내장
- 사용량 기반 비용 모델
- 서버 관리 불필요
단점:
- Cold Start 지연이 분석에 문제 (네이티브 의존성)
- 실행 시간 제한이 불충분할 수 있음
- 네이티브 라이브러리의 복잡한 의존성 관리
- 장기 실행 작업에 높은 호출당 비용
Consequences
Positive
독립적 스케일링
- 높은 분석 수요 시 Worker 수평 확장
- 사용자 트래픽에 따라 API 독립 확장
- 필요한 곳에 리소스 할당으로 비용 최적화
장애 격리
- Worker 메모리 고갈이 API 크래시 유발 안함
- 분석 타임아웃이 API 응답 차단 안함
- 전체 장애 대신 부분 성능 저하
기술적 최적화
- Worker: 처리량 최적화 (배치 처리, 고메모리)
- API: 지연 시간 최적화 (캐싱, 커넥션 풀링)
배포 유연성
- Worker 코드 수정 없이 API 버그 핫픽스
- API 다운타임 없이 분석 알고리즘 업데이트
- 독립적 릴리스 주기
Negative
운영 오버헤드
- 두 서비스 각각 모니터링, 로깅, 알림 필요
- 여러 배포 파이프라인 유지보수
- 환경 설정 동기화 필요
통신 의존성
- 큐 시스템(PostgreSQL)이 핵심 인프라가 됨
- 작업 처리에 네트워크 지연 추가
- 메시지 전달 보장 설정 필요
일관성 문제
- 여러 서비스에서의 DB 접근 조율 필요
- 스키마 변경이 두 서비스에 영향
- 공유 데이터 모델에 버전 관리 전략 필요
기술적 함의
| 측면 | 함의 |
|---|---|
| 큐 시스템 | PostgreSQL 기반 큐 필요 (River) |
| 데이터베이스 접근 | 두 서비스 모두 DB 연결 관리 필요 |
| 모니터링 | 서비스 간 디버깅을 위한 분산 추적 |
| 배포 | 별도 CI/CD 파이프라인 또는 조율된 릴리스 |
| 설정 | 공유 환경 변수 동기화 필요 |
