피드로 돌아가기
컬리 기술블로그Backend
원문 읽기
풀필먼트 입고 서비스팀에서 분산락을 사용하는 방법 - Spring Redisson
컬리 입고서비스팀이 Spring Redisson 기반 어노테이션 AOP를 도입해 멀티 인스턴스 환경에서 동시성 제어 구현
AI 요약
Context
RMS(입고관리 시스템)에서 카프카의 중복 발주 수신, 검수 등록 시 더블 클릭, 네트워크 이슈로 인한 중복 요청 등 다양한 동시성 문제가 발생했다. 애플리케이션 레벨의 예외 처리만으로는 멀티 인스턴스 환경에서 동시성 제어가 불충분했다.
Technical Solution
- Redis Redisson을 선택한 이유: Lettuce 대비 Lock interface를 기본 제공해 retry, timeout 설정이 간편하고, Pub/Sub 방식으로 Redis 부하 감소
- Redisson 의존성 추가:
org.redisson:redisson-spring-boot-starter:3.18.0빌드 스크립트에 포함 - RedissonConfig 클래스로 RedissonClient 빈 등록: Spring 환경설정에서 Redis 호스트/포트를 읽어 Config 객체로 변환
- @DistributedLock 커스텀 어노테이션 제공: key(필수), timeUnit, waitTime(기본값 5초), leaseTime(기본값 3초) 파라미터로 구성
- DistributedLockAop 클래스로 @Around 를 이용한 락 획득/해제 로직 구현: CustomSpringELParser로 동적 파라미터 평가, AopForTransaction으로 별도 트랜잭션 분리 처리
Impact
분산락이 미적용된 경우 동일한 발주코드로 10개의 동시 요청 발생 시 중복 등록되었으나, 분산락 적용 후 1건만 등록되는 것으로 검증됨.
Key Takeaway
멀티 인스턴스 환경에서 동시성 문제를 처리할 때, Redisson의 Lock interface와 Pub/Sub 메커니즘을 어노테이션 기반 AOP로 래핑하면 비즈니스 로직 오염 없이 분산락을 선언적으로 적용할 수 있다.
실천 포인트
Spring 환경의 멀티 인스턴스 서비스에서 동시성 제어가 필요한 메서드는 Redisson @DistributedLock 어노테이션을 적용하고 key 파라미터에 SpEL(Spring Expression Language)을 통해 동적 락 이름을 지정하면, 비즈니스 코드 수정 없이 선언적으로 분산락을 적용할 수 있다.