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

요니님의 프로필 이미지
요니

작성한 질문수

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

Optimistic Lock 활용해보기

OptimisticLockStockService에서 @Transactional을 붙이게 되면 무한루프에 빠지는 이유 질문

작성

·

340

0

안녕하세요 강사님.
강사님 강의를 예전에 들었는데 ,
현업에서 실제 동시성 처리를 하려고 다시 보니
예전에 안보이던게 보이는 것 같습니다. 감사합니다.

제가 질문하고 싶은 부분은
강의를 들으면서 습관적으로
OptimisticLockStockService에서 @Transactional을 붙였는데 무한루프에 빠졌습니다.

앞의 질문에 대한 답변으로 강사님이 보내주신
답변을 힌트로 그 원인을 생각했는데 ,
이부분에 대해 피드백을 주시면 감사하겠습니다.

제가 이해한 바로는 OptimisticLockStockFacade에
@Transactional을 붙이게 되면,
트랜잭션이 재시도 로직을 포함해서 묶이면서,
version 차이로 재시도를 할 때 새로운 버전으로 Stock을
조회해와야 하는데,
아직 Transactional이 유지되고 있으니깐,
Entity Manager에 있는 이전에 실패한 version의 Stock을 가지고 다시 update를 실패해서
무한루프에 빠진다고 생각했습니다.

답변 2

0

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

요니님 안녕하세요!
생각하신 원인이 맞습니다!

0

안녕하세요, 인프런 AI 인턴입니다. 요니님의 질문에 대해 도움을 드리고자 합니다.

요니님께서 말씀하신 낙관적 락(OptimisticLock)과 관련된 트랜잭션 처리에서 무한 루프에 빠지는 문제는, 트랜잭션 범위와 재시도 로직이 연관된 것으로 이해해 주셔야 합니다. 특히, 낙관적 락을 사용할 때 @Transactional 어노테이션의 적용 범위는 매우 중요합니다.

일반적으로 낙관적 락은 동시성을 관리하기 위해 데이터의 버전을 확인하며, 트랜잭션이 성공적으로 데이터를 업데이트하면 버전 번호가 증가합니다. 만약 여러 클라이언트가 동시에 같은 데이터를 업데이트하려고 할 때, 최초의 성공한 트랜잭션만이 버전 번호를 업데이트하고, 나머지 트랜잭션들은 버전 불일치로 인해 실패하게 됩니다.

예상하신 바와 같이, OptimisticLockStockFacade 클래스에 @Transactional을 붙이면 해당 클래스의 메서드들이 하나의 트랜잭션으로 묶이게 됩니다. 이로 인해 만약 해당 메서드 내에서 버전 불일치로 인해 실패하고 재시도하는 로직이 있다면, 재시도할 때도 기존 트랜잭션 내에서 실행되므로 동일한 엔티티 매니저와 연결된 기존 버전의 데이터를 참조하게 됩니다. 따라서 업데이트에 실패한 이후에도 무한히 같은 버전의 데이터로 재시도하면서 무한 루프에 빠지는 것입니다.

이 문제에 대한 해결책으로는 재시도 로직을 갖는 메서드를 @Transactional의 적용 범위 밖으로 분리하는 방법이 있습니다. 다시 말해, 재시도를 담당하는 메서드는 별도의 트랜잭션을 시작하여 실패시마다 새로운 트랜잭션에서 재시도 할 수 있도록 구성해야 합니다. 이를 통해 실패한 경우 새 트랜잭션으로부터 최신 버전의 데이터를 가져와 재시도하게 되므로 무한 루프를 방지할 수 있습니다.

이와 유사한 내용을 다루는 기존 답변이 있습니다. 아래 링크를 참고하시면 이해하시는 데 도움이 될 것입니다.

기존 답변에서도 Isolation Level과 관련하여 낙관적 락의 동작 원리 및 무한 루프에 빠지는 현상에 대해 상세히 설명하고 있으며, 그 원인과 해결 방안에 대해 토론하는 내용을 살펴볼 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

요니님의 프로필 이미지
요니

작성한 질문수

질문하기