우당탕탕
[JPA] 낙관적 락(Optimistic Lock)과 비관적 락(Pessimistic Lock)에 대해 본문
낙관적 락, 비관적 락에 대해
JPA를 사용하여 데이터베이스와 연결된 애플리케이션을 개발할 때, 동시성 처리와 관련된 이슈가 발생할 수 있다.
이러한 이슈를 해결하기 위한 방법 중 하나는 락(lock)을 사용하는 것이다.
이번 포스팅에는 낙관적 락과 비관적 락에 대해 알아보고, 예제코드와 이를 사용하는 이유 및 장단점을 함께 써보겠다.
낙관적 락(Optimistic Lock)
낙관적 락은 충돌이 거의 발생하지 않을 것이라고 가정하고, 충돌이 발생한 경우에 대비하는 방식이다.
낙관적 락은 JPA에서 버전(Version) 속성을 이용하여 구현할 수 있다. 낙관적 락의 특징으로는 충돌 발생확률이 낮고, 지속적인 락으로 인한 성능저하를 막을 수 있다.
아래는 예시 코드이다.
1. Entity
@Entity
public class SampleEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private Long version;
private String data;
}
2. Repository
@Repository
public interface SampleEntityRepository extends JpaRepository<SampleEntity, Long> {
}
3. Service
@Service
public class SampleEntityService {
@Autowired
private SampleEntityRepository sampleEntityRepository;
public SampleEntity updateData(Long id, String newData) {
SampleEntity sampleEntity = sampleEntityRepository.findById(id).orElseThrow();
sampleEntity.setData(newData);
return sampleEntityRepository.save(sampleEntity);
}
}
작동원리로는 SampleEntity 클래스에 @Version 어노테이션을 이용하여 version 필드로 지정한다.
데이터를 수정할 때 같은 id 값이지만 다른 사용자에 의한 변경이 발생하면 version 값이 다르게 되고, 이때 예외가 발생하므로 충돌로부터 안전하게 처리할 수 있다.
비관적 락(Pessimistic Lock)
비관적 락은 충돌이 발생할 확률이 높다고 가정하여, 실제로 데이터에 액세스 하기 전에 먼저 락을 걸어 충돌을 예방하는 방식이다. 비관적 락은 JPA에서 제공하는 LockModeType을 사용하여 구현할 수 있다.
아래는 예시코드이다
1. Repository
@Repository
public interface SampleEntityRepository extends JpaRepository<SampleEntity, Long> {
}
2. Service
@Service
public class SampleEntityService {
@Autowired
private SampleEntityRepository sampleEntityRepository;
@Autowired
private EntityManager entityManager;
@Transactional
public SampleEntity updateDataWithPessimisticLock(Long id, String newData) {
SampleEntity sampleEntity = entityManager.find(SampleEntity.class, id, LockModeType.PESSIMISTIC_WRITE);
sampleEntity.setData(newData);
entityManager.flush();
return sampleEntity;
}
}
위 코드를 설명해보면 EntityManager의 find 메소드에 락 타입(LockModeType.PESSIMISTIC_WRITE)을 지정하여 데이터에 락을 걸어두고, 변경 작업이 끝난 후에 락을 해제한다. 이를 통해 다른 트랜잭션이 동시에 수정할 수 없어 동시성 처리 이슈를 방지할 수 있게 된다.
이제 낙관적 락과 비관적 락에 대해 알아보았으니 이들의 장단점에 대해서도 알아보자
낙관적 락
장점: 리소스 경쟁이 적고 락으로 인한 성능저하가 적다.
단점: 충돌 발생 시 처리해야 할 외부 요인이 존재한다.
비관적 락
장점: 충돌 발생을 미연에 방지하고 데이터의 일관성을 유지할 수 있다.
단점: 동시 처리 성능 저하 및 교착상태(Deadlock) 발생 가능성이 있다.
위에서 알아본 내용처럼 낙관적 락과 비관적 락은 각각의 사용 상황에 따라 선택할 수 있다. 충돌 발생 확률이 낮고 성능 저하를 예방하려면 낙관적 락을 사용하면 되고, 충돌을 미연에 방지하고 데이터의 일관성을 유지하려면 비관적 락을 사용하면 된다. 선택한 락 방식에 따라 JPA를 효과적으로 사용하여 동시성 처리 이슈를 해결할 수 있다.
'언어 > Java' 카테고리의 다른 글
[Java] 자바 LTS(Long Term Support)란 무엇인가? (0) | 2024.09.28 |
---|---|
[Java] String, StringBuilder, StringBuffer의 차이와 장단점 (0) | 2024.01.29 |
[Java] static(정적) 변수와 메모리에 대해 (0) | 2022.11.02 |
[Java] 람다 표현식, 람다(Lambda Expression)이란? (0) | 2022.09.12 |
[Java] 가비지 컬렉션(Garbage Collection) 알고리즘 (가비지 컬렉션 - 2) (0) | 2022.08.29 |