Reading을 분리하자! - CQRS 도입기

윤태호·2023년 4월 28일
1

CRUD는 완벽한가요???

  • 필자뿐만 아니라 주니어 및 개발을 막 공부한 사람들은 JPA 및 MariaDB, Mysql 하나에서 CRUD를 완벽하게 하는 것도 벅찰 것이다!!
    필자도 완벽하게 JPA와 RDB의 다양한 기술을 완전히 익힌 것이 아니다. 누가 보기엔 오버 스펙으로 공부한다 생각하겠지만, 잠을 줄이면서라도 공부한다면 누가 말리겠는가...ㅎㅎ

왜 DB 분리를 생각했나요??

  • TechTalk을 진행하면서 CQRS에 대한 개념을 살짝 가지고 있었지만, Final Project를 하면서는 그 외에도 해야할 것이 많았기에 Project에 못 녹여내고 있었습니다.
    그러던 어느 날 Query DslJPA를 같이 쓰다가 순환참조의 문제를 겪게 되었습니다. 이를 해결하기 위해 다양한 방법을 썼지만 근본적인 방법이 없을까?!?! 하고 나의 강사님께 여쭤보았습니다. 강사님은 그 때 왜 모두들 Project에서 CQRS를 구현할 생각을 안하냐고 말씀하셨습니다. 왜냐하면 필자는 Query dsl로 거의 모든 Reading을 처리하고 있었고, JPACUD의 역할을 맡고 있었습니다. 그렇게 할 것이면 차라리 둘을 분리하는 것이 더 옳고 자연스럽게 MSA의 구조를 택할 수 있었습니다. 실제로 MSA의 책을 읽으면 CQRS와 이벤트 소싱에 대한 부분이 나옵니다.

분리하는 것은 좋다! 그러면 동기화 및 일관성은??

  • 분리하는 것은 좋은데 둘이 값은 동일해야하 데이터의 일관성이 유지됩니다.
    그러면 의문이 드는 것이 그것을 누가 어떻게 역할을 할 것인가????
    바로 여기서 등장하는 부분이 비동기 이벤트 처리입니다. 필자도 처음에 듣고 너무 생소했다. 그러면 비동기 이벤트 처리에 대해 잠시 짚고 넘어가보자!!

    동기화를 위해 우리는 서비스와 DB를 분리할 것인데, CUD의 DB에서 일어난 작업을 Reading의 DB에도 같이 일어나야 한다는 것입니다.
    그러면 CUD에서 일어난 이벤트를 Reading에 전달해 줘야합니다. 또한 추가적으로 비동기적이여야합니다. 왜냐하면 CUD에서 전달을 못하면 Reading의 서비스를 멈출 것인가?? 반대로 Reading에서 서비스가 멈추면 CUD를 멈출 것인가??? 이렇기에 비동기적으로 진행되어야 합니다.

  • 위에 CQRS로 필자가 이해한 비동기 이벤트 처리를 간단히 설명했지만, 심플하게 Sender와 Reciver가 존재하며 그 사이에서 Message 및 이벤트를 비동기적으로 처리해 주는 것으로 생각하면 편합니다.

비동기 처리 이벤트는 누가 지원하나??

비동기 처리 이벤트는 대표적으로 2가지가 널리 알려져있습니다.

  • Kafka
  • RabbitMq

개발자들은 위의 2개를 이용하여 비동기 이벤트 처리를 진행하는데요, 간단하게 둘의 공통점과 차이점을 보고 넘어가겠습니다.

  • 공통점
    - Message Que를 통해 데이터를 전송합니다. 그리고 이를 만들어내는 Producer(Sender),Consumer(Reciver)가 존재합니다.
  • 차이점
    - kafka는 pub/sub 방식 / RabbitMQ는 메시지 브로커 방식
    kafka의 pub/sub방식은 생산자 중심적인 설계로 구성. 생성자가 원하는 각 메시지를 게시할 수 있도록 하는 메시지 배포 패턴으로 진행
    RabbitMQ의메시지브로커방식은 브로커 중심적인 설계로 구성. 지정된 수신인에게 메시지를 확인, 라우팅, 저장 및 배달하는 역할을 수행하며 보장되는 메시지 전달에 초점
    - 전달된 메시지에 대한 휘발성
    RabbitMQ는 queue에 저장되어 있던 메시지에 대해 Event Consumer가져가게 되면 queue에서 해당 메시지를 삭제한다.
    하지만, kafka는 생성자로부터 메시지가 들어오면 해당 메시지를 topic으로 분류하고 이를 event streamer에 저장한다. 그 후, 수신인이 특정 topic에 대한 메시지를 가져가더라도 event streamer는 해당 topic을 계속 유지하기 때문에 특정 상황이 발생하더라도 재생이 가능하다.
    - 용도의 차이
    kafka는 클러스터를 통해 병렬처리가 주요 차별점인 만큼 방대한 양의 데이터를 처리할 때, 장점이 부각된다.
    RabbitMQ는 데이터 처리보단 Manage UI를 제공하는 만큼 관리적인 측면이나, 다양한 기능 구현을 위한 서비스를 구축할 때, 장점이 부각된다.
  • 필자는 Consumer가 꺼져있거나, 응답을 못해도 이벤트 및 메세지가 반영구적으로 저장되어있다가, 처리가 가능하기를 원했기에 RabbitMq보다 Kafka를 택하게 되었다.

