FastAPI 기반 이커머스 아키텍쳐 설계 - 1. 대용량 트래픽 아키텍쳐 개요
이커머스 서비스를 구현하기 위해 대용량 트래픽 처리를 고려한 아키텍쳐 설계 방안에 대해 정리해 보았습니다. 프론트엔드는 Next.js 기반, 백엔드는 FastAPI, 인프라는 AWS를 활용하여 서비스 개발을 진행하도록 아키텍쳐를 구성하였습니다. 대용량 트래픽 처리가 가능한 시스템 구현시 확장성 및 높은 동시성을 확보하는 것이 중요합니다.
대용량 트래픽 처리시 "확장성"과 "동시성"의 개념에 대한 이해
확장성(Scalability):
사용자 증가나 데이터 확장에 따라 성능을 유지하며 성장할 수 있는지 여부를 의미합니다. 이는 시스템이 변하는 부하를 효과적으로 처리하고, 사용자가 증가하더라도 안정성과 성능을 유지할 수 있도록 하는 설계와 구조를 갖추는 것입니다. 확장성은 크게 두가지로 구분할 수 있습니다.
수평적 확장성(Horizontal Scaling):
서버 수를 확장함으로서 성능을 높이는 방식으로 여러 서버를 네트워크로 연결. 개별 서버에 부하가 집중되지 않도록 분산처리하는 것을 고려합니다.
■ 방안: 로드밸런서(e.g. NGINX)를 통해 트래픽을 각 서버로 고르게 분산하고 이를 통해 시스템 전체가 더 많은 요청을 안정적으로 처리
■ 특성 및 고려사항
1. 개별 서버의 성능에 상대적으로 덜 의존하게 되며, 필요에 따라 새로운 서버를 추가함으로써 트래픽 처리 용량을 늘릴 수 있음
2. 고려사항: 복잡한 관리, 데이터 일관성, 네트워크 지연, 디버깅 및 모니터링 복잡성, 로드 밸런싱의 한계 고려 필요
1) 복잡한 관리: 수평적 확장성을 고려하여 대용량 트래픽 처리가 가능하도록 설계 시 관리상의 복잡도가 증가할 수 있으며, 이를 보완하기 위해 컨테이너화, 오케스트레이션 도구 활용, IaC 등을 고려할 수 있습니다.
- 어플리케이션 측면
1. 컨테이너화: 도커와 같은 컨테이너 기술을 활용하여 일관된 어플리케이션 환경을 제공하여, 서버관리의 복잡성을 줄일 수 있음
2. 오케스트레이션 도구 활용: 쿠버네티스(k8s), 도커 스웜(Docker Swarm) 같은 오케스트레이션 도구를 활용하여 서버배포,운영을 자동화하여 관리 부담을 줄일 수 있음
- 인프라 측면
1. Infrastructure as Code(IaC): Terraform, Ansible 등을 사용해 인프라 코드를 관리하여 반복적인 설정 및 변경작업을 자동화하고 일관성을 유지할 수 있음
2) 데이터 일관성 문제: 분산 시스템에서는 여러 서버에 데이터를 나누어 저장하거나 처리하기 때문에, 데이터 일관성을 유지하는 데 어려움이 있을 수 있습니다. 예를 들어, 데이터베이스 샤딩을 적용했을 때 데이터 간의 동기화를 보장하는 데 추가적인 노력이 필요합니다. 이를 보완하기 위해 Apache Cassandra나 Google Spanner 등의 분산 DB를 사용하여 데이터 일관성 및 분산된 환경에서의 가용성을 보장하는 방법을 고려할 수 있습니다.
3) 비용: 서버를 추가할 때마다 추가적인 하드웨어 비용뿐만 아니라, 네트워크 인프라, 유지 보수, 전력 비용 등도 증가합니다. 클라우드 서비스를 사용하더라도 트래픽 분산과 관련된 비용이 높아질 수 있습니다. 이를 보완하기 위해 자동 스케일링, 서버리스 컴퓨팅 도입을 고려할 수 있습니다.
- 자동 스케일링: 클라우드 서비스에서 제공하는 자동 스케일링 기능을 활용하여 트래픽 증가시에만 서버 인스턴스를 자동으로 늘리고 부하가 줄어들면 인스턴스를 축소하여 비용을 절감할 수 있음
- 서버리스 컴퓨팅 도입: AWS Lambda, Google Cloud Functions 등의 서버리스 기능을 활용하여 트래픽 변화에 따라 유연하게 대응할 수 있으며, 실행된 만큼 비용이 청구되므로 이를 통한 경제적인 운영이 가능함
4) 네트워크 지연: 여러 서버가 분산되어 있으면 요청과 응답 과정에서 네트워크 지연(latency)이 발생할 수 있습니다. 특히, 서버 간의 데이터 전송이 필요한 경우 지연 시간이 성능에 영향을 줄 수 있습니다.
- CDN 활용: 정적 자산(static asset) 및 캐시가능한 컨텐츠를 CDN에 배포하여 클라이언트-서버간 지연을 줄일 수 있음
- Static asset: HTML, CSS, Javascript(클라이언트 측 스크립트), 이미지파일, 폰트파일, 동영상 및 오디오 컨텐츠, 아이콘 및 벡터 이미지, 애플리케이션 번들 및 라이브러리, 변경빈도가 적은 API 응답
- 지연 최소화 전략: 각 서버의 지리적 위치를 사용자와 가깝게 두거나, edge 서버를 활용한 시간을 줄이는 방안
- 네트워크 최적화: 트래픽 우선순위 설정 및 압축기법을 적용해 네트워크 대역폭(bandwidth)를 효율적으로 사용
5) 디버깅 및 모니터링 복잡성: 분산된 여러 서버에서 문제가 발생했을 때, 디버깅과 모니터링이 어렵습니다. 로그를 중앙에서 관리하고, 각 서버의 상태를 추적하는 시스템이 필요하며 이로 인한 운영상의 부담을 증가시킬 수 있습니다. 이를 보완하기 위해 통합로깅, 분산추적시스템, 모니터링 도구 도입을 고려하는 것이 필요합니다.
- 통합로깅시스템 도입: ELK, Grafana 등의 툴을 활용하여 모든 서버의 로그를 중앙에 수집하고 이를 시각화하여 관리
- 분산추적시스템: Jaeger, Zipkin 등을 통해 분산된 시스템에서의 요청지점을 분석하고 병목지점을 파악
- 모니터링 도구: Prometheus와 같은 모니터링 툴을 활용해 각 서버의 상태, 자원 사용률, 응답시간을 실시간으로 추적하고 경고알림을 설정하여 빠르게 대응할 수 있음
6) 로드 밸런싱의 한계: 로드 밸런서가 모든 서버에 트래픽을 균등하게 분산해도, 각 서버의 상태나 성능이 다를 경우 특정 서버에 과부하가 걸릴 수 있습니다. 로드 밸런싱 자체가 병목점이 되지 않도록 주의해야 합니다. 이를 보완하기 위해 지능형 로드밸런싱, 부하분산전략 다중화를 고려할 수 있습니다.
- 지능형 로드밸런싱: 단순한 라운드로빈방식 대신, 각 서버의 상태를 고려해 트래픽을 분산하는 지능형 로드밸런서 도입: AWS ELB, NGINX의 상태기반 로드밸런싱 기능
- 부하분산전략 다중화: 로드밸런서 이중화
수직적 확장성(Vertical Scaling):
기존 서버의 하드웨어 성능을 업그레이드하여 더 많은 요청처리가 가능하도록 하는 방식으로 CPU, RAM, 스토리지 등의 자원을 추가하거나 교체하여 처리성능을 개선하게 되어 이를 통해 더 많은 요청을 처리할 수 있습니다. 이를 위해 CPU 코어를 늘리거나 더 빠른 메모리, 더 큰 스토리지를 추가해 성능을 높입니다.
- 장점: 시스템을 상대적으로 간단한 구조로 유지할 수 있으며, 복잡한 네트워크 구성 없이 처리 성능을 올릴 수 있습니다.
- 단점: 하드웨어 한계에 도달시 추가 확장이 어렵다는 점, 하드웨어 관련 비용증가를 고려해야 합니다.
동시성(Concurrency):
아키텍쳐 레벨의 동시성:
수천~수만의 사용자가 동시에 서비스를 요청할때 이를 효율적으로 트래픽을 처리할 수 있는 아키텍쳐가 필요합니다. 이 레벨에서는 다수의 서버, 로드밸런싱, 분산처리시스템 등이 동시성을 보장합니다.
예시:
- 로드밸런서
- CDN
- 분산 데이터베이스
- 메시지큐: Kafka, RabbitMQ 등의 시스템을 활용하여 대량의 데이터를 비동기적으로 처리할 수 있습니다. 이는 트래픽 급증 시 서버가 즉시 모든 요청을 처리할 필요없이 작업을 큐에 쌓아두고 차례대로 처리하도록 합니다.
단일 어플리케이션 레벨의 동시성:
- I/O 대기시간을 최소화하고 단일 서버가 최대한 많은 클라이언트 요청을 처리하도록 하는 것이 목적
- 현재 개발시 활용중인 Fast API를 통해 어플리케이션 레벨에서의 비동기 처리가 가능합니다.
- 비동기 엔드포인트: 아래 예시는 FastAPI와 asyncio를 사용하여 엔드포인트 호출시 비동기적으로 대기를 진행하면서 다른 클라이언트의 요청을 비동기처리하는 것을 보여줍니다.
from fastapi import FastAPI
import asyncio
app = FastAPI()
@app.get("/process-data")
async def process_data():
await asyncio.sleep(5) # 비동기적으로 대기, 다른 요청을 병행 처리 가능
return {"message": "Data processed"}
비동기 데이터베이스 라이브러리 지원: asyncpg와 같은 비동기 데이터베이스 클라이언트를 사용하여 DB와의 비동기 연동을 지원할 수 있습니다.
기본 아키텍쳐 구성