[SSA] 락의 종류와 활용 가능한 상황

2025. 9. 9. 14:06·SSA/Back

 

간단한 락 정리 표

잠금 방식 특징 적합한 환경
Synchronized / ReentrantLock Java 코드 레벨에서 스레드를 제어 단일 서버, 단일 JVM
낙관적 락 (Optimistic Lock) DB에 버전(Version) 컬럼을 두어 데이터 정합성 검증 단일 DB, 데이터 충돌이 드물 때
비관적 락 (Pessimistic Lock) DB 트랜잭션 동안 Row에 배타적 락(Lock) 설정 단일 DB, 데이터 충돌이 빈번할 때
네임드 락 (Named Lock) DB 연결 기반으로 특정 이름의 락을 획득 단일 DB, MySQL 환경
분산 락 (Distributed Lock) Redis 등 외부 시스템을 통해 락을 관리 다중 서버, 분산 환경

 

### JVM 잠금 (Synchronized / ReentrantLock)

  • 방법: Java 언어 자체에서 제공하는 기능으로, 하나의 서버 프로세스(JVM) 내에서 코드 블록이나 메서드에 대한 동시 접근을 제어합니다. synchronized 키워드를 사용하거나, 더 세밀한 제어가 가능한 java.util.concurrent.locks.ReentrantLock 객체를 사용해 구현합니다. ReentrantLock 활용 시 여러 메서드나 서비스 간에 락을 명시적으로 공유할 수 있습니다.
  • 장점: 외부 시스템이나 라이브러리 없이 구현이 매우 간단하고 빠릅니다. 단일 서버 환경에서 간단한 동시성 문제를 해결하기에 적합합니다.
  • 단점: 서버가 두 대 이상으로 늘어나는 분산 환경에서는 전혀 동작하지 않습니다. 서버 A에서 획득한 락은 서버 B에 아무런 영향을 주지 못해, 결국 여러 서버에서 동시에 정원을 초과하여 등록되는 문제가 다시 발생합니다.

 

### 데이터베이스를 이용한 잠금 (비관적 락, Pessimistic Lock)

  • 방법: 한 스레드가 수강 인원을 확인하고 등록하는 동안, 다른 스레드가 해당 데이터에 접근하지 못하도록 데이터베이스의 Row에 배타적 잠금(Exclusive Lock)을 거는 방식입니다. JPA에서는 @Lock(LockModeType.PESSIMISTIC_WRITE) 어노테이션으로 쉽게 구현할 수 있습니다.
  • 장점: 구현이 비교적 간단하고, 데이터 정합성을 확실하게 보장합니다.
  • 단점: 잠금을 얻지 못한 나머지 스레드들은 앞선 스레드의 트랜잭션이 끝날 때까지 계속 대기해야 합니다. 동시 요청이 매우 많은 상황에서는 이 대기 시간 때문에 DB 커넥션 풀이 빠르게 고갈되고 전체 시스템의 성능이 급격히 저하될 수 있습니다.

 

### 데이터베이스를 이용한 잠금 (낙관적 락, Optimistic Lock)

  • 방법: 실제로 데이터를 잠그지 않고, "데이터 쓰기 작업에 의한 충돌이 거의 없을 것"이라고 낙관적으로 가정하는 방식입니다. 테이블에 version 컬럼을 추가하고, 데이터를 수정할 때 처음에 읽었던 version과 현재 DB의 version이 일치하는지 확인합니다. 만약 version이 다르다면 다른 스레드가 먼저 수정한 것이므로, 현재 트랜잭션을 실패시키고 재시도를 유도합니다. JPA에서는 @Version 어노테이션으로 구현합니다.
  • 장점: 잠금을 사용하지 않아 대기가 없으므로, 충돌이 거의 발생하지 않는 환경에서는 비관적 락보다 훨씬 높은 성능을 보여줍니다.
  • 단점: 수강 신청처럼 충돌이 매우 빈번하게 발생하는 시나리오에는 최악의 선택입니다. 1000개의 동시 요청이 발생하면 1개를 제외한 999개가 실패하고 재시도를 반복하게 되어, 엄청난 수의 예외를 발생시키고 리소스를 낭비하게 됩니다.

 

### 데이터베이스를 이용한 잠금 (네임드 락, Named Lock)

  • 방법: MySQL 등 일부 데이터베이스에서 제공하는 기능으로, 테이블이나 Row가 아닌 사용자가 지정한 '이름'에 대해 락을 획득하는 방식입니다. GET_LOCK('lecture_1_enroll')과 같은 함수를 호출하여 락을 획득하고, 처리가 끝나면 RELEASE_LOCK()으로 해제합니다.
  • 장점: 특정 데이터 Row와 상관없이 여러 로직을 하나의 락으로 묶어서 제어할 수 있어 유연성이 높습니다.
  • 단점: 특정 데이터베이스에 종속적이라 다른 DB로 교체하기 어렵습니다. 락을 획득하고 해제하는 로직을 코드에서 명시적으로 관리해야 하므로 번거롭고, 해제를 누락하면 시스템 전체가 멈추는 데드락이 발생할 수 있습니다.

 

