🎯 목표
- 동시성 환경에서 데이터 정합성을 보장하기 위한 락의 개념과 종류를 정리
- 비관적 락(Pessimistic Lock)과 낙관적 락(Optimistic Lock)의 차이와 실전 적용 방법을 이해
- 트랜잭션 충돌 가능성, 성능, 시스템 특성에 따른 전략 선택 기준을 제시
✅ 락이 필요한 이유
- 다수의 트랜잭션이 동일 자원에 접근할 때, 정합성 문제 발생 가능
- 예: 은행 계좌 출금 처리 중 동시 요청이 들어와 잔고 초과 인출이 발생할 수 있음
- → 이를 방지하기 위해 락(Lock)을 사용하여 데이터 보호
🔒 락의 종류
| 분류 |
방식 |
특징 |
| 비관적 락 (Pessimistic Lock) |
선제적으로 락 획득 |
충돌 가능성이 높을 때 유리 |
| 낙관적 락 (Optimistic Lock) |
충돌 감지 후 처리 |
충돌이 드물고 성능 중요할 때 유리 |
🔍 Pessimistic Lock (비관적 락)
개념
- 데이터를 읽거나 쓰기 전에 미리 락을 건다
- 다른 트랜잭션이 접근하지 못하게 선점
- 충돌을 미리 방지
구현 방법 (JPA 기준)
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT p FROM Product p WHERE p.id = :id")
Product findProductForUpdate(@Param("id") Long id);
SELECT ... FOR UPDATE 쿼리로 구현됨
- 락이 해제될 때까지 다른 트랜잭션은 대기 또는 락 타임아웃 발생
장점
- 충돌 없이 정합성 보장에 강력
- 잦은 수정 경쟁 환경에 적합
단점
- 락 대기 시간 증가 → 성능 저하
- 데드락 발생 가능성 있음
🪶 Optimistic Lock (낙관적 락)
개념
- 데이터 변경 시점까지는 락 없이 처리
- 최종 커밋 직전에 버전 비교를 통해 충돌 감지
구현 방법 (JPA 기준)
@Entity
public class Product {
@Version
private Long version;
}
- 엔티티에
@Version 필드 추가
- 업데이트 시점에 DB의 버전과 비교 → 일치하지 않으면 예외 발생 (
OptimisticLockException)
장점
- 락을 사용하지 않아 성능 우수
- 읽기 위주 시스템에 적합
단점
- 충돌 발생 시 예외 처리 필요
- 낙관이 빗나간 경우 재시도 로직 필요
🧪 적용 전략 비교
| 항목 |
Pessimistic |
Optimistic |
| 충돌 감지 시점 |
쓰기 전 선점 |
커밋 직전 비교 |
| 성능 |
낮음 (대기 발생) |
높음 (락 없음) |
| 트랜잭션 충돌 빈도 |
높을 때 유리 |
낮을 때 유리 |
| 데드락 가능성 |
있음 |
없음 |
| 복잡도 |
낮음 |
재시도 로직 필요 (복잡도 ↑) |
📌 실무 적용 기준
| 상황 |
추천 락 방식 |
| 동일 데이터에 잦은 수정 발생 |
Pessimistic Lock |
| 대부분 읽기 작업, 드물게 쓰기 발생 |
Optimistic Lock |
| 충돌 발생 시 반드시 막아야 하는 경우 (ex. 재고, 출금) |
Pessimistic Lock |
| 확장성과 성능이 중요한 읽기 지향 시스템 |
Optimistic Lock |