Reading의 최적화 된 DB를 찾아라!

CQRSReading의 서비스와 DB를 분리하기로 했는데, 똑같은 RDB를 쓰는 것은 말이 안된다. 그러면 이제 과연 Reading(조회)에 최적된 DB가 무엇인지 생각해야한다.
후보로는 NoSQL, Redis, Elastic Search를 생각해냈다.

위의 세가지의 DB는 RDB의 높은 조회 속도를 자랑한다. 왜냐하면 Key-Value 및 Index를 통해 데이터를 조회하기에 기존 RDB는 모든 데이틀 무선 가져와서 찾아내기에 위의 세가지 보다 느리다.

필자는 Elasic Search를 택했는데 다른 DB를 택하지 않은 이유와 같이 설명하겠다.

  • Redis도 높은 조회 속도를 자랑하지만, InMemory DB이기에 나중에 대용량 데이터가 들어오게 된다면, Memory 용량을 감당할 수 없다.
  • NoSQL도 훌륭한 대체재였지만, 검색에 특화된 Elastic search의 인덱스화 및 Tokenizer, Analyzer를 활용하고 경험해보고 싶었습니다.

Elastic Search + Logstash + Kibana?

ElasticSearch를 Reading을 위한 DB로 선택한 이후 공부를 진행하는 과정에서 끊임 없이 같이 등장하는 것은 ELK 스택이였다.
ELK 스택이란??

  • ElasticSearch + Logstash + Kibana를 합친 기술스택을 뜻하며, Log 수집 및 분석 그리고 시각화를 한번에 할 수 있는 스택이다.

필자도 단순히 Elastic Search만 활용하는 것이 아닌, 요새 IOT의 시대에 쏟아져 나오는 데이터 및 로그들을 분석하고 시각화 할 수 있는 ELK의 스택을 도입하기로 하였습니다.

이제 데이터의 파이프를 구축해보자!!!

드디어 CQRS의 구조 구축을 위한 각각의 Open Source 기술을 선정하였습니다.
이제는 이 OpenSource를 활용하여 어떻게 데이터를 주고 받고 읽어낼 것인지를 위한 Pipeline을 구축해야 했습니다.
필자는 Spring Boot, AWS의 EC2, MariaDB, AWS의 MSK, AWS의 Elastic Search, Docker, Logstash들을 활용하여 데이터 전송을 위한 Server 구축과 Infra 구축을 완료하였습니다. 아래의 그림을 보시면 이해가 쉬울 것입니다.

글을 마무리 하며

필자의 CQRS의 도입기는 이제 시작입니다. 왜 이런 프로젝트를 시작하게 되었는지 그리고 어떻게 구상하였는지에 대해, 간단하게 설명드렸습니다. 위의 내용은 정말 어렵고 제가 설명하거는 극히 일부분이기에 만약 이 글을 읽으신다면, CQRS부터 천천히 다시 공부해보시면서 시작하는 것도 좋을 것 같습니다.
다음 글은 CUD 부분의 Server 및 Infra와 Kafka가 기다리고 있으니 기다려주시길 바랍니다!!!!!!
그리고 마지막으로 단순 CRUD를 잘하는 것도 매우 중요하지만, 빠르게 변화하는 IT의 세계에 고도화된 기술을 스스로 공부하는 자세도 중요하다고 생각합니다 ㅎㅎ
같이 공부해나가면 좋겠습니다!!!

profile
성장하는것을 제일 즐깁니다.

0개의 댓글