본문 바로가기

PHP

[Laravel]CQRS 적용, Elasticsearch (1)

개요

개발 규모가 커짐에 따라 나타나는 문제의 하나로, 레코드 수 증가데이터베이스 쿼리 복잡화로 인한 응답 속도 지연이 있습니다.

웹 서비스의 규모 확대에 따라 검색이 복잡해지고, 출시 시에는 문제가 되지 않았던 대규모 데이터 검색이나 문장 검색 시에 일반적으로 사용하는 Like 검색, 구현 코드의 복잡성 증가 등에 의한 성능 저하가 해당 됩니다.

CQRS(커맨드 쿼리 책임 분리)

Command(쓰기): 데이터베이스 입력

Query(읽기): 데이터베이스 검색 

애플리케이션 규모에 관계없이 데이터 입출력은 변하지 않으며, 보통 RDBMS를 사용해 쓰기 읽기가 함께 사용됩니다.

 

Command 할땐 정확하지 않는 데이터가 발생하지 않도록 제약이나 정규화를 하면서 테이블 설계를 수행합니다.

하지만, 실무에선 검색 효율을 생각해 설계했던 DB 와 상반된 검색용 테이블이 되기도 하며, 때로는 양쪽(검색용, 기존 테이블)을 담보하기 위한 코드를 구현함에 따라 코드가 점점 복잡해지기도 합니다.

 

애플리케이션 개발시, 데이터 쓰기보다는 대규모 데이터베이스의 모든 레코드를 대상으로 검색 하거나, 읽기가 대부분인 웹 애플리케이션에서는 확장하기 쉬운 읽기와 함께 구현 코드의 유지보수성과 확장성을 보장 해야합니다.

 

이에 대응하기 위한 CQRS 설계 패턴으로,  읽기와 쓰기를 별도로 처리하는 방법입니다.

CQRS 기본 개념

 

Command 는 확실한 데이터 쓰기와 정합성을 보장하는 RDBMS를 선택하고, 

Query를 담당하는 데이터베이스는 성능을 고려해 엘라스틱서치 같은 전문 검색 엔진 등을 선택하며, 현재 일반적으로 널리 사용되는 패턴입니다.

 

이런 문제 해결을 위해 간단하게 CQRS를 구현해보겠습니다.

CQRS 설계 패턴

여기에서는 간단한 테스트를 위해 위의 그림의 패턴으로 처리 하지만

실무에서라면 애플리케이션 규모에 따라 구성을 변경해야합니다. 예로들어, Command 실행시 Mysql에 쓰고 큐를 이용해 이벤트 처리 하는 등으로 흐름을 구성하면 수많은 트랙잭션이 발생하게 됩니다.

 

실무 적용 흐름

따라서, 실제로는 큐에서 이벤트만 발생시키고 각 데이터베이스에 써넣은 뒤 가공 처리를 해야합니다

이때 장애 대응 등을 위해 과거 이벤트 내역을 저장합니다. 라라벨 큐를 이용해 동일한 큐를 여러 처리에서 동시에 Subscribe하거나 과거의 큐를 보존할 때는 라라벨 큐가 아니가 래빗MQ 나 Kafka 같은 메시징 미들웨어를 선택해야합니다.

 

다음장부터 구현을 진행합니다.