# 송금 기능의 동시성 문제 해결 과정
### 문제 상황
- 송금 로직은 두 가지 주요 작업 포함
1) 지갑에서 송금액 차감
2) 수신자가 받을 수 있는 거래 생성
- 다중 스레드 동시성 테스트 시 잔액 불일치 발생 (예: 100개 스레드 송금 후 2원만 차감됨)
- 금액이 더 크거나 대규모 사용자 환경에서는 치명적인 문제가 될 수 있음
### 해결 시도 1: 낙관적 락(Optimistic Lock)
- Wallet 엔티티에 **@Version 추가 적용**
- **초기 버전 값이 null**로 설정되어 **NullPointerException** 발생
- 성공률 매우 낮음 (100회 시도 중 3-4회만 성공)
- 낙관적 락으로 인한 재시도가 많아 **HikariCP Connection Pool 타임아웃** 발생
### 해결 시도 2: Redis를 활용한 분산 락
1. **Lettuce + SETNX 방식**
- setIfAbsent 메서드를 사용한 스핀 락 구현
- 여전히 잔액 불일치 문제 발생
2. **Redisson 활용 접근**
- **트랜잭션 시작 전 락 획득 방식**으로 변경
- 락 키를 UUID로 설정하여 각 요청마다 다른 락을 사용하는 문제 발견
- **락 키를 고정값으로 변경** 후 동시성 문제 해결
- 1000건 테스트 시 약 20초 소요, 모든 트랜잭션 성공
### 해결 시도 3: synchronized 키워드 국소적 적용
- synchronized는 다량 + 큰 범위 사용을 피하면 괜찮음 (자바 클래스 안에도 존재)
- 메서드 전체 또는 지갑 업데이트 부분에만 적용 시도
- 단독으로는 동시성 문제 해결 불충분
### 최종 해결책
- Redisson을 이용한 분산 락 + 락 키를 고정값으로 설정
- synchronized 제거 시 성능 향상 (1000건 처리 시간 20초 → 12초)
### 추가 고려 사항
- 낙관적 락 + "더티 체킹 삭제" 조합 테스트 계획
- Named Lock, Atomic Integer 등 다른 접근법 비교 검토 계획
낙관적 락을 통한 제어 성공, 나머지 실패
100개의 스레드 (User)를 통해 / 10초간 / 1번 반복 요청
지갑에 있는 돈: 200 → 102 확인
송금 요청 테이블에는 100개 쌓임