FastAPI와 SQLAlchemy에서 이해하는 낙관적 락과 비관적 락

2025. 10. 6. 16:53·컴퓨터 과학/데이터베이스

웹 개발이나 API 설계에서 동시성 문제는 피할 수 없는 주제입니다. 특히 시뮬레이션 실행이나 계좌 잔액 수정처럼 동시에 여러 요청이 들어오는 상황에서는 데이터 정합성을 유지하는 것이 중요합니다. 이를 위해 흔히 사용하는 방법이 락(Lock) 전략입니다. 이번 글에서는 **낙관적 락(Optimistic Lock)**과 비관적 락(Pessimistic Lock), 그리고 분산 락(Redis 락) 개념을 정리합니다.


1. 비관적 락(Pessimistic Lock)

원리:

  • 데이터를 조회하거나 수정할 때 즉시 잠금
  • 다른 트랜잭션이 해당 데이터를 수정하지 못하도록 차단

장점:

  • 동시성 충돌 방지
  • 데이터 정합성 강력 보장

단점:

  • 락이 유지되는 동안 다른 트랜잭션은 대기 → 성능 저하
  • 데드락 가능

DB 적용 예 (PostgreSQL + SQLAlchemy):

from sqlalchemy import select
execution = db.execute(
    select(SimulationExecution)
    .where(SimulationExecution.id == 1)
    .with_for_update()
).scalar_one()

주의: 단일 DB 연결에서는 안전하지만, 멀티 서버 환경에서는 다른 서버의 DB 연결에는 락이 적용되지 않을 수 있습니다. 따라서 Redis 같은 분산 락을 함께 사용해야 안전합니다.


2. 낙관적 락(Optimistic Lock)

원리:

  • 데이터를 자유롭게 조회(잠금 없음)
  • 수정 시점에 버전(version) 또는 타임스탬프(timestamp) 비교
  • 충돌이 발생하면 업데이트 실패 후 재시도

장점:

  • 잠금을 오래 유지하지 않아 성능 유리
  • 충돌 가능성이 낮은 데이터 처리에 적합

단점:

  • 충돌이 잦으면 재시도 빈도 증가 → 성능 저하 가능

DB 컬럼 예:

version = Column(Integer, default=1)

동작 예시:

  1. 트랜잭션 A와 B가 같은 레코드 조회
  2. A가 먼저 수정 후 커밋 → 버전 증가
  3. B가 수정 시도 → 버전 불일치 → 실패 → 재시도 필요

즉, “서로 자유롭게 읽고, 마지막에 저장할 때 충돌 체크”하는 방식입니다.


3. Redis 분산 락

원리:

  • 여러 서버 환경에서 동시에 같은 리소스 접근을 막기 위해 사용
  • API/애플리케이션 레벨에서 잠금 처리

동작 예시:

if redis.set(lock_key, "locked", nx=True, ex=30):
    # 락 획득 → 작업 수행
    redis.delete(lock_key)  # 락 해제
else:
    raise HTTPException(409, "이미 실행 중")

특징:

  • 실제 잠금 방식 → 비관적 락과 유사
  • 단일 DB만 사용하는 비관적 락과 달리 멀티 서버 환경에서 동시성 제어 가능

4. 언제 어떤 락을 사용할까?

락 유형 사용 상황 장점 단점
비관적 락 충돌 가능성 높음 정합성 강력 성능 저하, 데드락 가능
낙관적 락 충돌 가능성 낮음 성능 좋음 충돌 시 재시도 필요
Redis 분산 락 멀티 서버 환경 안전한 동시성 제어 외부 시스템 의존

실무에서는 비관적 락 + Redis 분산 락 병행하여

  • DB 내부 정합성 확보
  • 멀티 서버 동시 요청 제어
    둘 다 안전하게 처리하는 패턴을 사용합니다.

5. 마무리

  • 비관적 락: “먼저 잠근다”
  • 낙관적 락: “나중에 확인한다”
  • Redis 분산 락: “서버 간에도 잠금 정보를 공유한다”

이 세 가지를 이해하고 적절히 설계하면, FastAPI와 SQLAlchemy 환경에서 시뮬레이션 실행이나 계좌 처리 등 동시성 문제를 안정적으로 해결할 수 있습니다.

'컴퓨터 과학 > 데이터베이스' 카테고리의 다른 글

트랜잭션의 연산 중 COMMIT의 개념을 간략히 설명해주세요.  (0) 2022.08.06
'컴퓨터 과학/데이터베이스' 카테고리의 다른 글
  • 트랜잭션의 연산 중 COMMIT의 개념을 간략히 설명해주세요.
rondeveloper
rondeveloper
  • rondeveloper
    Ron's learning record
    rondeveloper
  • 전체
    오늘
    어제
    • 분류 전체보기 (99)
      • k8s (1)
      • AWS (1)
      • 리눅스 (3)
      • Docker (8)
      • 라이브러리 & 프레임워크 (14)
        • React (2)
        • NestJS (8)
        • Spring (0)
        • Django (3)
        • FastAPI (1)
      • 웹 (2)
        • Nginx (1)
      • 프로그래밍 언어 (29)
        • HTML (0)
        • CSS (0)
        • JavaScript (21)
        • Python (3)
        • Node.js (0)
        • TypeScript (4)
        • Java (1)
      • Today I learned (9)
      • 알고리즘 (9)
        • 백준 (0)
        • 프로그래머스 (8)
        • 개념 (1)
      • 티끌모아 태산 (5)
        • 하루에 영단어 하나씩 (5)
        • 독서 (0)
      • 시행착오 (3)
      • 데이터베이스 (2)
        • MySQL (0)
      • 컴퓨터 과학 (8)
        • 네트워크 (2)
        • 운영체제 (0)
        • 데이터베이스 (2)
        • 자료구조 (4)
      • 포트폴리오 (4)
        • JJINCAFE IN SEOUL (4)
        • CODEUNICORN (0)
      • 회고 (0)
      • CICD (1)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    쿠버네티스
    FastAPI
    모듈
    Til
    컨테이너
    배열
    Kubernetes
    iterable
    리눅스
    자바스크립트
    조인
    레벨2
    생활코딩
    기초
    Docker
    javascript
    django
    typeorm
    mysql
    IP 주소
    도커
    Python
    코딩테스트
    네트워크
    Kubectl
    스택
    프로그래머스
    redis
    nestjs
    typescript
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
rondeveloper
FastAPI와 SQLAlchemy에서 이해하는 낙관적 락과 비관적 락
상단으로

티스토리툴바