From d5c50bf0bb81e745f7ce083e54e1407048d29219 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Wed, 14 Aug 2024 14:43:31 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20main=20=EB=A8=B8=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chap08/README.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++- chap09/README.md | 1 - chap10/README.md | 1 - 3 files changed, 88 insertions(+), 3 deletions(-) delete mode 100644 chap09/README.md delete mode 100644 chap10/README.md diff --git a/chap08/README.md b/chap08/README.md index 3843a87..f86120a 100644 --- a/chap08/README.md +++ b/chap08/README.md @@ -1 +1,88 @@ -# 8. 애그리거트 트랜잭션 관리 \ No newline at end of file +# 8. 애그리거트 트랜잭션 관리 + +### 8.1 애그리거트와 트랜잭션 + +- 트랜잭션 처리 방식 + +1. 선점 방식 (비관적 락) 2. 비선점 방식 (낙관적 락) + +### 8.2 선점 잠금 + +- 한 트랜잭션에서 쓰기를 하는 동안 다른 트랜잭션에서는 잠금으로 대기 +- JPA에서는 EntityManager는 LockModeType을 인자로 받는 find()메서드르 제공함 + +```java +entityManger.find(Order.class,LockModeType.PESSIMISTIC_WRITE) +``` + +- for update 쿼리를 이용해서 선점 잠금을 구현한다. + +```java +@Lock(LockModeType.PESSIMISTIC_WRITE) +``` + +- 스프링 데이터 JPA는 @Lock 애너테이션을 사용해서 잠금 모드를 지정한다. + +**교착상태** + +- 선점 잠금에서 교착생태가 발생할 수 있음 +- 스레드 1, 2에서 각각 자원을 선점한 상태에서 서로 상대가 가진 자원에 대해 선점 잠금을 시도할 경우 발생함 +- 해결 방법 + 1. 잠금을 구할 때 최대 대기 시간을 지정해야 함 + 2. 각 잠금 순서를 일치시켜주면 데드락이 발생하지 않음 + +```java +// JPA 해결 방법 +Map hints=new HashMap(); + hits.put("javax.peristence.lock.timeout",2000); + Order order=entityManager.find(Order.class,LockModeType.PESSIMISTIC_WRITE) +``` + +- DBMS에 따라 힌트가 적용되지 않을 수가 있다. + +```java +//스프링 데이터 JPA는 @QueryHints 애너테이션을 사용해서 쿼리 힌트를 작성할 수 있다. +@Lock(LockModeType.PESSIMISTIC_WRITE) +@QueryHints({ + @QueryHint(name = "javax.peristence.lock.timeout", 2000) +} +) +@Query("selet m from Member m where m.id = :id) + OptionalfindByIdForUpdate(@Param("id) MemberId memberId) +``` + +### 비선점 잠금 + +- 동시에 접근하는 것을 막는 대신 변경한 데이터를 실제 DBMS에 반영하는 시점에 변경 가능 여부를 확인하는 방식이다. + +```java +UPDATE aggtable SET version=version+1,colx=?,coly=? + WHERE aggid=?and version=현재 버전 +``` + +- JPA는 버전을 이용한 비선점 잠금 기능을 지원한다. @Version 애너테이션을 붙이고 매핑되는 테이블에 버전을 저장할 칼럼을 추가하면 된다. + +```java +public class Order { + + @Version + private long version; + + ... +} +``` + +- 비선점 잠금 충돌 발생시 스프링 프레임워크에서 OptimisticLockingFailureException이 발생함 + +**강제 버전 증가** + +- 루트 애그리거트의 값이 바뀌지 않았더라다도 애그리거트의 구성요소 중 일부 값이 바뀌면 논리적으로 그 애그리거트는 바뀐 것이다. +- 따라서 애그리거트 내의 어떤 구성요소의 상태가 바뀌면 루트 애그리거트이 버전 값이 증가해야 비선점 잠금이 올바르게 동작한다. +- JPA의 경우 LockModeType.OPTIMISTIC_FORCE_INCREMENT를 사용하면 해당 엔티티의 상태가 변경되엇는지에 상관엇이 트랜잭션 종료 시점에 버전 값 증가 + 처리를 한다. +- 스프링 데이터 JPA에서는 @Lock 애너테이션을 이용해서 지정하면 된다. + +### 오프라인 선점 잠금 + +- 잠금 선점 시도, 잠금 확인, 잠금 해제, 잠금 유효시간 연장의 네 가지 기능이 필요하다 +![img.png](img.png) \ No newline at end of file diff --git a/chap09/README.md b/chap09/README.md deleted file mode 100644 index 78747ab..0000000 --- a/chap09/README.md +++ /dev/null @@ -1 +0,0 @@ -# 9. 도메인 모델과 바운디드 컨텍스트 \ No newline at end of file diff --git a/chap10/README.md b/chap10/README.md deleted file mode 100644 index c08b9ac..0000000 --- a/chap10/README.md +++ /dev/null @@ -1 +0,0 @@ -# 10. 이벤트 \ No newline at end of file From 4e067b66442aa8b3b0bf33712225ebc4c415ccf3 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Wed, 21 Aug 2024 17:18:13 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[Week=2010]=20CQRS=20-=20=EB=B0=95=EC=A4=80?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chap11/README.md | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/chap11/README.md b/chap11/README.md index e5b1c15..4f6703e 100644 --- a/chap11/README.md +++ b/chap11/README.md @@ -1 +1,42 @@ -# 11. CQRS \ No newline at end of file +# 11. CQRS + + +### 11. 1 단일 모델의 단점 + +- 시스템이 상태를 변경할 때와 조회할 때 단일 도메인 모델을 사용하기 때문 +- 객체 지향으로 도메인 모델을 구현할 때 주로 사용하는 ORM 기법은 도메인 상태 변경 기능을 구현하는 데는 적합하지만 주문 상세 조회 화면처럼 여러 애그리거트에서 데이터를 가져와 출력하는 기능을 구현하기에는 고려할게 많아서 구현을 복잡하게 만드는 원인이 됨 + +→ 구현 복잡도를 낮추는 간단한 방법 : 상태 변경을 위한 모델과 조회를 위한 모델을 분리하는 것 + +### 11.2 CQRS + +- Command Query Responsibility Segregation +- 상태를 변경하는 명령을 위한 모델과 상태를 제공하는 조회를 위한 모델을 분리하는 패턴 +- CQRS를 사용하면 각 모델에 맞는 구현 기술을 선택할 수 있다. +- 명령 모델 : 객체지향에 기반해서 도메인 모델을 구현하기에 적당한 JPA, + - 트랜잭션을 지원하는 RDBMS +- 조회 모델 : DB 테이블에서 SQL로 데이터를 조회할 때 좋은 마이바티스 + - 단순히 데이터를 읽어와 조회하는 기능은 응용 로직이 복잡하지 않기 때문에 컨트롤러에서 바로 DAO를 실행해도 무방하다. + - 조회 성능이 좋은 메모리 기반 NoSQL + +### 11.2.1 웹과 CQRS + +- 웹은 쓰기 요청 보다 조회 요청의 빈도수가 높음 +- 메모리에 캐싱하는 데이터는 DB에 보관된 데이터를 그대로 저장하기보다는 화면에 맞는 모양으로 변환된 데이터를 캐싱할 때 성능에 더 유리하다. + +### 11.2.2 CQRS 장단점 + +**장점** + +- 명령 모델을 구현할 때 도메인 자체에 집중할 수 있다는 점 +- 조회 성능을 향상시키는 데 유리하다는 점 + +**단점** + +- 구현해야할 코드가 더 많음 +- 더 많은 구현 기술이 필요함 + +**결론** + +- 도메인이 복잡하지 않은데 CQRS를 도입하면 두 모델을 유지하는 비용만 높아지고 얻을 수 있는 이점은 없다. +- 반면 트래픽이 높은 서비스인데 단일 모델을 고집하면 유지 보수 비용이 오히려 높아질 수 있으므로 CQRS 도임을 고려하자. \ No newline at end of file