# 송금 기능의 동시성 문제 해결 과정

### 문제 상황
- 송금 로직은 두 가지 주요 작업 포함
   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 등 다른 접근법 비교 검토 계획

1차: 기존 로직을 가지고 동시성 테스트를 해 보자