studybook
  • Introduction
  • 실무 하며 깨닫는 부분 정리
    • 옵션에 대해서
    • 코드 작성의 순서
    • 자바 프로그램에 문제가 생겼다면
    • 장애 대처법
  • Logstash, Beats 정리
  • Zookeeper 정리
  • Message Queue 정리
    • RabbitMQ 삽질
  • Java 관련 정리
    • Java Primitive Wrapper class
    • Java NIO
    • Java8 Double colon operator
    • Effective Java
      • 4장
      • 5장
      • 6장 - Enum, Annotation
      • 7장 - Method
      • 8장 - 프로그래밍 일반
      • 9장 - Exception
    • Java8 Lambda expression
    • JDBC
    • Linux에서 WatchService 이상동작
  • Spring 관련 정리
    • Spring Bean init, destroy 순서
    • Spring Async Controller
    • Spring Executable jar 웹 개발 및 배포
    • Spring Boot Font 배포 에러
    • Spring AOP
      • Spring AOP로 모든 Request 로그 남기기
    • Spring Cache
    • Spring Cloud
      • Consul로 spring 설정 관리하기
    • Spring Test
      • Spring Test DirtiesContext
      • Spring Test MockBean, SpyBean
      • Spring Test Dynamic @Scheduled
    • Spring JDBC
    • Spring Validation
    • Spring Transaction Management
      • Spring with JTA 삽질
    • Spring에서 효율적으로 Static resource 관리하기
    • Zuul을 사용해서 Spring Reverse proxy 만들기
    • Spring Security
    • 스프링 어노테이션이 안 먹힐 때 의심해볼만한 것
    • Spring Data
    • Spring Webflux
      • Tobi 강연
  • 코드 리팩토링
    • 한번에 하나씩
  • 지속적 통합 (CI)
    • Jenkins pipeline 삽질기
  • Log Aggregator 정리
    • Flume 테스트
    • Fluentd 테스트
  • Web Socket 정리
  • Akka
    • Actor 모델
    • Supervision
  • IE 8 대응 정리
  • 함수형 프로그래밍
    • 모나드
  • Netty
    • Netty 기본 예제
    • Netty 주요 특징
    • Netty 부트스트랩
    • Netty 채널 파이프라인, 코덱
    • Netty 이벤트 모델
    • Netty 바이트 버퍼
  • 스칼라 관련 정리
    • Maven으로 컴파일하기
    • Scala def 괄호 여부의 차이
    • 스칼라 function, method 차이점
    • ScalaTest와 Spring 연동하기
    • Programming in Scala
  • J2S 컨퍼런스
  • Android
    • 테스트
    • NDK
  • DDOS
  • HTTP
  • HttpClient
  • Container
    • Image 개요
    • cri-o
    • kata containers
    • Open Container Initiative Image
    • Buildkit
  • Github pages
  • Static Website
  • Webhook
  • Service Discovery Tools
    • Etcd
    • Eureka
    • Consul
      • ACL
    • 비교
  • React
    • JSX
    • React Element
    • Components, Props
    • State, Lifecycle
    • Handling Event
    • Flux
  • Vagrant
    • SSH 접속
  • Linux
    • Systemd
    • Alternatives
  • Messaging protocols
    • XMPP
    • AMQP
  • Windows
    • Windows10 내장 우분투에 ssh 클라이언트로 접속하기
    • Windows10 Hyper-V와 Virtual Box가 충돌을 일으켰을 때
    • Hyper-V 기반 docker에서 Shared Drives 설정 실패할 때
    • 윈도우 개발환경 설정
    • Docker desktop 없이 docker 환경 세팅하기
    • UWP 앱을 항상 관리자권한으로 실행하는 바로가기 만들기
  • Spring camp 2017
    • Project Reactive
    • 이벤트 소싱
    • CQRS
  • Spring webflux
  • 리액티브 프로그래밍
  • Linux Settings
    • 홈서버 백업 및 복구기
    • 홈서버 트러블슈팅
  • Kubernetes
    • k3s 설치 및 삽질
    • pod resources
    • Argo workflow
    • 트러블 슈팅
      • Kubernetes namespace의 phase가 Terminating에서 멈춰있을 때
    • 쿠버네티스 마스터
    • Knative
    • Knative Pipeline
    • Aggrerated API server
    • Accessing the API
      • Authenticating
  • Sonarqube
  • HTTP/2
  • Go
    • Go Module
    • Go dependency injection
    • Go Error handling
    • Go in Action
      • 3장 패키지
      • 4장 배열, 슬라이스, 맵
      • 5장 GO의 타입 시스템
      • 6장 동시성
      • 7장 동시성 패턴
      • 8장 표준 라이브러리
      • 9장 테스트와 벤치마킹
    • Go Channel 사용법
  • Cloud Native
Powered by GitBook
On this page
  • CQRS (Command Query Responsibility Segregation)
  • 단점
  1. Spring camp 2017

