2022. 12. 16. 00:16ㆍ프로그래머스/TIL
최근 팀 미팅 했을 때, 개인 프로젝트(AToZ 프로젝트)에 대해서 설명하는 발표시간을 가졌다.
내가 만든 프로젝트는 의류 주문 관리 프로젝트였다. 다음과 같은 피드백을 받았다.
- Order의 validate에 대해서 잘 생각을 해보자 -> 들어온 가격이 주문에서 필요한 가격과 일치하는지, 더 들어왔는지 덜 들어왔는지 등
- 특히 가격에 관리된 것 -> order에도 가격이 필요할 것 -> 나중에 쿠폰도 들어가면 total 금액을 order에 들고 있어도 달라짐
- 그리고 OrderStatus에 대한 부분도 더 고민할 것 -> 더 세분화될 수 있음. (출고 준비 중, 배송 시작, 출고 완료, 배송 완료 등)
- Product 카테고리도 더 세분화될 수 있는데 동적으로 만들어야함. Enum으로 만들 수 있는 부분과 아닌 부분을 잘 생각할 것. -> 동적으로 만들어져야 하는 부분과 아닌 부분.
- 동시성에 대한 것 => 진짜 중요함. (예) 상품 재고가 하나 남았을 때, 두 명이 동시에 접근하는 경우 누가 살 수 있는가?
그래서 진짜 중요한 동시성에 대해서 찾아보고 학습해보자아!
동시성 이슈란?
동시성 이슈는 주문 도메인에서 생각했을 때 재고가 하나 남은 상품을 사기 위해서 두 명의 유저가 접근을 하는 경우를 생각해보면 접근 시에 둘 다 재고가 하나가 남아있다고 판단할 것이고 둘 다 상품을 살 수 있을 것이다. 그러면 재고는 결국 음수인데 0으로 기록되는 경우가 생기고 둘다 주문에 성공하는 경우가 생긴다. 이런 경우 동시성 이슈라고 한다.
이 경우를 어떤 식으로 해결할 수 있을까? 해결방법을 알아보자.
동시성 문제 해결방법
일반 변수에 대한 동시성 이슈 해결 방법
static 변수를 공유하여 사용하는 경우 발생할 수 있고 이를 해결하기 위해서 Synchronized, Volatile, Atomic 클래스 와 같은 방식들이 있는데 Synchronized(임계 구역)와 Volatile은 성능 문제가 있어서 Atomic 클래스를 사용한다고 한다.
DB의 동시성 이슈
먼저 DB의 트랜잭션 성질과 격리 수준에 대한 내용을 공부하면 좋을 것 같다.
https://private-space.tistory.com/97
=> 해당 글을 읽어보자.
일반 변수에서 말했던 Synchronized로도 해결할 수 있다. 하지만 말했듯 성능이슈가 생길 수 있다.
그래서 Lock에 대해서 알아보자.
JPA Optimistic Lock, Pessimistic Lock
Optimistic Lock
낙관적 잠근은 데이터 갱신 시 충돌이 발생하지 않을 것이라고 낙관적으로 생각하고 Lock을 거는 방식이다.
DB에 Lock을 걸지 않고 Conrflict Detection에 가깝다고 볼 수 있다. 이를 사용하기 위해서 @Version을 Int, Long 타입의 변수를 구현해줌으로써 간단하게 구현이 가능하다.
주의 사항은 다음과 같다.
- 각 엔티티 클래스는 하나의 버전 속성만 있어야함.
- 여러 테이블에 매핑된 엔티티의 경우 기본 테이블에 배치되어야함.
- 버전에 명시할 타입은 int, Integer, long, Long, short, Short, Timestamp 중 하나여야 함.
JPA는 SELECT 시에 트랜잭션 내부에 버전 속성으 값을 보유하고 트랜잭션이 업데이트 하기 전에 버전 속성을 다시 확인함. 그 동안 버전 속성이 변경 되었으면 OptimisticLockException이 발생, 변경 X -> 버전속성을 증가하는 업데이트.
Pessimistic Lock
비관적 잠금은 트랜잭션이 충돌 한다고 비관적으로 생각하고 우선 Lock을 거는 방법
트랜잭션 안에서 서비스 로직이 진행되어야하고 DB 수준에서 엔티티 Lock을 포함한다.
비관적 잠금은 3가지 모드가 존재한다. (모두 트랜잭션이 커밋되거나 롤백될때까지 유지)
- PESSIMISTIC_READdirty read가 발생하지 않을 때 마다 Shared Lock을 획득하고 데이터가 UPDATE, DELETE 되는 것을 방지.
- PESSIMISTIC_WRITEExclusive Lock을 획득하고 데이터를 다른 트랜잭션에서 READ, UPDATE, DELETE 하는 것을 방지.
- PESSIMISTIC_FORCE_INCREMENTWRITE와 유사한데 @Version이 지정된 엔티티와 협력하기 위해 도입 -> 잠금 획득 시 버전 업데이트
- JPA Lock에 대한 오해를 말한다 읽어보면 좋을 것 같다.
https://catch-me-java.tistory.com/60
내가 받은 피드백과 거의 유사한 부분에 관한 내용을 담고 있다 읽으면 좋을 것 같다.
'프로그래머스 > TIL' 카테고리의 다른 글
[좌충우돌 개발일지 - Spring Security] 로그아웃, 쿠키 기반 자동로그인 (rememberMe) (0) | 2022.12.14 |
---|---|
[좌충우돌 개발일지 - Spring Security] DelegatingPasswordEncoder (0) | 2022.12.14 |
[좌충우돌 개발일지 - Spring Security] WebSecurityConfigurerAdapter - Deprecated (0) | 2022.12.14 |