1. 느슨한 결합을 위한 노력
예시 정책.
1. 회원 도메인과 가족계정 도메인이 있다.
2. 회원의 인증정보가 초기화되면 가족계정에서 탈퇴된다.
1단계. 모놀리틱한 구조(그저 동기적인 코드로 구현)
회원의 인증이 초기화되면 -> 가족계정 서비스에서 탈퇴된다.
이 행위의 주체는 회원이다.
즉, 회원 본인인증 해제 로직과 가족계정 탈퇴 로직이 강한 결합을 이루고 있다.
2단계. 시스템의 물리적인 분리
물리적으로는 분리되었지만 코드레벨의 호출이 HTTP 요청에 의한 호출로 변경되었을 뿐 여전히 강한 결합이다.
3. 비동기 HTTP 요청
비동기로 구현된 HTTP 요청은 쓰레드레벨의 의존을 제거할 뿐 여전히 강한 결합이다.
4. 메시지 큐를 사용한 요청
회원 인증 초기화시 가족계정 탈퇴를 요구하는 메시지를 발행함으로 물리적인 결합은 제거되었지만 논리적으로는 강하게 결합된 상태다.
회원인증을 담당하는 도메인에서 가족계정을 담당하는 도메인에서 해야할 작업을 명시하고 있으니까 말이다.
주의해야할 것.
요청을 위해 발행한 메시지가 대상 도메인에게 바라는 행위를 담은 메시지라면 그저 비동기 구조일 뿐,
우리가 다루고자 하는 이벤트가 아니다.
.
.
.
.
.
.
.
5. 드디어 느슨한 결합
메시지큐에 똑같이 메시지를 발행하였지만 4단계와 다른점이 있다면
회원 도메인에서 발행한 메시지는 가족계정의 탈퇴를 지시하는 메시지가 아니라 그저 "회원인증 초기화"를 알리는 메시지라는 점이다.
출처:
2. 이벤트란?
여기서 말하는 이벤트는 다음과 같다.
밥을 먹고 설거지를 하는 서비스라면
밥을 먹고나서 "설거지를 하라"는 이벤트를 발행하는 것이 아닌
"밥을 먹었다"라는 이벤트를 발행하는 것이다.
다른 예시로,
경찰관이 자동차에게 "직진하라"는 이벤트를 발행한다면,
이렇게 차들이 많아지면 이벤트를 발행하는 경찰관에게는 부하가 걸리게 된다. 차 하나하나마다 발행을 해줘야하기 때문
하지만, 신호등은 우리에게 이벤트를 발행하지 않는다. 정확히 말하면 경찰관처럼 우리에게 직진하라고 지시하지 않는다.
그저 지금이 빨간불인지 파란불인지만 알려줄 뿐 자동차가 신호등을 관찰하다가 판단한다.
따라서 신호등은 자신의 상태만 메시지로 발행하고 후속 행동은 이를 관찰하는 자동차들이 판단하여 처리한다.
한마디로 줄여서
"주목할 만한 상태를 이벤트로 발행한다"
고 보면 될 것같다.
AWS에서 발생하는 거의 모든 동작은 이벤트를 발생시킨다. 다음은 EC2의 생명주기 변경 이벤트이다.
출처:
3. 이벤트 드리븐 아키텍쳐의 이모저모
이벤트 드리븐 아키텍쳐의 제약사항
- 이벤트는 발생한 사건에 대해 약속된 형식 사용
- 불변 : 과거의 메시지를 변경할 수 없음
- 발생한 사건에 대한 결과 상태 전달
- 생성자는 이벤트를 누가 처리했는지 이벤트 처리 상태에 관여하지 않음
- 소비자는 이벤트를 누가 생성했는지, 생성자에 관심 갖지 않음
이벤트 드리븐 아키텍쳐 설계시 고려사항
Loosely coupling
- 한 모듈이 따른 모듈에 너무 종속적이면 안된다.
- 고려사항이라고는 하지만 비동기적인 프로그램을 하기 위해선 사실상 필수 사항
Removing dependencies
- 의존성을 제거
- 의존성을 제거 해서 Loosely한 coupling 상태로 만들어야 함
Nonblocking transaction
- 트랜잭션 단계에서 서로 영향을 주지 않도록 해야함.
- 회원가입을 할때, 핸드폰 인증을 하고 이메일 인증을 순차적으로 진행을 하는데 이메일 인증에서 오류가 났다고 해서 핸드폰 인증까지 같이 취소가 되면 안됨
Asynchronized callback
- 비동기 콜백은 필수는 아님
- 그러나 사용의 편리성으로 가장 많이 사용
Fallback /Retry
- 실패 했을 경우 어떻게 하고 어디까지 돌아가서 재시도 할것인가를 구분 지을 필요 있음
- 딱히 정해진 방식이 없어서 설계자의 능력이 중요
Event logging
- 비동기는 로그가 중구난방으로 찍히기 때문에, 이벤트 로그가 잘 찍히게 설계해야함.
이벤트 드리븐 아키텍쳐의 장단점
특징과 장점
- Sevice간 호출이 많은 Microservice Architecture에 적합.
- Infra Structure의 유연한 사용
- Polyglot 구성에 용이 -> 모듈별로 서로 다른 언어와 DB 사용 가능
- 가용성, 응답성 ↑ -> 효율성, 성능 ↑ -> 요청이 많아질 수록 성능 향상 기대
- Fault Isolation : 에러가 생겨도 각각의 모듈에 독립적으로 생기기 때문에 다른 모듈은 정상 가동이 가능
단점
- 설계 복잡도, 운영 복잡도 증가
- Message Broker 의존성 증가 ->Fault Isolation의 장점이 있어도 모든 Message가 모이는 Message Broker 자체가 고장나면 시스템이 멈춰버림
- 코드 가독성 하락 -> 눈에 익은 코드가 아니므로 코드 읽기가 어려움
- 디버깅 난이도 상승 -> 스텝투스텝으로 동기적으로 따라갈 수가 없고, 중구난방으로 로그가 찍히기 때문에 어디서 고장이 났는지 파악하기 힘듬
- log를 통한 system flow 가독성 하락
출처: https://be-developer.tistory.com/37
'Infra' 카테고리의 다른 글
[RabbitMQ] 블록체인 트랜잭션을 RabbitMQ를 사용하여 안전하게 처리하기 (0) | 2022.09.02 |
---|---|
[RabbitMQ] NodeJS와 Spring에 AWS RabbitMQ 적용하기 (0) | 2022.04.22 |
[Infra] 무중단 배포 방식(Rolling / BlueGreen / Canary) (3) | 2021.10.30 |
[Infra] 다중 서버 환경 (0) | 2021.08.25 |