이벤트 소싱

  • 상태를 변경할 때 따로 로그를 남기는 경우가 있지만 트랜잭션이 아니고 또 개발자가 선택한 정보만 남기기 때문에 데이터 유실 가능성이 있다.

  • 이벤트 소싱은 도메인에서 발생하는 모든 액션을 이벤트로 바꾸고, 이벤트 저장소에 저장하고, 이벤트 핸들러에 의해서 상태가 변경되는 것.

    • 전통적으로는 state를 저장. 이벤트 소싱에서는 이벤트를 저장.

    • 예를 들어 장바구니 기능이라면 전통적으로는 장바구니의 상태를 저장하지만 이벤트소싱은 아이템 추가, 삭제에 대한 이벤트만 저장하고 결과가 필요하면 리플레이를 돌려서 상태를 생성하게끔 함.

  • 도메인 오브젝트 하나당 하나의 이벤트 스트림

  • 커맨드가 들어오면 validation을 거쳐서 이벤트를 생성 후 이벤트 저장소에 저장. 만약에 수행 불가능한 상태라면 오류 반환

  • 이벤트 자체는 돌이킬 수 없는 사실. 불변 객체. -> 따라서 항상 성공하며, 과거형을 사용한다.

  • 결과를 만들땐, 초기값으로부터 버전 n까지 모든 이벤트를 순차적으로 집계한 결과. 즉 최신이라면 모든 이벤트를 불러와서 적용시키면 된다.

  • 이벤트를 저장하면서 동시에 핸들러로 보내서 상태를 변경하게 함.

    • 이렇게 되면 결국 이것도 원자성은 없어지는게 아닌가?

  • 보통 RDB에 저장할 땐 키에는 오브젝트 아이디와 버전, 밸류에는 이벤트 타입과 직렬화된 전체 페이로드

  • 아주 오랫동안 살아남은 도메인 오브젝트가 있다면?

    • 엄청난 갯수의 이벤트를 가지고 있음

    • 덕분에 성능에 굉장한 영향을 끼침

    • 저장하는데도 큰 용량을 차지함

    • 1 <= m <= n 일 때, state(n) = state(m) + eventIterator(m, n)

    • 칼레이도에서 봤던 것처럼 일종의 스냅샷으로 바꿔둘 수 있지 않을까?

  • 그래서 별도의 스냅샷 저장소를 두고 거기에 스냅샷을 저장해둔다.

  • 분산 시스템에는 두가지 어려운 문제가 있음. 메세지가 중복될 수 있고 순서를 보장할 수 없음.

    • 이벤트 소싱을 하더라도 정확히 메세지를 1번 전달하는 것은 해결하기 힘든 문제임.

    • 그에 대한 대안으로 적어도 1번 전달을 사용함. 이 경우 메세지가 중복될 수 있어서 메세지의 멱등성을 보장해야만 함.

    • 즉, add(5) 이런 이벤트가 되면 멱등성을 보장할 수 없기 때문에 set(15)와 같은 이벤트가 되어야 함.

    • 이벤트 소싱을 쓰게 되면 모든 이벤트가 저장되므로 이 경우 유리함. 전통적 방식이면 일부 set 이벤트를 유실할 수도

  • 이벤트 스트림 - 메세지 브로커 - 컨슈머 구조? 이렇게 되면 1 이벤트에 1 컨슈머를 보장하는게 가능함.

CQRS (Command Query Responsibility Segregation)

  • 만약 재고 10개 미만 상품 목록을 알려면?

    • 이벤트 저장소 풀 스캔하여 상품 하나하나 복원하여 고르면 되긴 하겠지만... 성능하고 어쩔

    • 따라서 이론적으로는 이벤트 소싱은 CQRS에 독립적이지만 그렇게 되면 위와 같은 케이스에 대응할 수가 없음.

  • 원래는 CQS라는게 있었음. 즉, 쿼리가 상태를 변경하지 않는다. 어떤 의미에서는 getter, setter같기도. 메소드를 두 그룹으로 나눠서 하나는 결과만 리턴하고 하나는 상태만 변경하고.

  • CQRS는 CQS에서 더 나아가서 객체 단위에서 나눠버리는 것. 그 이상으로 가면 아예 시스템, 어플리케이션단위에서 구분해버리는 것.

  • 즉 Command Side, Query Side 두 시스템으로 나누어짐.

  • Command side는 클라이언트에서 커맨드가 들어오면 도메인 레이어에서 이벤트 스토어에 저장하기만 함. 그 이후에는 Query side로 이벤트 전송

  • Query Side는 이벤트들을 받아다가 뷰를 만들고 유지함. 덕분에 오직 조회 편의성만 신경씀. 클라이언트가 뭔가 데이터가 필요하면 여기로 보내서 받아감.

  • 하나의 read 모델이 여러 도메인의 이벤트 스토어를 가지고 있을 수 있음. 이렇게 되면 조인같은게 쉽게 가능.

  • 또한 하나의 도메인 이벤트 스토어는 어떻게 저장하든 그 형식에 구애받지 않음.

단점

  • 익숙하지 않고

  • 학습 곡선이 가파르고

  • 모든 과정이 비동기이고

  • eventual consistency이기 때문에 중간중간에 맞지 않을 수 있고

  • 과도한 엔지니어링이 발생하므로 모든 곳에 적용하려고 하지 말고.

  • RDB의 유일성 제약을 걸 수가 없어서 데이터 중복 막기 쉽지 않고

  • 이미 만들어져있는 도구가 적다.

PreviousProject ReactiveNextCQRS

Last updated 7 years ago