[DB / JPA] 낙관적 락과 비관적 락

2025. 3. 2. 18:48·면접 준비/DB
728x90
반응형
SMALL

비관적 락과 낙관적 락의 차이점

 

비관적 락(Pessimistic Lock)과 낙관적 락(Optimistic Lock)은 동시성 제어(Concurrency Control) 를 위해 사용되는 두 가지 대표적인 방식입니다.

1. 비관적 락(Pessimistic Lock)

 

비관적 락은 데이터를 수정하는 동안 다른 트랜잭션이 해당 데이터를 변경하지 못하도록 차단하는 방식입니다. 즉, 트랜잭션이 시작되면 즉시 잠금을 걸고, 트랜잭션이 종료될 때까지 다른 트랜잭션이 접근할 수 없도록 하는 방식입니다.

 

특징

 

✅ 장점

• 경쟁이 심한 환경에서도 안전하게 데이터 정합성을 보장할 수 있습니다.

• 동시성 충돌이 발생할 가능성이 높은 경우 적합합니다.

 

❌ 단점

• 잠금이 유지되는 동안 다른 트랜잭션이 대기해야 하므로 성능 저하가 발생할 수 있습니다.

• 데드락(Deadlock) 위험이 있습니다.

JPA에서 비관적 락 사용 예시

 

JPA에서 비관적 락을 사용하려면 @Lock 어노테이션을 이용하면 됩니다.

import jakarta.persistence.LockModeType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
import java.util.Optional;

public interface ProductRepository extends JpaRepository<Product, Long> {

    @Lock(LockModeType.PESSIMISTIC_WRITE) // 비관적 쓰기 락 적용
    Optional<Product> findById(Long id);
}

위 코드에서 @Lock(LockModeType.PESSIMISTIC_WRITE)을 설정하면,

해당 데이터를 조회할 때 쓰기 락(PESSIMISTIC_WRITE) 이 걸려 다른 트랜잭션에서 해당 데이터를 변경하지 못하도록 막습니다.

2. 낙관적 락(Optimistic Lock)

 

낙관적 락은 데이터에 잠금을 걸지 않고 트랜잭션이 완료될 때 충돌이 있는지 확인하는 방식입니다.

즉, 트랜잭션이 끝날 때까지 다른 트랜잭션이 데이터를 변경하지 않았다고 가정하고 작업을 수행한 후,

커밋 시점에 충돌을 검출하고 롤백 처리합니다.

 

특징

 

✅ 장점

• 데이터 충돌이 자주 발생하지 않는 경우 성능이 뛰어납니다.

• 락을 걸지 않으므로 데드락이 발생하지 않습니다.

 

❌ 단점

• 동시에 여러 트랜잭션이 같은 데이터를 수정하려고 할 경우 충돌이 발생할 가능성이 높습니다.

• 충돌이 발생하면 트랜잭션이 롤백되므로 재시도 로직이 필요할 수 있습니다.

JPA에서 낙관적 락 사용 예시

 

JPA에서는 @Version 어노테이션을 이용해 낙관적 락을 적용할 수 있습니다.

import jakarta.persistence.*;

@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private int stock;

    @Version // 낙관적 락을 위한 버전 필드
    private int version;

    // Getter, Setter 생략
}

그리고 Repository에서 데이터를 수정할 때는 @Version 필드를 자동으로 활용하여 충돌을 감지합니다.

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    @Transactional
    public void updateStock(Long productId, int quantity) {
        Product product = productRepository.findById(productId)
                .orElseThrow(() -> new RuntimeException("상품을 찾을 수 없습니다."));

        product.setStock(product.getStock() - quantity);
        productRepository.save(product);
    }
}

낙관적 락의 동작 방식

1. 데이터 조회 시 version 값을 함께 가져옵니다.

2. 트랜잭션이 끝날 때 version 값을 비교합니다.

• 트랜잭션이 시작될 때 읽은 version 값과, 커밋 시점의 version 값이 동일하면 정상적으로 업데이트 수행

• 다른 트랜잭션이 먼저 값을 변경하여 version 값이 바뀌었다면, 예외(OptimisticLockException) 발생 및 롤백

비관적 락 vs 낙관적 락 비교 정리

비관적 락 (Pessimistic Lock)낙관적 락 (Optimistic Lock)

