현금성 재화가 오가는 게임에서 재시도 로직 없이 정합성을 지킨 비결
![]()
금융 플랫폼 안에서 게임을 돌린다고 생각해보세요. 캐릭터 레벨도 올라가고 SAL이라는 재화도 쌓이는데, 이게 현금성이에요. 유저 액션, 운영 변수, 배치 처리가 동시에 같은 데이터를 건드리는 상황에서 정합성이 깨지면? 돈이 허공에서 생기거나 사라지는 일이 벌어지죠. 뱅크샐러드 팀이 "일해라 김뱅샐"을 만들면서 마주한 근본적인 고민이었어요.
적절한 동시성 제어가 없으면 갱신 손실(Lost Update)이 발생해요. 두 요청이 동시에 같은 데이터를 읽고 각자 수정한 뒤 저장하면, 먼저 저장한 쪽의 변경이 사라지거든요. 현금성 재화가 오가는 시스템에서 이건 결코 타협할 수 없는 문제죠.
비관적 락도, 분산 락도 맞지 않았다
세 가지 잠금 방식을 검토했어요. 비관적 락은 DB 레벨에서 행을 선점하는 방식이라 정합성은 확실하지만, 대규모 트래픽에서 병목이 생길 수 있어요. 분산 락은 Redis를 활용해서 서버 인스턴스 간 자원 접근을 제어하지만, 별도 인프라 운영 비용이 발생하죠. 두 방식 다 이 서비스의 특성에는 과하거나 맞지 않았어요.
낙관적 락은 버전 번호를 통해 수정 시점에 데이터가 변했는지만 확인하는 방식이에요. DB 잠금 시간이 거의 없어서 성능이 최상이죠. `update_version` 컬럼 하나만 추가하면 구현할 수 있다는 점도 매력적이었어요.
캐릭터 데이터가 유저별로 격리된 구조가 결정적이었다
최종 선택은 낙관적 락이었어요. 결정적인 이유는 충돌 확률이 낮다는 점이에요. 캐릭터 데이터가 각 유저별로 격리된 구조라서, 서로 다른 유저의 요청이 같은 행을 건드릴 일이 없거든요. 같은 유저의 동시 요청만 충돌할 수 있는데, 그 빈도는 극히 낮죠.
인프라 복잡도 최소화도 중요했어요. Redis 같은 별도 인프라 없이 컬럼 하나로 해결되니까요. 게임다운 매끄러운 반응성 확보, 복잡한 재시도 로직이 필요 없는 서비스 구조까지 고려하면, 낙관적 락이 이 상황의 최적해였어요. 모든 상황에 맞는 만능 잠금은 없고, 서비스의 데이터 접근 패턴을 정확히 파악하는 게 올바른 선택의 출발점이라는 걸 보여주는 사례죠.