인프런 커뮤니티 질문&답변

gelab님의 프로필 이미지

작성한 질문수

재고시스템으로 알아보는 동시성이슈 해결방법

재고감소 로직작성

동시성 문제 해결방안

작성

·

89

·

수정됨

0

 

@Transactional
public void decrease(Long id, Long quantity) {
    Stock stock = stockRepository.findById(id).orElseThrow();
    stock.decrease(quantity);

    stockRepository.saveAndFlush(stock);
}

현재 강의 코드인데, 락을 사용해서 해결을 할 수도 있지만, 그냥 아래와 같이 JPQL을 사용해서 해결할 수 있지 않나요?

@Transactional
public void decrease(Long id, Long quantity) {
    Stock stock = stockRepository.findById(id).orElseThrow();

    if (stock.getQuantity - quantity < 0) {
        throw new RuntimeException("재고는 0개 미만이 될 수 없습니다.");
    }

    stockRepository.decrease(id, quantity);
}
@Modifying
@Query("UPDATE Stock s SET s.quantity = s.quantity - :quantity WHERE s.id = :id")
public void decrease(@Param("id") Long id, @Param("quantity") Long quantity);

락을 사용하는 것보다 이렇게 하는게 비용이 더 적을 것 같은데, 이렇게 하지 않는 이유를 알 수 있을까요??

답변 2

0

최상용님의 프로필 이미지
최상용
지식공유자

gelab 님 안녕하세요!
말씀하신대로 native query 를 사용해서 해결할수도 있습니다.
다만, native query 를 사용할때는 아래와 같은 조건으로 해야할것 같습니다.

@Query("UPDATE Stock s SET s.quantity = s.quantity - :quantity WHERE s.id = :id and (s.quantity - :quantity) >= 0")

또한, 이 강의는 동시성이라는 주제를 다루기위하여 "재고" 라는 아이템을 선택한것이지 "재고"를 다루려면 무조건 lock 을 잡아야한다는 아니었습니다!

감사합니다.

 

0

안녕하세요, 인프런 AI 인턴입니다.

님의 질문과 관련하여, JPQL을 사용하여 동시성 문제를 해결하는 방안에 대해 설명드리겠습니다. JPQL을 사용하여 데이터를 직접 업데이트하는 방식은 실제로 동시성 처리에 있어서 비용이 덜 드는 방식일 수 있습니다. 하지만 몇 가지 고려해야 할 사항들이 있습니다.

첫째, JPQL로 직접 업데이트할 경우, 영속성 컨텍스트(Persistence Context)와 데이터베이스 간의 동기화 문제가 발생할 수 있습니다. 영속성 컨텍스트는 엔티티의 상태를 관리하며, 이 상태가 데이터베이스와 일치한다고 가정합니다. 하지만 JPQL을 통해 데이터베이스를 직접 업데이트하면, 영속성 컨텍스트가 알지 못하는 상태로 데이터가 변경되어 데이터 일관성 문제가 발생할 수 있습니다.

둘째, JPQL을 사용한 업데이트는 비즈니스 로직이 데이터베이스 계층으로 내려가게 만들 수 있습니다. 이는 계층화된 아키텍처 원칙에 어긋날 수 있으며, 유지보수성과 코드의 명확성 측면에서도 불리할 수 있습니다.

셋째, @Modifying 어노테이션을 사용할 때 자동으로 EntityManager를 클리어하지 않으면, 영속성 컨텍스트에 남아 있는 엔티티와 실제 데이터베이스의 데이터 간에 불일치 문제가 생길 수 있습니다. 이를 해결하기 위해 @Modifying(clearAutomatically = true)를 사용하여 문제를 해결할 수는 있지만, 이는 추가적인 고려사항을 필요로 합니다.

그럼에도 불구하고, 특정 상황에서는 JPQL을 사용하여 동시성 문제를 해결하는 것이 유리할 수 있습니다. 특히, 대량의 데이터를 처리해야 하고 비즈니스 로직이 간단할 경우, 또는 락을 사용하는 것보다 성능 상의 이점이 명확한 경우 등이 그 예시입니다. 하지만 이러한 접근 방법을 선택하기 전에는 어플리케이션의 전반적인 아키텍처, 유지보수성, 데이터 일관성 보장 등을 종합적으로 고려해야 합니다.

Information provided does not directly answer your question about not choosing JPQL for concurrency issues, so please consider the above points as a general consideration on using direct database updates with JPQL in context of JPA and concurrency management.

gelab님의 프로필 이미지

작성한 질문수

질문하기