잠금 방식 트랜잭션이 시작될 때 즉시 잠금 잠금 없이 트랜잭션 종료 시 충돌 확인
경쟁 환경 경쟁이 심한 환경에서 적합 경쟁이 적은 환경에서 적합
데드락 위험 있음 없음
성능 동시성이 낮아 성능 저하 가능 동시성이 높아 성능 우수
충돌 발생 시 충돌 방지 가능 충돌 발생 시 예외 발생 및 롤백

비관적 락 vs 낙관적 락 선택 기준

• 경쟁이 빈번한 환경 (e.g., 은행 시스템, 재고 관리 등) ➝ 비관적 락

• 경쟁이 적고 성능이 중요한 경우 (e.g., 읽기 요청이 많고 쓰기 충돌이 드문 경우) ➝ 낙관적 락

실제 활용 예시

1. 비관적 락 적용 예시

• 동시에 많은 사용자가 같은 데이터를 수정할 가능성이 높은 경우

• 예: 온라인 쇼핑몰에서 “한정 수량” 상품 구매 처리

2. 낙관적 락 적용 예시

• 대부분 읽기 위주이며, 가끔 업데이트가 발생하는 경우

• 예: 게시판 댓글 수정, 사용자의 프로필 정보 변경

결론

• 비관적 락은 강력한 데이터 일관성을 보장하지만 성능 저하가 우려됨.

• 낙관적 락은 충돌이 자주 발생하지 않는 환경에서 유리하며 성능이 뛰어남.

• 상황에 따라 적절한 방법을 선택하는 것이 중요!

728x90
반응형
SMALL

'면접 준비 > DB' 카테고리의 다른 글

[DB] PhantomRead란?  (0) 2025.03.02
[DB / Transaction] 트랜잭션 고립 수준  (0) 2025.03.02
[CS 면접 질문 - DB] 파티셔닝  (0) 2025.01.06
[CS 개념 정리 - DB] 정규화  (1) 2025.01.06
[CS 개념 정리 - DB] 인덱스  (0) 2025.01.06
'면접 준비/DB' 카테고리의 다른 글
  • [DB] PhantomRead란?
  • [DB / Transaction] 트랜잭션 고립 수준
  • [CS 면접 질문 - DB] 파티셔닝
  • [CS 개념 정리 - DB] 정규화
공부하고 기억하는 공간
공부하고 기억하는 공간
IT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
IT - railroadIT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
    250x250
  • 공부하고 기억하는 공간
    IT - railroad
    공부하고 기억하는 공간
  • 전체
    오늘
    어제
    • 분류 전체보기 (314)
      • 면접 준비 (36)
        • OS (6)
        • Spring Security (0)
        • Java (2)
        • DB (9)
        • Network (3)
      • ElasticSearch (2)
      • Kafka (4)
      • Spring (22)
        • Spring Cloud (7)
        • Security6 (5)
        • JPA (12)
        • 프로젝트 리팩토링 회고록 (4)
        • Logging (8)
        • Batch (2)
      • Redis (17)
        • Redis 개념 (8)
        • Redis 채팅 (5)
        • Redis 읽기쓰기 전략 (1)
      • AWS (11)
      • 리눅스 (29)
        • 리눅스 마스터 2급 (5)
        • 네트워크(기초) (7)
        • 리눅스의 이해 (6)
        • 리눅스의 설치 (2)
        • 리눅스 운영 및 관리 (6)
      • JAVA-기초 (16)
        • JAVA기본 (11)
        • Design Pattern (5)
      • JSP (27)
        • JSP 기본 개념 (10)
        • JSP (1)
      • SQL (1)
      • TIL (36)
      • 문제 풀이 (2)
        • Programmers (9)
        • 백준 문제풀이 (28)
      • JavaScript (10)
      • HTML (17)
      • Ngrinder (1)
        • Ngrinder 문서 정리 (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      JS
      자바 알고리즘
      프로그래머스
      Til
      리눅스
      jsp기초
      레디스
      springsecurity
      JSP
      자바기초
      CSS
      자바 반복문
      jsp request
      redis
      java
      HTML
      리눅스마스터2급정리
      자바 면접질문
      백준
      리눅스마스터2급
      spring redis
      Springframework
      JavaScript
      자바스크립트
      스프링프레임워크
      자바
      Spring
      자바 면접
      Spring Data Redis
      redis 채팅
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    공부하고 기억하는 공간
    [DB / JPA] 낙관적 락과 비관적 락

    개인정보

    • 티스토리 홈
    • 포럼
    • 로그인
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.