일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 스프링 배치
- vm
- 배포
- spring cloud
- Container
- 컨테이너
- 가상화
- 데이터베이스
- 자바
- Spring Security
- 도커
- 스프링 시큐리티
- web server
- JPA
- Spring
- CS
- computer science
- spring batch
- HTTP
- ORM
- CI/CD
- 스프링 부트
- 스프링
- virtualization
- 백엔드
- Java
- mysql
- 웹 서버
- spring boot
- 영속성 컨텍스트
- Today
- Total
개발 일기
[분산 환경] 분산 환경에서 느슨한 결합을 위한 이벤트 기반 아키텍처 본문
[분산 환경] 분산 환경에서 느슨한 결합을 위한 이벤트 기반 아키텍처
개발 일기장 주인 2025. 3. 10. 14:06드링클리 프로젝트에서 MSA로 전환하면서 Feign으로도 다 처리가능한데 왜 다들 Kafka 비동기 처리에 목숨을 거는건지 잘 이해가 되지 않아 정리하게 됐다.
회원시스템 이벤트기반 아키텍처
우선 Micro-Service Architecture 왜 필요한가?
마이크로서비스는 애플리케이션을 느슨하게 결합된 서비스의 모임으로 구조화하는 서비스 자향 아키텍처(SOA) 스타일의 일종인 소프트웨어 개발 기법이다.
이때 마이크로서비스 얘기가 나오면 Event-Driven Architecture가 나오는 이유 또한 이 이벤트 기반 아키텍처가 느슨한 결합을 돕기 때문이다.
왜 느슨한 결합이 필요한데?
정보처리기사나 Software Engineering과목을 수강하면서 수도 없이 들은 Coupling 낮추기를 반복적으로 학습했었는데 사실 깊게 생각해보진 않았다.
그래서 예를 회원가입을 예로 들어보겠다.
회원 가입 시 첫번째, DB에 회원 정보 저장 / 두번째, 가입 축하 이메일 전송 / 세번째, 구독 마이크로서비스에 회원 정보 초기화 이렇게 3가지 작업을 처리한다고 가정해보자.
- HTTP 기반(FeignClient 등) 동기(Synchronous)처리
회원 가입을 처리하면서 가입 완료 처리를 하고, 이메일을 보낸 후 구독 마이크로서비스에 HTTP로 후속 처리를 요청하는 작업이 모두 동기적으로 처리된다면, 회원 가입 요청이 끝나기 위해서 이 3가지의 모든 작업이 순차적으로 모두 처리되어야 한다.
이로 인해 각 서비스의 응답 시간이 길어지고, 시스템 전반적으로 속도가 느려진다면 성능에 치명적인 영향을 끼칠 수 있다.
예를 들어, 이메일 전송 서버가 느리거나 알림 시스템이 다운된 경우, 회원 가입 요청 자체가 지연될 수 있습니다. - @Async나 이벤트기반 비동기(Asynchronous) 처리
비동기 처리는 각 후속 작업을 독립적으로 처리 할 수 있도록 한다.
즉, 회원 가입 요청이 들어온 경우 가입 완료 처리를 한 후 그 즉시 응답을 반환하며 나머지 작업인 이메일 전송 및 구독 마이크로서비스에 후속 작업 요청은 비동기적으로 처리된다.
이러한 것이 가능한 이유는 이메일 전송과 같이 즉시 처리할 필요가 없는 작업에 적합하다. 몇 초 늦어진다고 해도 별로 큰 문제가 발생하지 않기 때문이다.
이를 통해 서비스 간 결합도를 낮출 수 있으며 순차적으로 작업들이 처리되기를 기다리지 않기때문에 성능 이슈도 많이 개선될 것이다.
느슨한 결합을 위한 이벤트 기반 아키텍처
위와 같은 예시에서 위 행위의 주체는 회원이고 가족 계정에 대한 후속 행위가 필요하다.
그러나 위의 경우 두 도메인은 분리되지 않고 강한 결합을 이루고 있는 것을 확인할 수 있다.
그러나 이전에도 말했듯이 MSA는 해당 서비스의 비즈니스 로직에 대해 집중하기 위해 느슨한 결합을 이뤄야한다.
물리적으로 시스템이 분리되었지만 코드레벨의 호출이 동기적인 HTTP 통신으로 변경되었을 뿐 여전히 강한 결합을 이루고 있다.
그래서 이를 비동기로 처리한다고해도 쓰레드 레벨의 비동기를 해결할 뿐 회원 마이크로서비스에 여전히 가족 계정에 대한 후속 처리가 필요하다는 의도는 그대로 존재하고 있기에 강한 결합을 이루고 있다.
그렇기 때문에 메시징 큐를 떠올릴 수 있는데 그렇다고 무조건 느슨한 결합을 가져오는 것은 아니다.
위와 같이 본인인증이 초기화 될 시 가족 계정 탈퇴라는 메시지를 발생하고 가족 계정에서 해당 메시지를 구독하고 있다고 했을때
회원에 물리적인 의존관계는 제거 되었지만 여전히 논리적인 의존관계를 가지고 있기 때문에 여전히 강한 결합이다.
메시지 발행 시 의도가 담기게 된다면 이는 단순한 비동기 요청일 뿐 느슨한 결합을 가져다 주지는 않는다.
그래서 같이 가족 계정 탈퇴와 관련된 이벤트가 아닌 회원 본인인증 초기화라는 이벤트를 발행한 후 가족 계정 마이크로서비스에서 해당 본인인증 해제라는 이벤트를 구독하고 있다면 이는 느슨한 결합 이라고 볼 수 있다.
도메인 내 비관심사 분리
예시로 로그인 프로세스를 들어보자.
회원이 디바이스로 로그인할 경우 아래와 같은 플로우가 필요하다고 하자.
- 회원 로그인 히스토리 기록
- 동일 계정으로 로그인된 타 디바이스 로그아웃 처리
- 동일 디바이스의 다른 계정 로그아웃
- 로그인 처리
그런데 위와 같이 되었을 때 부가 정책들이 함께 포함되어 있기 때문에 도메인의 주행위가 무엇인지 파악하기 어렵다.
그래서 아래와 같이 주관심사를 찾고 부가적인 비관심사를 분리해야한다.
이때 비관심사는 내부 이벤트를 통해 처리해야한다.
이벤트 기반 처리 과정
우선 로그인이라는 도메인 행위에 의해 Login 내부 이벤트가 발행될것이다.
AWS SNS와 SQS를 사용하면 하나의 이벤트를 여러 개의 구독으로 분배하여 처리할 수 있다.
이번 예시 처럼, 특정 이벤트가 발생했을 때, 이를 처리해야 할 비관심사 작업 3가지가 있다. 이때 각 작업을 SQS 큐로 분리하여 전달하고, 각 작업은 이벤트 기반으로 비동기적으로 처리될 수 있다. 이렇게 분리된 큐에서 각 구독자는 자신이 구독한 이벤트만 수신하고 처리하므로, 작업들이 독립적으로 실행되며 시스템의 효율성을 높일 수 있다.
그 결과 이와 같이 도메인의 행위에 대한 응집을 증가 시키고 비관심사에 대한 결합을 낮출 수 있다.
이벤트 저장소의 필요성
만약 이벤트의 유실이 용납이 되지 않는 경우 이벤트 저장소가 꼭 필요하다. 아래 영상을 추가적으로 참고하면 좋을 것 같다.
https://www.youtube.com/watch?v=b65zIH7sDug&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC
'Back-End > Spring Cloud + MSA + Kubernetes' 카테고리의 다른 글
[분산 환경] 분산 환경에서의 트랜잭션 처리 (0) | 2025.03.10 |
---|---|
[Kafka] 느슨한 서버 간 통신을 위한 Message Queue - Kafka (0) | 2025.02.11 |
[Spring Cloud] Spring Cloud Config Server - 2 (Spring Cloud Bus & RabbitMQ) (0) | 2025.02.11 |
[Spring Cloud] Spring Cloud Config Server - 1 (0) | 2025.02.10 |
[Spring Cloud] Spring Cloud Gateway & Spring Cloud LoadBalancer (0) | 2025.02.10 |