🧑🏻‍💻 낙관적 Lock 이란?

<aside> 💡 DB의 Lock을 사용하지 않고 Version 관리를 통해 애플리케이션 레벨에서 처리

</aside>

Version 관리

낙관적 Lock 진행

낙관적 Lock 전체 코드

  1. Product에 version 추가
	//버전 칼럼 추가
    @Version
    private Long version;
  1. 결제 할 상품을 찾을 때, 낙관적 LOCK을 건다.
@Lock(LockModeType.OPTIMISTIC)
@Query("select p from Product p where p.id = :productId")
Optional<Product> findByIdWithOptimistic(@Param("productId") Long productId);
  1. findByIdWithOptimistic를 사용하여 결제할 상품을 DB에서 조회한다.
@Transactional
    public int orderProduct(String pgToken, Long memberId){

		' ' ' ' '

        Product product = productRepository.findByIdWithOptimistic(Long.valueOf(productId))
            .orElseThrow(() -> new ProductNotFoundException(ErrorCode.PRODUCT_NOT_FOUND));

		' ' ' ' '

        product.saleProduct(); //쿼리 2
        paymentHistoryRepository.save(paymentHistory); //쿼리 1
        return product.getStock();
        //트랜잭션.커밋
    }
}
  1. 낙관적 Lock 테스트 코드

    // 동시성 테스트 시작 ====================================================================
    int threadCount = 3; //3개의 Thread도 테스트 후 점차 늘려나간다.
    ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
    CountDownLatch latch = new CountDownLatch(threadCount);
    
    List<Exception> exceptionList = new ArrayList<>();
    
    for (int i = 0; i < threadCount; i++) {
            executorService.submit(() ->{
            try {
                paymentService.orderProduct("asg", member.getId());
            } catch (Exception e) {
                e.printStackTrace();
                exceptionList.add(e);
            } finally {
                latch.countDown();
            }
        });
    }
    
    latch.await();
    Assertions.assertThat(exceptionList.get(0) instanceof OptimisticLockingFailureException);
    

🚀 트러블 슈팅

1. Mock Test → Spring Boot Test

@SpringBootTest, @MockBean, Mockito, Junit 등 테스트에 대해서…

2. DeadLock 문제

3. TestCode 수정 및 의미 공부