낙관적 락 vs 비관적 락
(DB 관점)
🔹 낙관적 락 (Optimistic Lock)
🔸 개념
- 충돌이 드물다고 가정
- 데이터를 읽을 때는 락을 걸지 않고, 업데이트 시점에 변경 여부를 검증
- 주로 버전(version) 컬럼 또는 타임스탬프로 검증
🔸 동작 방식
- 트랜잭션 A/B가 같은 row를 읽음
- A가 먼저 수정 → version 증가
- B가 수정 시도 → version 불일치 → 업데이트 실패

🔸 예시 (JPA)
@Version
private Long version;
🔸 장점
- 락 대기 없음 → 성능 우수
- 데드락 위험 거의 없음
- 읽기 중심 시스템에 적합
🔸 단점
- 충돌 시 재시도 로직 필요
- 충돌 빈도가 높으면 오히려 비용 증가
🔸 적합한 상황
- 트래픽은 많지만 동시 수정은 드문 경우
- 조회 위주의 서비스
- REST API, 이벤트 기반 처리, MSA 환경
🔹 비관적 락 (Pessimistic Lock)
🔸 개념
- 충돌이 자주 발생한다고 가정
- 데이터를 읽는 순간부터 락을 선점
- 다른 트랜잭션은 대기 또는 실패
🔸 동작 방식
- 트랜잭션 A가 row 조회 + 락 획득
- B는 해당 row 접근 시 대기(block) 또는 실패
- A 커밋/롤백 후 락 해제
🔸 예시 (JPA)
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("select o from Order o where o.id = :id")
Order findForUpdate(Long id);
🔸 장점
- 데이터 정합성 강력 보장
- 충돌 처리 로직 단순
🔸 단점
- 락 대기 → 성능 저하
- 데드락 가능성
- 트랜잭션 길어지면 시스템 병목
🔸 적합한 상황
- 동시 수정이 빈번
- 금액, 재고, 좌석, 포인트 등 절대 정확해야 하는 데이터
- 짧은 트랜잭션이 보장될 때
🔹 핵심 비교 표
| 항목 | 낙관적 락 | 비관적 락 |
|---|
| 락 시점 | 커밋 시 검증 | 조회 시 즉시 |
| 성능 | 👍 좋음 | 👎 낮아질 수 있음 |
| 충돌 처리 | 실패 후 재시도 | 원천 차단 |
| 데드락 | 거의 없음 | 발생 가능 |
| 구현 난이도 | 중 (재시도 필요) | 낮음 |
| 사용 예 | 게시글 수정, 프로필 | 결제, 재고 차감 |
🔹 실무 선택 기준 (중요)
🔸 낙관적 락을 선택해야 할 때
- 평균적으로 동시 수정 확률 < 1%
- API 요청이 많고 응답 지연이 민감
- 재시도가 허용되는 도메인
🔸 비관적 락을 선택해야 할 때
- 절대 중복/오류가 발생하면 안 됨
- 충돌이 빈번하고 재시도가 비용 큼
- 트랜잭션이 매우 짧음
🔹 실무에서 자주 쓰는 패턴
-
기본은 낙관적 락
-
정말 중요한 구간만 비관적 락으로 국소 적용
-
MSA 환경에서는 DB 락보다
- Redis 분산 락
- 메시지 큐 직렬화
- Saga / Outbox 패턴
을 함께 고려