비관적 락 vs 낙관적 락: 동시성 문제를 해결하는 두 가지 방법

2025. 3. 23. 13:41Back-End/DB

반응형

🙋‍♂️ 들어가기 전에: 왜 "락(Lock)"이 필요할까?

우리는 여러 사용자가 동시에 사용하는 서비스를 만들고 있어요.

예를 들어, 같은 상품의 재고를 동시에 여러 명이 주문한다고 해볼게요.

 

이럴 때 누군가의 수정이 다른 사람의 수정에 덮어씌워져 버린다면?

 

데이터가 꼬이고, 실제로는 재고가 1개인데 2명이 주문에 성공하는 말도 안 되는 일이 생길 수 있어요.

이걸 동시성 문제(concurrency issue)라고 해요.

그래서 이런 문제를 방지하기 위해 락(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);

이렇게 하면 해당 데이터를 조회하는 동시에 락이 걸리게 되어서,
다른 트랜잭션은 이 데이터를 읽지도, 수정하지도 못해요.

 

 

😊 낙관적 락 (Optimistic Lock)

👉 낙관적으로 본다는 건?

"설마 동시에 수정하진 않겠지? 일단 수정하고, 나중에 바뀌었는지 확인하자!"

 

낙관적 락은 락을 안 걸고 그냥 수정합니다.
대신에, 수정하려는 순간 이 데이터가 다른 누군가에 의해 바뀌었는지를 체크해요.

✅ 특징

  • 충돌이 잘 안 날 거라고 가정하고 진행.
  • 수정할 때 버전 정보를 확인해서 변경된 게 있으면 실패시킨다.
  • 성능은 좋지만, 충돌이 나면 예외가 발생하고 다시 시도해야 함.

📌 예시 (JPA 기준)

1. 엔티티에 버전 필드 추가

@Entity
public class Product {
    
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private int quantity;

    @Version
    private int version;  // 자동으로 관리됨
}

2. 저장할 때 충돌이 나면 예외 발생

product.setQuantity(product.getQuantity() - 1);
productRepository.save(product);

→ 누군가 먼저 수정해서 version 값이 바뀌었으면
OptimisticLockingFailureException 예외가 발생해요!

 

그렇다면 언제 비관적 락, 언제 낙관적 락?

상황 추천 락

경쟁이 자주 발생하는 경우 (ex. 인기 상품 주문) 🔐 비관적 락
경쟁이 거의 없는 경우 (ex. 유저 설정 변경) 😊 낙관적 락

 


💡 마무리 요약

구분 비관적 락 낙관적 락

락 방식 먼저 락을 건다 나중에 확인한다
성능 낮음 (대기 발생) 높음 (충돌 시 재시도 필요)
안정성 매우 안정적 충돌 가능성 존재
실용 예시 재고 감소, 은행 송금 마이페이지 수정, 게시물 좋아요

 

 

✨ 같이 알아두면 좋은 개념

동시성(concurrency) 여러 사용자가 동시에 하나의 자원에 접근할 때 발생하는 상황
트랜잭션(Transaction) 데이터베이스에서 하나의 작업 단위를 의미
JPA Version 필드 @Version으로 낙관적 락을 적용할 때 필수로 사용
ACID 원칙 데이터베이스 트랜잭션의 4가지 성질 (Atomicity, Consistency, Isolation, Durability)

 

실무에선 동시성 문제는 정말 자주 만나게 돼요.
비관적 락과 낙관적 락은 성능과 안정성 사이의 밸런스를 잡는 개념이기 때문에
서비스의 특성과 상황에 맞게 적절히 선택하는 것이 중요합니다.

 

반응형

'Back-End > DB' 카테고리의 다른 글

PostgreSQL 자주 쓰는 명령어 요약  (0) 2025.04.16
macOS에 PostgreSQL 설치  (0) 2025.04.16
MyBatis Mapper 사용 팁  (0) 2025.04.08
JPA + Oracle DB에서 시퀀스 설정하는 방법  (0) 2025.03.15
정규화 비정규화  (0) 2025.03.13