### Redis 분산 락 (Distributed Lock)

  • 방법: 애플리케이션 서버 외부의 Redis 같은 중앙화된 시스템을 사용하여 락을 관리하는 방식입니다. 모든 서버는 이 Redis에 특정 키(예: lock:lecture:1)에 대한 락을 요청하고, 락을 획득한 서버만 임계 영역(critical section) 로직을 실행할 수 있습니다. Java에서는 Redisson 라이브러리를 사용하면 복잡한 로직을 손쉽게 구현할 수 있습니다.
  • 장점: 서버가 여러 대인 분산 환경에서 동시성을 제어할 수 있는 해결책입니다. DB에 직접 부하를 주지 않아 성능이 뛰어나고, 스케일 아웃에 유연하게 대처할 수 있습니다.
  • 단점: Redis라는 외부 시스템에 대한 의존성이 생깁니다. Redis 장애 시 락을 획득할 수 없어 서비스에 영향을 줄 수 있습니다. DB 락에 비해 구현이 다소 복잡합니다.

#### 구체적인 Redis 분산 락 종류 (더 많음)

Lettuce 락

  • Redis를 사용하여 비교적 간단한 동시성 제어를 원하는 경우
  • 빠른 동기화가 필요한 경우
  • 분산 환경일 경우 (여러 개의 DB, 서버)
  • 스핀 락 방식

Redisson 락

  • 분산 시스템에서 효율적으로 락을 관리하고, 부하를 최소화해야 하는 경우
  • 동시 접근이 많은 시스템에서 성능과 동기화 문제를 모두 해결하고자 할 경우
  • 분산 환경일 경우 (여러 개의 DB, 서버)
  • pub/sub 방식 가능

Lettuce의 스핀 락을 적극 활용하게 된다면 지속적으로 재시도를 요청하므로 Redis에 부하를 주게 됩니다.

이후, 계속해서 대기 상태에 빠지면 전체 서비스에 문제가 생길 수 있습니다.

 

조금 고민해 보자면,

재시도가 필요하지 않은 Lock의 경우 비교적 간단한 Lettuce를 활용해 볼 수 있을 것 같습니다 !

 

이외의 경우, 조금 더 많은 고민이 필요하겠지만 의존성이 발생하더라도 Redisson 락을 사용할 것 같습니다 ..

 

 

 

 

 

 

 

'SSA > Back' 카테고리의 다른 글

[SSA] 특강 개설 시 선착순 동시성 이슈 해결  (2) 2025.09.10
[SSA] 수강 로직에 대한 간단한 고민 ..  (0) 2025.09.09
[SSA] Kafka Consumer가 멱등성을 가질 수 있도록 설계  (0) 2025.09.09
[SSA] 수강 기능, 알림 기능을 이벤트 기반으로 분리  (0) 2025.09.09
[SSA] 이벤트 발행에 트랜잭셔널 아웃박스 패턴을 적용  (1) 2025.09.08
'SSA/Back' 카테고리의 다른 글
  • [SSA] 특강 개설 시 선착순 동시성 이슈 해결
  • [SSA] 수강 로직에 대한 간단한 고민 ..
  • [SSA] Kafka Consumer가 멱등성을 가질 수 있도록 설계
  • [SSA] 수강 기능, 알림 기능을 이벤트 기반으로 분리
하가네
하가네
  • 하가네
    하 렌
    하가네
  • 전체
    오늘
    어제
    • 분류 전체보기 (128) N
      • Computer Science (27)
        • 운영체제 (7)
        • 데이터통신 (10)
        • 자료구조 (4)
        • 논리회로 (0)
        • 확률 및 통계 (0)
        • 데이터베이스 (2)
        • AI소프트웨어 (3)
        • 컴퓨터네트워크 (1)
      • Design (5) N
        • OOP - 객체 지향 프로그래밍 (3) N
        • DDD - 도메인 주도 개발 (데이터베이스 주도 .. (0)
        • EDA - 이벤트 기반 아키텍처 (1)
        • MSA - 마이크로서비스 아키텍처 (0)
        • ADD - AI 주도 개발 (1)
      • Language (2)
        • Java (0)
        • TypeScript (2)
      • Framework (12)
        • Spring (9)
        • NestJS (3)
      • Engine (3)
        • Elasticsearch (1)
        • GraphQL + Apollo Federation (2)
      • Plugin - Extension (1)
        • VS Code (1)
        • IntelliJ (0)
      • Tips (2)
        • 터미널 명령어 (1)
        • 우분투 명령어 에러 (1)
      • SSA (26)
        • Front (1)
        • Back (23)
        • DB (1)
        • 기획 (1)
      • CNU SW 아카데미 (43)
        • 1주차 (5)
        • 2주차 (5)
        • 3주차 (2)
        • 4주차 (1)
        • 5주차 (3)
        • 6주차 (2)
        • 7주차 (0)
        • 8주차 (2)
        • 9주차 (14)
        • 10주차 (0)
        • 11주차 (1)
        • 12주차 (0)
        • 13주차 (2)
        • 14주차 (2)
        • 15주차(최종 프로젝트) (3)
        • 최종 프로젝트 이후 (1)
      • 모각코 (6)
        • 2023 동계 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Husky
    DX(DeveloperExperience)
    프론트엔드/백엔드
    ci/cd
    Typescript
    ESLint
    개발자경험(DX)
    lint-staged
    생산성
    아키텍처
    릴리스엔지니어링
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.
하가네
[SSA] 락의 종류와 활용 가능한 상황
상단으로

티스토리툴바