Kotlin으로 초대코드 사용 시 동시성 문제와 낙관적 락(Optimistic Lock) 적용하기

한로·2025년 5월 23일
post-thumbnail

상황 설명: 동시성 문제란?

  • 여러 사용자가 거의 동시에 같은 초대코드를 사용하려고 할 때 문제가 생긴다.
  • 예) 초대코드 상태가 사용 안 된 상태인데, 사용자 A와 B가 동시에 사용 시도하면 둘 다 사용 가능해진다.
  • 결과: 중복 사용 문제 발생

동시성과 병렬성 차이

  • 동시성과 병렬성 차이 이해하기
  • 동시성(Concurrency): 여러 작업이 겹쳐서 진행되는 것처럼 보이지만, 실제로는 빠르게 왔다 갔다 하면서 실행하는 것
  • 병렬성(Parallelism): 여러 작업을 실제로 동시에 실행하는 것

JPA의 낙관적 락(Optimistic Lock)과 @Version

  • @Version 어노테이션은 JPA가 제공하는 낙관적 락을 구현하는 방법
  • 낙관적 락:
    • 데이터 충돌이 거의 없다고 가정하고, 저장 시점에만 충돌 여부를 체크한다.
    • 저장할 때 버전이 다르면 충돌로 인식해서 OptimisticLockException 예외가 발생한다.
  • @Version 필드는 데이터가 수정될 때마다 자동으로 값이 변경된다.
  • 많이 사용하는 타입: Long, Integer, Timestamp, LocalDateTime

낙관적 락의 동작 원리

  1. 데이터를 읽을 때 버전 번호도 함께 읽는다.
  2. 데이터를 수정하고 저장할 때, DB에 저장된 버전 번호와 변경 전 버전 번호를 비교한다.
  3. 버전 번호가 같으면 정상 저장하며, 버전 번호를 1 증가시킨다.
  4. 버전 번호가 다르면 다른 트랜잭션에서 이미 수정한 것으로 보고 예외를 발생시킨다.

실제 구현 시 고려 사항

  • @Version 필드는 JPA가 자동으로 관리하기 때문에 직접 값을 변경하지 말 것.
  • 충돌이 발생하면 OptimisticLockException이 발생하므로 예외 처리가 반드시 필요하다.
  • 예외 발생 시:
    • 트랜잭션 내에서 재시도 로직을 구현하거나,
    • 사용자에게 알림을 주어 다시 시도하게 해야 한다.
  • 상태 변경과 버전 체크가 트랜잭션 범위(@Transactional) 내에서 일어나야 한다.

profile
"Hello World"

0개의 댓글