💡 오늘 학습 키워드
- 대규모 시스템 설계
- RabbitMQ
🎯 학습 내용 정리
웹 서비스를 운영하다 보면 사용자가 증가하면서 동시에 수많은 요청이 발생한다.
초기에는 하나의 서버와 하나의 데이터베이스만으로도 충분하지만, 서비스 규모가 커질수록 단순한 구조만으로는 성능과 안정성을 보장하기 어렵다.
대규모 시스템에서는 많은 요청을 안정적으로 처리하면서도 장애에 강하고, 확장 가능한 구조를 설계하는 것이 중요하다.
RabbitMQ는 이러한 환경에서 비동기 처리와 서비스 간 결합도를 낮추기 위해 가장 많이 사용하는 메시지 브로커 중 하나이다.
1. 대규모 시스템 설계
대규모 시스템이라고 해서 단순히 사용자가 많은 시스템만 의미하는 것은 아니다.
많은 사용자가 동시에 접속하더라도 안정적으로 서비스를 제공할 수 있도록 설계된 시스템을 의미한다.
대표적으로 고려해야 하는 요소는 다음과 같다.
- 동시 접속자 수
- TPS(Transactions Per Second)
- 응답 속도
- 확장성(Scalability)
- 장애 대응(Fault Tolerance)
- 데이터 일관성
서비스가 성장할수록 가장 먼저 확인해야 하는 것은 최대 동시 요청량(TPS) 이다.
예를 들어 특정 시간에 초당 200건의 요청이 발생한다면 최소 200TPS 이상을 처리할 수 있도록 설계해야 한다.
실무에서는 예상치 못한 트래픽 증가를 고려하여 약 1.5배 정도의 여유 용량을 확보하는 경우가 많다.
갑작스러운 이벤트나 프로모션으로 예상보다 많은 요청이 발생한다면 다음과 같은 방법으로 대응할 수 있다.
- 서버 증설(Scale-Out)
- Auto Scaling
- Queue를 이용한 요청 대기
- 캐시 활용
모든 요청은 동일하게 처리하지 않는다.
읽기(Read) 요청과 쓰기(Write) 요청은 병목이 발생하는 위치가 다르므로 각각 다른 방식으로 최적화한다.
1) 읽기(Read) 요청 최적화
대부분의 조회 요청은 데이터베이스 조회 시간이 가장 오래 걸린다.
이를 줄이기 위해 다양한 방법을 사용한다.
Cache
가장 많이 사용하는 방식이다.
Client
↓
Redis Cache
↓ (Miss)
Database
동일한 데이터를 반복 조회하는 경우 DB 대신 Redis에서 데이터를 가져오기 때문에 응답 속도가 매우 빨라지고 DB 부하도 크게 감소한다.
Database Index
검색 조건에 맞는 인덱스를 생성하면 조회 속도가 크게 향상된다.
하지만 인덱스가 너무 많아지면 INSERT, UPDATE 성능은 저하될 수 있다.
Read Replica
조회 전용 데이터베이스를 별도로 운영한다.
Master DB
│
Replication
│
Read Replica
조회 요청은 Replica가 처리하고 쓰기 요청은 Master가 처리하여 부하를 분산한다.
Database Sharding
데이터를 여러 DB에 분산 저장하는 방식이다.
하나의 DB에 모든 요청이 집중되는 것을 방지할 수 있다.
대표적으로
- User ID 기준 샤딩
- 날짜 기준 파티셔닝
등이 있다.
Query Optimization
SQL 자체를 효율적으로 작성하는 것도 중요하다.
- 필요한 컬럼만 조회
- 불필요한 JOIN 제거
- 실행 계획(EXPLAIN) 확인
등을 통해 성능을 개선할 수 있다.
2) 쓰기(Write) 요청 최적화
쓰기 요청은 대부분 Database 저장 시간이 병목이 된다.
이를 해결하기 위해 다양한 방법을 사용한다.
비동기 처리
가장 대표적인 방법이 메시지 큐를 이용한 비동기 처리이다.
Client
↓
Application
↓
RabbitMQ
↓
Consumer
↓
Database
사용자는 즉시 응답을 받고 실제 DB 저장은 Consumer가 처리한다.
이 방식은 대량의 요청이 발생해도 애플리케이션 응답 속도를 유지할 수 있다.
Batch 처리
실시간 처리가 필요하지 않은 데이터는 일정 시간마다 한꺼번에 저장한다.
대표적인 예시는
- 로그 저장
- 통계 데이터
- 대량 이메일 발송
등이다.
분산 Database
하나의 DB만으로 쓰기 성능을 감당하기 어렵다면 여러 DB에 데이터를 분산 저장한다.
이를 통해 처리량과 가용성을 높일 수 있다.
MSA에서는 하나의 요청이 여러 서비스에 걸쳐 수행되는 경우가 많다.
예를 들어
주문 생성
↓
결제
↓
재고 차감
각 서비스가 독립적인 DB를 사용한다면 데이터 일관성을 유지하는 것이 매우 중요하다.
대표적인 해결 방법은 다음과 같다.
1) 분산 트랜잭션
여러 시스템에서 하나의 트랜잭션처럼 동작하도록 만드는 방식이다.
대표적으로
- 2PC(Two Phase Commit)
- Saga Pattern
을 사용한다.
Saga Pattern은 각 단계를 개별 트랜잭션으로 수행하고 실패하면 보상 트랜잭션을 실행하는 방식으로, MSA 환경에서 가장 많이 사용된다.
2) Event Sourcing
현재 상태를 저장하는 것이 아니라 상태 변경 이벤트를 저장한다.
예를 들어
주문 생성
결제 완료
배송 시작
배송 완료
모든 이벤트를 저장한 뒤 이벤트를 재생하여 현재 상태를 계산한다.
데이터 변경 이력을 모두 확인할 수 있다는 장점이 있다.
3) CQRS
Command와 Query를 분리하는 설계 방식이다.
Command
(쓰기)
↓
Database
↓
Projection
↓
Read Database
↓
Query
(조회)
읽기와 쓰기를 각각 최적화할 수 있으며 Event Sourcing과 함께 자주 사용된다.
모니터링과 로깅은 서비스가 정상적으로 운영되는지 확인하기 위해 반드시 필요한 요소이다.
모니터링(Monitoring)은 대표적으로
- TPS
- 응답 시간
- CPU
- Memory
- Error Rate
등을 실시간으로 수집한다.
주로
- Prometheus
- Grafana
를 사용한다.
이상 징후가 발생하면 즉시 알림을 받아 빠르게 대응할 수 있다.
로깅(Logging)은 애플리케이션에서 발생하는 이벤트를 기록한다.
대표적으로
- ERROR
- WARN
- INFO
- DEBUG
로그를 수집하여 문제 원인을 분석한다.
주로
- Elasticsearch
- Logstash
- Kibana(ELK)
를 사용한다.
대규모 시스템에서는 코드 작성만큼 테스트와 배포 전략도 중요하다.
대표적인 테스트는 다음과 같다.
- Unit Test
- Integration Test
- Load Test
- Regression Test
- UAT(User Acceptance Test)
특히 부하 테스트를 통해 실제 운영 환경과 유사한 상황을 미리 검증하는 것이 중요하다.
배포 전략으로는
- CI/CD
- Rolling Deployment
- Canary Deployment
- Blue-Green Deployment
등을 활용하여 무중단 배포와 빠른 롤백을 구현한다.
2. RabbitMQ
RabbitMQ는 대표적인 메시지 브로커(Message Broker)이다.
애플리케이션 사이에서 메시지를 전달하는 중간 역할을 수행한다.
Producer
↓
Exchange
↓
Queue
↓
Consumer
RabbitMQ를 사용하면 요청을 비동기로 처리할 수 있어 응답 속도를 높이고 시스템 간 결합도를 낮출 수 있다.
RabbitMQ의 역할은 다음과 같다.
1) 비동기 처리
시간이 오래 걸리는 작업을 Queue에 저장하고 나중에 처리한다.
대표적으로
- 이메일 발송
- 문자 발송
- 주문 처리
- 로그 저장
등이 있다.
2) 부하 분산
여러 Consumer가 하나의 Queue를 함께 소비하여 작업을 분산 처리한다.
Queue
↓
Consumer A
Consumer B
Consumer C
이를 통해 대량의 요청도 효율적으로 처리할 수 있다.
3) 내결함성
메시지를 Queue에 저장하기 때문에 Consumer 장애가 발생해도 메시지가 즉시 사라지지 않는다.
Consumer가 복구되면 다시 처리할 수 있다.
RabbitMQ는 다음 요소들로 구성된다.
Message
Queue를 통해 전달되는 데이터이다.
예를 들어 주문 정보나 회원 가입 정보가 메시지가 된다.
Producer
메시지를 생성하여 RabbitMQ에 전달하는 역할이다.
Queue
메시지가 저장되는 공간이다.
기본적으로 FIFO(First In First Out) 방식으로 처리된다.
Consumer
Queue에서 메시지를 가져와 실제 작업을 수행한다.
Exchange
Producer가 보낸 메시지를 적절한 Queue로 전달하는 라우터 역할을 한다.
Producer는 Queue가 아니라 Exchange에 메시지를 전송한다.
RabbitMQ는 AMQP(Advanced Message Queuing Protocol)를 기반으로 동작한다.
AMQP는 메시지를 송수신하기 위한 표준 프로토콜이다.
AMQP의 주요 구성 요소는 다음과 같다.
- Message
- Exchange
- Queue
- Binding
Binding은 Exchange와 Queue를 연결하는 규칙이다.
RabbitMQ는 여러 방식으로 메시지를 라우팅할 수 있다.
1) Direct Exchange
Routing Key가 정확히 일치하는 Queue로 전달한다.
Routing Key : order.created
↓
order.created Queue
가장 기본적인 방식이다.
2) Topic Exchange
패턴을 이용하여 메시지를 전달한다.
order.*
payment.#
- * : 한 단어
- # : 여러 단어
다양한 이벤트를 유연하게 라우팅할 수 있다.
3) Fanout Exchange
Routing Key를 무시하고 연결된 모든 Queue에 메시지를 전달한다.
Exchange
↓
Queue A
Queue B
Queue C
대표적으로 알림이나 이벤트 브로드캐스트에 사용된다.
4) Headers Exchange
Routing Key 대신 Header 값을 기준으로 Queue를 선택한다.
특정 메타데이터를 기준으로 라우팅해야 하는 경우 활용된다.
대규모 시스템은 단순히 서버를 여러 대 추가하는 것으로 해결되지 않는다.
사용자 수와 TPS를 분석하고, 읽기와 쓰기의 특성을 분리하며, 캐시와 메시지 큐를 적절하게 활용해야 한다. 또한 데이터 일관성을 유지하기 위해 분산 트랜잭션, Saga Pattern, Event Sourcing, CQRS 등을 상황에 맞게 선택해야 하며, 모니터링과 테스트, 무중단 배포 체계까지 함께 구축해야 한다.
RabbitMQ는 이러한 대규모 시스템에서 비동기 처리와 부하 분산을 담당하는 핵심 컴포넌트 중 하나이며, 올바르게 활용하면 시스템의 성능과 안정성을 크게 향상시킬 수 있다.
📚 한줄 정리
1. 대규모 시스템은 읽기·쓰기 요청을 각각 최적화하고 데이터 일관성과 모니터링을 고려해 설계해야 한다.
2. RabbitMQ는 비동기 처리와 메시지 라우팅을 통해 높은 처리량과 안정성을 제공하는 핵심 메시지 브로커이다.
'Bootcamp > Fundamentals' 카테고리의 다른 글
| Redis를 활용한 Session Clustering, Leaderboard 그리고 Cache (0) | 2026.07.24 |
|---|---|
| Redis (0) | 2026.07.23 |
| CI/CD와 GitLab CI + AWS ECS 자동배포 (1) | 2026.07.22 |
| Docker와 Docker Compose (0) | 2026.07.21 |
| Event Driven Architecture와 Kubernetes (0) | 2026.07.05 |