에그코드 기술 이야기 · 데이터베이스 Lock 시리즈 ②
안녕하세요, 에그코드입니다.
저희는 자체 서비스를 직접 운영하며 웹·SaaS·MVP를 만드는 개발사입니다.
지난 1편에서는 "충돌은 드물다"고 믿고 저장하는 순간에만 확인하는 낙관적 락을 다뤘습니다.
이번 2편은 정반대 방식입니다. 아예 처음부터 잠그고 시작하는 비관적 락(Pessimistic Lock)입니다.

비관적 락이란 무엇인가
비관적 락은 이름 그대로 비관적으로 가정합니다. "충돌은 자주 일어난다"고 보고, 데이터를 읽는 순간부터 아예 잠급니다.
내가 작업을 끝낼 때까지 다른 요청은 문 앞에서 기다립니다.
낙관적 락이 "일단 진행하고 저장할 때 확인"이라면, 비관적 락은 "잠그고 시작"입니다.
어떻게 미리 잠글까 — FOR UPDATE
비관적 락은 애플리케이션이 아니라 DB가 직접 거는 락입니다. 대표적으로 조회 SQL 뒤에 FOR UPDATE를 붙입니다.
"이 행을 읽는 동안, 아무도 손대지 못하게 잠가라."
그러면 그 행에 배타 락(exclusive lock) 이 걸리고, 다른 트랜잭션은 커밋될 때까지 대기합니다.

읽기끼리는 허용하되 쓰기만 막고 싶다면 공유 락(shared lock) 을 씁니다. 이 락들은 트랜잭션이 끝나는 순간(커밋·롤백)에 풀립니다.

낙관적 락과 뭐가 다른가
가장 큰 차이는 잠그는 시점입니다. 낙관적 락은 저장할 때 버전으로 확인하고, 비관적 락은 읽을 때부터 잠급니다.
그래서 충돌이 나도 비관적 락은 재시도가 없습니다. 이미 잠갔으니까요. 대신 다른 요청은 그만큼 기다려야 합니다.
| 구분 | 낙관적 락 | 비관적 락 |
|---|---|---|
| 잠그는 시점 | 저장할 때 확인만 | 읽을 때부터 잠금 |
| 충돌 나면 | 되돌리고 재시도 | 재시도 없음 · 남은 요청 대기 |
| 방식 | 앱이 버전으로 판정 | DB가 행을 직접 잠금 |
| 잘 맞는 곳 | 읽기 많고 충돌 드묾 | 충돌 잦고 정확성 중요 |
정리하면 낙관적 락은 빠르지만 충돌 시 되돌려야 하고, 비관적 락은 느긋하지만 한 번에 확실합니다.
그래서 언제 쓰면 좋을까
비관적 락이 맞는 경우는 분명합니다. 같은 데이터에 충돌이 잦고, 한 번 틀리면 손해가 큰 작업입니다.
잔액 이체, 좌석·재고 선점처럼 "무조건 정확히 한 번"이 중요한 곳이죠. 읽기가 훨씬 많고 충돌은 드문 서비스라면 오히려 낙관적 락이 낫습니다.
비관적 락도 공짜는 아닙니다. 대기가 쌓이면 처리량이 떨어지고, 여러 락을 엇갈린 순서로 잡으면 데드락 위험도 생깁니다. 잠그는 범위와 시간은 짧을수록 좋습니다.

정리하며
비관적 락은 "충돌은 잦다"는 가정 위에서, 미리 잠가 정확성을 지키는 방식입니다.
낙관적 락과 비관적 락 사이에 정답은 없습니다. 충돌 빈도와 대기 비용에 따라 선택이 갈립니다.
저희 에그코드는 자체 서비스를 운영하며, 서비스마다 어느 쪽이 맞는지 따져 정합성 문제가 없도록 골라 적용합니다.
다음 편 예고 — 3편 «분산 락». 서버가 여러 대라면, DB 락만으로는 왜 부족할까요?
함께 읽어보세요 — 데드락과 라이브락, 동시성 함정 2가지 · 분산 락 — 서버가 여러 대면 DB 락으론 부족한 이유 · 커넥션 풀, 몇 개로 설정해야 할까
에그코드는 자체 서비스를 운영하며 웹·SaaS·MVP를 만듭니다. 서비스에 맞는 락 전략을 함께 고민합니다.
동시성·데이터 정합성이 걱정된다면 문의하기