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
  • 전체
    오늘
    어제
    • 분류 전체보기 (101)
      • k8s (1)
      • AWS (1)
      • 리눅스 (4)
      • 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)
      • AI Agent (1)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바