오늘의 알고리즘
코드카타는 매일 진행된ㄷㅏ...
하면 할수록 파이썬이 그리워진다.
프로그래머스-개인정보 수집 유효기간
문제 분석
- 주어진 것
- today: 오늘 날짜
- terms: 약관 종류와 유효기간(개월 수)
- privacies: 개인정보 수집일과 동의한 약관 종류
- 날짜 비교
- today와 비교해서 만료일이 지나면 개인정보의 인덱스를 결과에 추가해서 반환
아이디어
- 날짜를 숫자로 변환해서 비교
- 어차피 한달의 기준을 28일로 잡기 떄문에 이를 하나의 정수 값으로 변환해서 비교함
- 약관별 유효기간 관리
- terms 배열은 "A 3" 이런 형식으로 저장됨
- Map에 저장해 빠르게 조회할 수 있음
- 만료일 계산
- 만료일 비교
import java.util.*;
class Solution {
public int[] solution(String today, String[] terms, String[] privacies) {
Map<String, Integer> termMap = new HashMap<>();
for (String term : terms) {
String[] splitTerm = term.split(" ");
termMap.put(splitTerm[0], Integer.parseInt(splitTerm[1]));
}
int todayDays = toDays(today);
List<Integer> expiredIndices = new ArrayList<>();
for (int i = 0; i < privacies.length; i++) {
String[] privacy = privacies[i].split(" ");
int startDays = toDays(privacy[0]);
String termType = privacy[1];
int expirationDays = startDays + termMap.get(termType) * 28;
if (expirationDays <= todayDays) {
expiredIndices.add(i + 1);
}
}
return expiredIndices.stream().mapToInt(Integer::intValue).toArray();
}
private int toDays(String date) {
String[] parts = date.split("\\.");
int year = Integer.parseInt(parts[0]);
int month = Integer.parseInt(parts[1]);
int day = Integer.parseInt(parts[2]);
return (year * 12 * 28) + (month * 28) + day;
}
}
풀이
- termMap: HashMap으로 선언해 약관별로 유효기간을 저장
- todayDate: today는 정수로 변환해서 사용
- expiredIndices: 만료된 개인정보 인덱스를 저장할 배열
- privacies 배열을 순회하면서 수입일과 약관 종류를 파악하여 약관에 따른 만료일을 계산한다
- startDays: 수집일
- termType: 약관 종류
- 오늘 날짜보다 작으면 배열에 추가한다
- toDays: 날짜를 일 단위로 변환
- ex) "2022.05.19" → (2022 × 12 × 28) + (5 × 28) + 19 = 847919
잠온당...
대규모 시스템이란?
수백만 명의 사용자가 동시에 접속, 상호작용하는 환경에서
단순히 많은 사용자를 처리하는 것 뿐만 아니라 안정성과 신뢰성을 유지하면서 고성능을 제공할 수 있는 시스템
대규모 시스템의 맥락에서 실시간 데이터를 빠르게 처리하고, 적합한 결과를 추출하는 프로세스!
이런 특징이 있다.
특징
- 데이터 양이 매우 큼
- 데이터가 기하급수적으로 증가하며, 초당 수십만에서 수백만 건의 데이터를 처리해야 하는 상황
- 예: SNS 플랫폼(트위터, 인스타그램), IoT 센서 네트워크, 금융 거래 시스템
- 고가용성
- 시스템이 중단 없이 작동해야 하며, 데이터 유실이 없어야 함
- 예: 실시간 거래 시스템, 스트리밍 서비스(ex: 넷플릭스)
- 분산 아키텍처
- 단일 서버가 아닌 여러 대의 서버(클러스터)로 이루어진 분산 환경에서 데이터가 처리됨
- 확장성과 내결함성이 장점
- 확장성
- 데이터 양이나 사용자가 증가해도 시스템이 성능 저하 없이 확장 가능해야 함
- 예: 클라우드 기반 확장형 인프라(AWS, GCP)
- 실시간 처리
- 데이터가 생성됨과 동시에 실시간으로 처리 및 분석이 이루어져야 하는 경우
- 예: 실시간 로그 분석, 광고 시스템
하여간 겁나 멋있는 시스템이란 것이다.
대규모 시스템을 설계, 구축하는 과정에서 고려해야 할 요소들을 알아보자!
목표
- 대규모 스트림 처리에 대한 이해
- 대규모 시스템의 전반적인 구성과 운영에 대한 이해
시스템 설계의 기준
1. 동시 접속자와 초당 요청량(TPS)
1-1 사용자수
- 몇 명의 사용자가 시스템을 사용할 것인지 파악하는 것이 중요함
- 하루에 몇 명의 사용자가 접속하는 지도 알아야 하지만 동시 접속자의 요청 수도 중요!
1-2 TPS (Transactions Per Second)
-
초당 처리되는 트랜젝션의 수를 나타내는 지표
-
시스템이 동시에 얼마나 많은 요청을 처리할 수 있는지를 나타냄. 이를 바탕으로 시스템의 처리 능력을 파악할 수 있다
-
일간 접속량보다는 초당 접속자 요청량이 가장 많은 특정 시간을 파악하고 이를 통해 시스템 용량 계획을 세워야 한다
-
예기치 못한 트래픽 증가를 버틸 수 있는 설계를 하는 것이 목표
-
"예기치 못한 이벤트"로 인해 설계 이상의 요청이 몰린다면?
- 애플리케이션의 수를 늘려서 버틴다
- 오류 상황에서 사용자가 대기할 수 있는 대기열을 설정한다
- 오토 스케일링을 통해 시스템 자원을 동적 할당하여 부하를 분산시킨다
2. 요청 종류에 따른 개발
- 시스템이 읽기 전용인지, 쓰기 및 업데이트를 위한 것인지도 고려해야 함
- DB에서 데이터를 조회하거나 쓰는 것은 많은 리소스를 먹는다. 이 부분의 허들을 최소화 하는 것이 중요
2-1. 읽기 요청 최적화
캐시 사용
-
모든 사용자가 같은 데이터를 요청하는 경우, DB 데이터를 레디스 같은 곳에 캐싱해두면 응답 속도를 빠르게 할 수 있다
-
개인화 데이터가 아니라면 캐시를 사용하는 것이 중요한 전략일 수 있다
-
엣지 단에서 캐싱 처리를 하면 시스템 요청 처리량이 줄어들어 적은 수의 애플리케이션으로도 요청을 처리할 수 있다
- 엣지 캐싱: 사용자와 가까운 곳에서 데이터를 제공하여 네트워크 지연을 최소화 함
-
캐시 갱신 전략에서도, 변경이 적은 데이터는 만료 시간을 길게, 변경이 잦은 데이터는 만료 시간을 짧게 설정하거나 변경 시점에 캐시를 무효화하는 전략을 이용할 수 있다
-
캐시 계층에서 데이터 소실 시 재요청을 통해 DB에서 다시 갖다놓는 것도 중요하다
데이터베이스 사용 최적화
-
데이터베이스 인덱싱
- 적절한 인덱스 설정은 읽기 성능을 최적화하여 쿼리 응답 시간을 줄일 수 있음
- 인덱스가 과도할 경우 쓰기 성능이 저하될 수 있음
-
데이터베이스 샤딩
- 데이터베이스를 여러 샤드로 분할해 각각의 샤드가 독립적으로 쿼리를 처리하도록 하는 방법
- 단일 데이터베이스에 대한 부하를 분산시키며, 읽기 요청에 대한 응답 속도를 향상시킬 수 있음
-
읽기 전용 데이터베이스
- 데이터를 주기적으로 동기화하여 최신 상태를 유지하며 읽기 요청을 처리
- 주 데이터베이스에 대한 읽기 부하를 줄이고 성능을 최적화 할 수 있음
-
쿼리 최적화
- 쿼리를 효율적으로 작성하여 데이터베이스의 읽기 성능을 향상시키는 방법
- 불필요한 join 제거, 필요 컬럼만 추출, 적절한 조건 사용 등
2-2. 쓰기 요청 최적화
쓰기 작업에서 가장 많은 시간이 소요되는 것은 DB에 데이터를 생성하는 부분이다
비동기 처리
-
쓰기를 비동기 처리하면 DB에 직접 접근하지 않고도 빠르게 응답을 반환할 수 있다
-
메시지를 바로 DB에 쓰지 않고 큐에 넣어 나중에 처리하는 등
-
비동기 처리는 높은 트래픽 처리에 특히 유용하다
-
비동기 처리 시 데이터 소실이나 오류를 방지하기 위해 큐에 넣을 때 적절한 검증 수행, 큐에 쌓인 데이터를 지속적으로 모니터링해 실패 요청은 재시도하는 매커니즘 마련 필요
-
데이터 순서를 보장하고, 중복 처리 방지를 위한 고유 식별자(ID) 사용
배치 처리
-
실시간 처리가 필요 없는 쓰기 요청은 배치 처리를 통해 한번에 처리
-
일정 시간마다 큐에 쌓인 메시지를 DB에 쓰는 방법 등
-
실시간 처리의 부담을 줄이고 시스템 자원을 효율적으로 사용 가능
-
데이터 소실 방지를 위해 배치 작업 중 오류 발생 시 이를 기록하고 재시도할 수 있는 매커니즘 필요
-
배치 작업의 상태를 모니터링하고 배치 작업이 완료되었는지 확인하는 프로세스 필요
분산 DB
-
단일 DB로 모든 쓰기 요청을 처리하기 어려울 경우, 분산 DB를 사용하여 부하를 분산시킬 수 있음
-
여러 개의 DB 인스턴스를 사용해 각 인스턴스가 특정 사용자 그룹의 데이터를 처리하도록 할 수 있음
-
데이터를 여러 개의 노드에 분산 저장하여 고가용성, 확장성 제공
-
샤딩 기법을 통해 DB를 수평 분할하여 각 샤드가 독립적으로 쓰기 작업을 하게 할 수도 있음
-> 단일 노드의 부하를 줄이고 전체 시스템의 능력을 향상시킬 수 있다
-
데이터 일관성 유지를 위해 트렌젝션 관리와 데이터 동기화를 신중히 고려해야 한다
-> 분산 트렌젝션이나 이벤트 소싱을 이용
3. 데이터 일관성 유지
분산 트렌젝션, 이벤트 소싱, CQRS 등의 기법을 이용할 수 있다
3-1. 분산 트렌젝션
여러 개의 독립된 시스템이나 데이터베이스에서 동시에 일어나는 트렌젝션을 일관되게 관리하는 방법
주요 개념
- 트랜젝션
- 데이터베이스의 상태를 변환하는 작업의 단위. ACID 속성을 보장함
- 원자성: 전부 성공하거나 전부 실패해야 함
- 일관성: 트랜젝션 완료 후에도 데이터베이스는 모든 무결성 제약 조건을 유지
- 격리성: 동시 실행되는 트랜젝션이 서로 간섭하지 않도록 보장
- 지속성: 트랜젝션이 성공적으로 완료된 후의 결과는 시스템 장애가 발생해도 영구 유지됨
- 분산 트랜젝션(Distributed Transaction)
- 여러 분산된 데이터 소스에 걸쳐 트랜젝션을 수행함
- 2PC (Two-Phase Commit)
- 분산 트랜젝션을 관리하는 프로토콜. 준비단계(prepare)와 커밋(commit) 단계로 나누어 트랜젝션 처리
- 준비 단계(Prepare Phase): 각 참여 노드는 트랜젝션 준비 상태를 확인하고, 준비 완료를 마스터 노드에 알림
- 커밋 단계(Commit Phase): 마스터 노드는 모든 참여 노드가 준비되었음을 확인하고 트랜젝션을 커밋하도록 지시함. 준비되지 않은 노드가 있다면 롤백
- 사가 패턴(SAGA Pattern)
- 트랜젝션을 여러 단계로 나누어 처리하고, 각 단계가 독립적으로 커밋함
- 실패 시 보상 트랜젝션을 실행하여 상태를 롤백
- 이벤트 소싱(Event Sourcing)
- 상태 변화를 이벤트로 기록하고, 해당 이벤트를 재생해 현 상태를 유지
단점
- 복잡성 증가
- 성능 저하: 2PC와 같은 프로토콜 사용 시 트랜젝션의 준비와 커밋 단계에서 지연이 발생할 수 있음
- 네트워크 오버헤드: 여러 시스템 간의 통신이 필요하므로 네트워크 오버헤드가 증가할 수 있음
- 복구가 어려움: 분산 트랜젝션 실패 시 모든 시스템에서 일관된 상태로 롤백하는 것이 어려울 수 있음
3-2. 이벤트 소싱
데이터 상태 변화를 이벤트로 기록하고 해당 이벤트들을 순차적으로 재생해 현 상태를 파악하는 방법
복잡한 비즈니스 로직을 수행하는 시스템에서 데이터 일관성과 추적 가능성을 높이는 데 유용함
복잡성이 증가할 수 있기 때문에 시스템 요구사항에 따라 신중하게 적용할 것
주요 개념
- 이벤트: 데이터의 상태 변화를 나타내는 기록
- 이벤트 스토어: 이벤트를 저장하는 저장소. 이벤트를 순서대로 저장
- 에그리게이트(Aggregate): 관련 이벤트를 모아 현재 상태를 재현할 수 있는 엔터티
- 도메인 모델의 일부분으로 이벤트를 적용해 상태를 변화시킴
- 커맨드: 에그리게이트에 특정 동작을 지시하는 명령어. 이벤트를 생성하는 트리거
- 프로젝션(Projection): 이벤트를 읽기 모델로 변환해 조회 성능을 최적화하는 방식
- 이벤트를 기반으로 읽기 전용 데이터베이스를 업데이트함
장점
- 데이터 변경 이력 추적에 용이
- 모든 상태 변화를 이벤트로 기록하기 때문에 데이터 변경 이력을 완벽 추적할 수 있음
- 복구 및 재생
- 이벤트를 재생해 시스템의 현상태를 복구할 수 있음
- 데이터 손실이나 시스템 장애 시 유용
- CQRS와의 자연스러운 통합
- 명령과 조회를 분리하여 성능과 확장성을 최적화할 수 있음
단점
- 복잡성 증가
- 읽기 성능
- 이벤트를 재생해 현 상태를 계산해야 하므로 읽기 성능이 저하될 수 있음
- 이를 위해 프로젝션과 CQRS를 활용할 수 있음
3-3. CQRS (Command Query Responsibility Segregation)
명령과 조회의 책임을 분리하는 소프트웨어 디자인 패턴
읽기 작업과 쓰기 작업을 서로 다른 모델로 분리하여 각 작업에 최적화된 구조를 사용할 수 있도록 함
주요 개념
- 명령(Command)
- 데이터를 변경하는 작업. 데이터베이스에 대한 쓰기 작업을 수행
- 데이터의 상태 변경을 담당함.
- 복잡한 비즈니스 로직을 포함할 수 있으며 데이터 무결성 보장을 위해 트랜젝션 사용
- 조회(Query)
- 데이터를 조회하는 작업. 데이터베이스에 대한 읽기 작업을 수행
- 조회 모델은 읽기 전용 데이터베이스 또는 캐시를 사용해 빠른 응답을 제공
장점
- 성능 향상: 읽기, 쓰기 작업 분리로 각 작업에 최적화된 데이터 저장소와 인프라 사용
- 확장성: 읽기, 쓰기를 독립적으로 확장할 수 있음
- 읽기 요청이 많은 경우 조회 모델을 수평 확장하여 부하를 분한하는 등
- 유지보수성: 비즈니스 로직이 명령 모델에 집중되기 때문에 복잡한 상태 변경 로직 관리가 쉬움
- 데이터 일관성: 이벤트 소싱을 통해 상태 변경을 이벤트로 기록하고 이벤트 재생으로 현상태 유지가 가능
단점
- 복잡성 증가: 시스템 설계와 구현의 복잡성이 증가. 명령 모델과 조회 모델을 각각 설계, 관리해야 함
- 데이터 동기화: 명령 모델과 조회 모델간의 데이터 동기화를 위해 추가적인 구현과 관리가 필요함
4. 모니터링과 로깅
시스템 안정성 유지, 성능 최적화, 문제 예방 및 대응을 위해 필수
4-1. 모니터링
애플리케이션, DB, 캐시 등 각 컴포넌트의 성능을 모니터링
Prometheus, Grafana 등의 도구 이용
시스템 주요 지표(TPS, 응답 시간, 에러발생률)를 모니터링하고 이상 징후 감지 시 알림 받을 수 있음
주요 사항
- 실시간 상태 파악
- 자동 알림: 특정 임계치 초과 시 알림 받을 수 있음
- 성능 분석: 모니터링 데이터를 기반으로 시스템 성능 분석이 가능
- 병목 지점 파악
- 사전 예방
- 신속 대응 가능
4-2. 로깅
주요 이벤트 로깅으로 문제 발생 시 원인 추적이 가능
Elasticsearch, Logstash, Kibana 등을 사용해 수집, 저장, 분석할 수 있음
이를 기반으로 문제 발생 시 문제를 파악하고 해결하는 데 이용
주요 사항
- 이벤트 추적
- 디버깅 및 오류 해결
- 패턴 분석: 로그 데이터를 분석하여 사용자의 행동 패턴이나 시스템 성능 패턴을 이해할 ㅅ ㅜ있음
- 장기적 최적화: 로그 데이터를 장기적으로 분석해 최적화를 진행할 수 있음
- 문제 원인 분석
- 법적 및 규제 요구사항 준수: 법적으로 보관해야만 하는 데이터가 있음
5. 테스트와 배포
어디에서나 테스트와 배포는 중요하다.
일단 멀쩡히 잘 굴러가는지 확인해야 하고, 또 멀쩡히 잘 굴러가야 하기 때문이다.
5-1. 테스트
이전에 공부한 내용.
테스트코드 작성하기 / 테스트
간단하게 정리해보았다.
- 단위 테스트
- 시스템 개별 구성요소를 테스트. JUnit, TestNG 등의 도구로 자동화된 단위 테스트를 작성하고 실행
- 개발 초기 단계에서 발생할 수 있는 결함을 조기에 처리하는 데 유용함
- 통합 테스트
- 여러 구성 요소가 함께 동작하는 지를 테스트. 개별 구성요소의 상호작용 테스트
- @SpringBootTest 어노테이션 활용
- 인터페이스 간의 문제를 발견하는 데에 유용함
- 부하 테스트
- 시스템이 높은 트래픽 상황에서도 문제없이 돌아가는지 확인. Apache, JMeter 등의 도구 활용
- 시스템 성능 한계를 파악하고 병목 지점을 찾아 최적화 할 수 있음
- 회귀 테스트
- 새로운 코드 변경이 기존 기능에 영향을 미치지 않는지 확인
- 기존 테스트케이스를 자동화해 주기적으로 실행하며 코드 변경으로 인한 결함을 방지할 수 있음
- 사용자 수용 테스트
- 실제 사용자 환경에서 시스템을 테스트해 사용자가 요구하는 기능이 모두 제대로 동작하는지 확인
- 사용자 피드백 반영으로 시스템 최종 조정을 마치면 배포 준비 완료
- 시스템이 실제 운영 환경에서 기대한대로 동작하는지 확인하는 단계
5-2. CI/CD
지속적인 통합(CI, Continuous Integration)
- 변경 코드를 자주, 자동으로 빌드, 테스트하며 코드 변경 시점에서 발생할 수 있는 문제를 조기 발견, 해결함
- 개발 주기 단축, 코드 품질 향상의 이점
지속적인 배포(CD, Continuous Deployment)
- CI 파이프라인을 통해 검증한 코드를 자동으로 프로덕션 환경에 배포
- 코드 변경 사항을 빠르고 안전하게 프로덕션 환경에 적용하며, 새로운 기능을 신속하게 제공할 수 있음
Canary 배포
- 새로운 버전을 전체 시스템에 배포하기 이전에 일부 사용자에게만 배포하여 문제가 없는지 체크
- 문제 발생 시 빠르게 롤백
- 리스크를 최소화하면서 새로운 기능을 단계적으로 도입할 수 있는 방법
블루-그린 배포(Blue-Green Deployment)
- 두 개의 환경을 사용하여 하나는 현재 운영 중인 환경, 하나는 새로운 버전을 배포하는 환경으로 사용
- 새로운 버전을 그린 환경에 배포한 후, 모든 트래픽을 그린으로 전환해버림
- 문제 발생 시 블루 환경으로 롤백
- 무중단 배포를 가능케하며 배포 실패 시 신속한 복구 제공
롤링 배포(Rolling Deployment)
- 새로운 버전을 점진적으로 배포하여 각 서버를 순차적으로 업데이트함
- 시스템 가동 시간을 유지하며 점진적으로 새로운 버전을 도입할 수 있음
- 대규모시스템에서 무중단 배포를 구현하는 데 유용함
RabbitMQ
메시지 브로커
애플리케이션과 시스템 간에 메시지를 송수신하는 데 사용
메시지 큐(Message Queue)를 기반으로 하며, 주로 비동기 통신, 시스템 간 데이터 전달, 이벤트 기반 아키텍처를 구현하는 데 사용됨
역할
- 비동기처리
- 데이터를 비동기적으로 처리해 시스템의 응답성을 높임
- 부하 분산
- 여러 소비자에게 메시지를 분산시켜 시스템의 부하를 균형 있게 분산함
- 내결함성
- 메시지를 안전하게 저장하여 시스템 장애 시 데이터 손실을 방지함
주요 개념
- 메시지 브로커
- 메시지 생산자(producer)가 보낸 메시지를 받아 저장한 후, 이를 소비자(consumer)에게 전달
- 메시지의 신뢰성과 순서를 보장함
- AMQP (Advanced Message Queuing Protocol)
- AMQP 0-9-1 프로토콜 지원
- AMQP는 메시지 브로커와 클라이언트 간의 통신 규칙을 정의하는 표준 프로토콜
- 메시지 큐(Message Queue)
- 메시지를 queue에 보관
- 여러 consumer가 큐에서 메시지를 가져가 처리할 수 있음
주요 구성 요소
- Message: 전달되는 데이터 단위.
- Producer: 메시지를 생성하여 RabbitMQ로 전송.
- Exchange: 메시지를 큐에 라우팅함. 라우팅 방식은 Exchange 유형에 따라 달라짐.
- Direct: 특정 라우팅 키를 사용하는 메시지를 정해진 큐로 보냄.
- Fanout: 메시지를 모든 큐로 브로드캐스트.
- Topic: 패턴 매칭으로 메시지를 라우팅.
- Headers: 메시지 헤더의 특정 속성을 기반으로 라우팅.
- Queue: 메시지를 저장하는 버퍼. 메시지가 Consumer에 의해 처리될 때까지 대기.
- Consumer: 큐에서 메시지를 가져와 처리하는 역할.
- Binding: Exchange와 Queue 간의 연결을 정의함. Exchange에 메시지가 도착했을 때, 특정 Queue로 라우팅되도록 설정.
RabbitMQ의 주요 특징
- 유연성
- 다양한 메시지 패턴 지원: 여러 메시지 전달 패턴(단일 소비자, 다중 소비자, 라운드 로빈, 팬아웃 등)을 지원
- 다양한 프로토콜 지원: AMQP, MQTT, STOMP, HTTP 등을 지원
- 메시지 신뢰성
- 메시지 지속성(Durability), 확인(Acknowledgment), 복제(Replication)를 통해 메시지 유실을 방지
- 확장성
- 클러스터링을 통해 확장 가능. 여러 노드에서 메시지를 분산 처리할 수 있음
- 분산 아키텍처: 페더레이션, 셰어드 노딩을 통해 분산된 메시징 시스템을 구축할 수 있음
- 플러그인 지원
- RabbitMQ는 다양한 플러그인을 통해 인증, 모니터링, 메시지 TTL(Time-To-Live) 설정 등을 지원
- 관리 인터페이스
- 웹 기반 관리 대시보드를 제공하여 큐, 메시지, 연결 상태를 모니터링하고 관리할 수 있음
장단점
장점
- 다양한 언어와 프로토콜 지원
- 메시지 신뢰성을 보장함
- 플러그인을 통한 확장성
단점
- 러닝커브 !!!!!
- 설정 및 운영 복잡성
- 복잡한 설정: 초기 설정이 복잡할 수 있으며 클러스터링 및 분산 환경에서는 더 많은 설정 요구됨
- 성능 이슈
- 메시지 브로커 오버헤드: 모든 메시지를 중앙 브로커를 통해 전달하기 때문에 높은 트래픽 상황에서는 오버헤드가 발생할 수 있음
- 대량의 메시지 처리에서는 성능 이슈가 있을 수 있음(Kafka 등과 비교할 때)
- 운영 비용
- 리소스 소비: 메모리와 CPU 자원을 많이 먹을 수 있음. 충분한 리소스를 제공해야 함
- 모니터링 및 유지보수: 지속적인 모니터링과 유지보수가 필요함.
- 제한된 메시지 크기
- 메시지 크기 제한: 매우 큰 메시지 처리에는 제한이 있을 수 있음. 대용량 파일 전송에는 적합하지 않음
AMQP
메시지 지향 미들웨어(MOM, Message-Oriented Middleware)에서 사용되는 애플리케이션 계층 프로토콜
메시지 송수신의 신뢰성과 보안을 보장
주요 개념
- Message: 전송 데이터 단위
- Queue: 메시지를 저장하고 전달
- Exchange: 메시지를 큐에 라우팅
- Binding: Exchange와 Queue 간의 연결을 정의
Exchange
메시지 브로커가 메시지를 교환기에서 큐로 라우팅하는 방식
다양한 방식으로 메시지를 라우팅할 수 있으며, 주로 메시지의 라우팅 키와 바인딩 키 또는 패턴을 기반으로 작동함
Direct Exchange
- 라우팅 키가 정확히 일치하는 큐로 메시지를 전달
- 라우팅 키가 a인 메시지를 a라는 바인딩 키를 가진 큐로 전달하는 식
Fanout: 메시지를 모든 큐로 브로드캐스트
- 라우팅 키를 무시하고 교환기에 바인딩된 모든 큐로 메시지를 브로드캐스트
- 모든 바인딩된 큐로 메시지가 전달됨
Topic Exchange: 패턴 매칭으로 메시지를 라우팅
- 패턴에는 와일드카드()와 #가 사용됨
- 라우팅 키가 quick.orange.rabbit인 메시지는 바인딩 키가 .orange.*인 큐로 전달되는 식
Headers Exchange: 메시지 헤더의 특정 속성을 기반으로 라우팅
- 라우팅 키 대신 메시지의 헤더를 기반으로 메시지를 라우팅함
- 헤더 값과 바인딩된 헤더 값이 일치하는 큐로 메시지를 전달