본문 바로가기
아키텍처

이벤트 기반(pub/sub) 시스템 개발 경험 정리

by jinbro 2020. 12. 25.

이벤트 기반 시스템이란?


말 그대로 이벤트 기반으로 동작하는 시스템이다.
이벤트 발행 시 수신 채널들에서 해당 이벤트를 처리하도록 고안된 시스템!

API 시스템과는 차이점은 무엇이 있을까?

경험을 토대로 써봐야겠다.

첫번째 요청 처리 관점으로 비교 해보면

  • API는 요청 받음과 동시에 처리를 시작하고 응답해야한다.
  • 이벤트 기반 시스템은 곧바로 처리할 수도 있고, 일정시간 딜레이 주고 처리할 수도 있다.

두번째 확장성 관점으로 비교 해보면

  • API는 하나의 요청으로 하나의 처리 만을 할 수 있다.
  • 이벤트는 1개지만 이벤트 처리 시스템을 N개 만들면 여러 처리를 할 수 있음

이벤트 기반 시스템을 선택해야했던 이유는?


처리량을 제어할 수 있는 시스템이 필요했다.

오픈 초기에는 요청량이 적지만 점차 비즈니스에 따라 사용량이 크게 늘어날 것으로 예상되는 시스템 이었기 때문에 그에 대한 고려가 반드시 필요했다.

그럼 "서버 스케일 아웃 하면 되는거 아냐? 스케일업 하면 되는거 아냐?" 라고 생각할 수 있다.

물론 빠른 처리에 기준을 둔다면 그럴 수도 있겠지만 속도 보단 안정적인 처리(일정한 시간동안 일정한 처리량)가 필요했다.

이렇게 처리 하려면 협의 단계에서 실시간성이 보장되어야하는지 확인이 필요하다 ^_^;;


어떻게 만들었나?

  1. api 서버로 요청이 오면 협의된 이벤트로 맵핑 후 AWS 라이브러리 내 기능으로 SQS에 쌓음
  • SQS는 AWS에서 제공하는 Queue(FIFO) 서비스임
    • 이벤트큐를 만들기 굉장히 쉬움
    • 이벤트 N회 수신 후 처리 실패 케이스(이벤트) 큐 개념(dlq)이 있어서 장애 관련 대응이 쉬움
    • 이벤트에 대한 모니터링, 알람 설정(AWS CloudWatch 연동)이 쉬움
    • 이벤트 페이로드(SQS 정책 참고)에 따라 사용 가능 여부가 갈릴 수 있음

  • 예제 코드
    • TestSqsClient : AWS 라이브러리에서 제공하는 기능을 감싸는 객체
    • SQS url, SQS 에 실을 메세지 바디(이벤트 수신부에서 받을 수 있음) 설정만 해주면 됨
@Component
public class TestSqsClient {
    @Value("${aws.sqs.test-event-queue}")
    private String queueUrl;

    private AmazonSQSAsync amazonSQSAsync;

    @PostConstruct
    public void init() {
        amazonSQSAsync = AmazonSQSAsyncClientBuilder.standard().withRegion(Regions.AP_NORTHEAST_2).build();
    }

    public void sendMessage(Object message) {
        String messageBody = new Gson().toJson(message);
        SendMessageRequest req = new SendMessageRequest()
                .withQueueUrl(queueUrl)
                .withMessageBody(messageBody);

        amazonSQSAsync.sendMessage(req);
    }
}
  1. AWS SQS에 이벤트가 쌓이면 event worker가 해당 이벤트를 수신하여 비즈니스 로직 수행
  • 예제 코드
@Slf4j
@Component
public class TestEventListener {

    @SqsListener(value = "${aws.sqs.test-event-queue}", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
    public void receive(String event){
        // 로직 수행
    }
} 

참고로 위 구성은 경험상 가장 심플하고 빠르게 구성했을 때의 시스템안이고, 경우에 따라 SQS를 AWS SNS, 카프카 등 다른 큐로 변경할 수도 있고, 필요에 따라 다른 서비스나 혹은 시스템이 추가될 수 있다.


운영 해보니 장점은?

  • 인프라 레벨 쓰로틀링 가능함 : 속도 보단 안정적인 처리량이 우선 시 되었는데 워커를 특정 대수 만큼만 계속 유지하면 되었다. 강제적으로 일정 처리량을 유지하기때문에 과도한 이벤트로 인한 사이드 이펙트 발생 가능성을 줄일 수 있었다.

  • AWS SQS를 사용해서 쉽게 모니터링 지표 편집, 알람 설정이 가능했다 : 물론 이 장점은 SQS와 같은 제공되는 서비스를 사용해서 얻은 장점이지 이벤트 기반 시스템의 장점은 아니다(첫째로 언급한게 가장 큰 목표였고, 그 목표를 달성하는 과정에서 얻은 부가적인 장점이랄까...)

  • 장애 후처리가 비교적 쉽다는 것이다. API로만 이뤄진 시스템이었다면 API 서버 장애 후처리를 하려면 필요에 따라 클라이언트가 재요청(타 팀까지 모두 장애 전파가 됨)을 하던지 해야하지만 이벤트 기반 시스템은 내부적으로 이벤트 재발행하거나 dlq와 같은 개념으로 실패 케이스 재처리만 하면 되므로 비교적 쉽다는 것을 느꼈다.


단점은?

  • 에러 발생 시에는 기존 API 서버 시스템과는 달리 중간 계층이 비교적 많아 경우의 수가 많아져서 어려움을 겪을 수 있음 : 다행히 회사에서는 키바나 로그 시스템을 운영 중이고, 로그만 잘 찍도록 구현해두었다면 트래킹이 그나마 쉽다. 반대로 말하면 관련된 시스템이 만들어져있지 않거나 시스템 없더라도 로그가 심어져 있지 않으면 어렵다는 말...이다...

  • 관리 포인트가 늘어날 수 있다는 것 : 요청이 올 때마다 이벤트 - 이벤트 처리 워커 시스템을 구성한다면 끝없이 관리 포인트가 늘어날 수 있다. 무조건적인 재활용도 금물이지만 무조건적인 생성도 피하는 것이 좋다고 생각한다. 맡은 도메인에 따라 시스템을 어떻게 나눌건지도 늘 생각하면서 관리포인트가 필요 이상으로 느는 것을 항상 방지해야한다.


정리

  • 새로운 형태의 시스템 개발 경험을 갖게 되어서 좋았음
  • 어느 한 쪽만(API vs 이벤트) 선택해서 개발하는게 아니라 필요에 따라 접목 해서 개발 가능
  • 협의, 파악 단계에서 잘 정리해두어야 그에 맞는 개발 스펙을 빠르게 정할 수 있을 것 같다 라는 생각이 들었음


댓글