서버 한 대에서만 동작하는 애플리케이션이라면 synchronized, ReentrantLock, 데이터베이스 락만으로도 동시성 문제를 해결할 수 있다. 하지만 서버가 여러 대로 늘어나고, 각 인스턴스가 동일한 자원을 수정하게 되는 순간 기존 방식은 더 이상 안전하지 않다.
이때 등장하는 개념이 분산 락이다. 분산 락은 여러 서버 인스턴스가 하나의 공유 자원에 접근할 때 “지금 누가 작업 중인지”를 중앙에서 일관되게 관리하기 위한 장치다. 대표적인 구현체로 Zookeeper와 Redisson이 있다. 이 글에서는 분산 락이 언제 필요한지, 그리고 두 도구를 언제 선택해야 하는지 정리한다.
분산 락이 필요한 상황
분산 락은 모든 시스템에 필요한 것은 아니다. 오히려 대부분의 경우에는 필요 없는 기술이다. 문제가 되는 상황은 “여러 서버가 동시에 같은 데이터를 수정할 때”다. 대표적인 예는 재고 차감, 쿠폰 발급, 이벤트 참여, 정산 처리 같은 작업이다.
서버가 한 대일 때는 애플리케이션 락으로 충분하지만, 서버가 두 대 이상이면 각 서버는 서로의 상태를 알 수 없다. 각자 락을 획득했다고 착각한 채 같은 데이터를 동시에 수정하게 된다. 이때 데이터베이스 락만으로도 해결할 수는 있지만, 트래픽이 많아질수록 DB 병목이 심해진다.
즉, 분산 락은 “여러 서버에서 동일한 임계 영역을 보호해야 할 때” 선택하는 도구다. 모든 요청에 락을 거는 것이 아니라, 정말 충돌 가능성이 높은 구간에만 제한적으로 사용하는 것이 중요하다.
Zookeeper 기반 분산 락 특징
Zookeeper는 분산 시스템을 위한 코디네이션 서비스다. 분산 락, 리더 선출, 설정 관리 등을 일관성 있게 처리하도록 설계되었다. Zookeeper 기반 분산 락의 핵심은 임시 노드(Ephemeral Node)와 순차 노드다.
락을 획득하려는 클라이언트는 특정 경로에 노드를 생성하고, 가장 앞선 노드를 가진 클라이언트만 락을 획득한다. 세션이 끊기면 임시 노드는 자동으로 제거되므로 락이 영구적으로 남지 않는다. 이 특성 덕분에 정합성과 안정성이 매우 높다.
다만 Zookeeper는 운영 비용이 높은 편이다. 별도의 클러스터를 구성해야 하고, 설정과 모니터링도 필요하다. 그래서 금융, 결제, 강한 일관성이 필요한 시스템처럼 락의 정확성이 최우선인 경우에 적합한 선택이다.
Redisson 기반 분산 락 특징
Redisson은 Redis를 기반으로 한 분산 락 라이브러리다. Redis의 빠른 성능과 Lua 스크립트를 활용해 락을 구현한다. Spring 환경에서 사용하기 쉽고, 설정 부담이 상대적으로 적다.
Redisson 분산 락의 핵심은 락 획득과 해제를 원자적으로 처리한다는 점이다. 또한 Watchdog 기능을 통해 락을 잡은 스레드가 살아 있는 동안 TTL을 자동 연장해준다. 이로 인해 락 만료로 인한 사고를 어느 정도 방지할 수 있다.
다만 Redis는 기본적으로 메모리 기반 저장소다. 네트워크 분리나 장애 상황에서는 일관성이 깨질 가능성도 존재한다. 그래서 Redisson은 “완벽한 락”보다는 “현실적으로 충분한 락”이 필요한 대부분의 웹 서비스에 적합하다.
분산 락 사용 기준 정리
분산 락을 도입하기 전에 반드시 질문해야 할 것이 있다.
정말 분산 락이 필요한가?
데이터베이스 락이나 낙관적 락으로 해결할 수는 없는가?
분산 락은 복잡성을 크게 증가시킨다.
정리해보면, 강한 일관성과 안정성이 최우선이면 Zookeeper가 적합하다. 운영 부담은 있지만 락의 신뢰도가 매우 높다. 반대로 빠른 개발과 적당한 안정성이 필요하다면 Redisson이 현실적인 선택이다.
가장 중요한 점은 분산 락을 남용하지 않는 것이다. 락은 시스템의 병목이 될 수 있다. 정말 임계 영역에만 적용하고, 가능하다면 낙관적 락이나 메시지 큐 같은 대안도 함께 검토하는 것이 좋은 설계로 이어진다.