Issue 1: 중복 정산

개선 전

일반 조회 쿼리 사용. 동시 접근 시 A 트랜잭션이 커밋하기 전 B 트랜잭션도 데이터를 읽어갈 수 있음.

public interface SettlementRepository extends JpaRepository<Settlement, Long> {
    //  락 없음: 동시성 이슈 발생 위험
    @Query("SELECT s FROM Settlement s JOIN FETCH s.seller WHERE s.status = :status")
    List<Settlement> findAllByStatus(SettlementStatus status, Pageable pageable);
}

개선 후

비관적 락 적용

public interface SettlementRepository extends JpaRepository<Settlement, Long> {
		// 비관적 락 적용
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("SELECT s FROM Settlement s JOIN FETCH s.seller WHERE s.status = :status")
    List<Settlement> findAllByStatus(SettlementStatus status, Pageable pageable);
}

Issue 2: 데드락

개선 전

ID 추출 시 정렬 과정 없음. 입력 데이터 순서에 따라 락 순서가 뒤죽박죽되어 교착 상태

// 정렬되지 않은 ID 리스트
List<Long> memberIds = settlements.stream()
    .map(s -> s.getSeller().getId())
    .collect(Collectors.toList()); // [50, 10, 30] 순서일 수 있음

// 결과: 50 -> 10 -> 30 순서로 락 시도 (다른 트랜잭션과 충돌 가능)
paymentSupport.findWalletsByMemberIdsForUpdate(memberIds);

개선 후