Skip to content

[BUG] ScheduledRecommendationService 일부 팀 실패 시 전체 롤백 #155

@ryuwldnjs

Description

@ryuwldnjs

상위 이슈


현상

배치 추천 생성 시 특정 팀에서 DB 예외가 발생하면, try-catch로 잡았음에도 이미 성공한 다른 팀의 추천까지 전부 롤백된다.

ScheduledRecommendationService.prepareDailyRecommendations()가 클래스 레벨 @Transactional로 전체 팀이 하나의 트랜잭션에서 실행되기 때문.

팀 A 추천 생성 → 성공
팀 B 추천 생성 → DB 예외 → save()의 @Transactional 프록시가 rollback-only 마킹
팀 C 추천 생성 → 성공
메서드 종료 → 커밋 시도 → UnexpectedRollbackException → 팀 A, C도 롤백

같은 문제를 가진 서비스

  • RecommendationEmailService.sendAll()

재현

로컬 MySQL 환경에서 통합 테스트로 재현한다.

1단계: 문제 재현

  1. 팀 3개 준비: 팀 A(정상), 팀 B(예외 유발), 팀 C(정상)
  2. RecommendationCreator@Transactional 추가
  3. 팀 B에서 RuntimeException 발생하도록 설정 (핸들 없음 등)
  4. prepareDailyRecommendations() 실행
  5. 검증: 팀 A, C의 Recommendation도 DB에 없음 → 전체 롤백 확인

2단계: 수정 후 검증

  1. RecommendationCreator.create()@Transactional(propagation = REQUIRES_NEW) 적용
  2. ScheduledRecommendationService의 클래스 레벨 @Transactional 제거
  3. 동일 테스트 실행
  4. 검증: 팀 B만 실패, 팀 A, C는 정상 저장

수정 방안

// RecommendationCreator: 팀별 독립 트랜잭션
@Transactional(propagation = Propagation.REQUIRES_NEW)
Recommendation create(Team team, RecommendationType type) { ... }

// ScheduledRecommendationService: 클래스 레벨 @Transactional 제거
// prepareDailyRecommendations()는 트랜잭션 없이 실행, 각 팀은 Creator가 관리

RecommendationEmailService도 동일하게 개별 이메일 발송을 독립 트랜잭션으로 분리한다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions