-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
🐛 Bug버그 수정 및 오류 해결버그 수정 및 오류 해결
Description
🐞 버그/에러 개요
비동기 메서드 @Async 사용 시 트랜잭션 분리로 인한 데이터 불일치 현상 발생
📝 상황 설명
📄 에러 대상
- AnswerServiceImpl.saveAnswer()
- FeedbackServiceImpl.saveFeedback()
🕵🏻♀️ 에러 상황
- saveAnswer()는 트랜잭션 안에서 Answer, Question 상태를 변경하고, 내부에서
@Async@Transactional이 적용된 saveFeedback()을 호출함 - 이후 의도적으로 RuntimeException을 발생시켜 saveAnswer()의 트랜잭션이 롤백되도록 설계
[Main Thread - saveAnswer()]
├── Answer 저장
├── Question 상태 업데이트
├── 비동기 saveFeedback() 호출
├── (예외 발생)
└── 전체 롤백
[Async Thread - saveFeedback()]
├── GPT API 호출
├── AnswerFeedback 저장
└── 독립적으로 커밋됨
문제점
- saveAnswer()에서 발생한 예외로 인해 Answer, Question은 DB에서 롤백됨
- 그러나 saveFeedback()은 별도 스레드에서 별도 트랜잭션으로 동작하여 커밋됨
- 이로 인해 실제 답변(Answer)은 없는데, 피드백(AnswerFeedback)은 존재하는 불일치 상태가 발생함
✅ Resolve TODO
- 비동기 메서드의 호출 시점/위치를 재검토 (트랜잭션 외부에서 호출되도록 리팩터링 고려)
- 트랜잭션 전파 전략, 트랜잭션 매니저 구성 방식 확인
📚 Remarks
- Spring에서
@Async와@Transactional을 함께 사용하면, 해당 메서드는 별도 스레드에서 새로운 트랜잭션으로 실행됨 - 호출부(saveAnswer)의 트랜잭션이 롤백되더라도, 비동기 메서드는 영향받지 않음
- 현재 구조에서는 서비스 내부에서 비동기 메서드를 호출하기 때문에, 데이터 정합성 문제의 위험성이 항상 존재함
비동기 처리 테스트 실패 - @Async 트랜잭션 분리 현상 검증 불가 (해당 테스트를 통과해야 입증 가능)
자세한 사항은 노션 참고
@SpringBootTest
@ActiveProfiles("test")
@EnableAsync // 테스트에서도 명시적으로 활성화
class AnswerServiceIntegrationTest {
@Test
@DisplayName("비동기 시 트랜잭션 미적용 테스트")
void saveAnswer_withAsyncFeedback_shouldCauseDataMismatch() throws InterruptedException {
// given
Long questionId = 1L;
AnswerDto dto = new AnswerDto("답변입니다");
// when - 예외를 던지기 전에 잠시 대기
try {
answerService.saveAnswer(dto, questionId);
Thread.sleep(1000); // saveFeedback 호출이 시작될 시간을 줌
throw new RuntimeException("일부러 트랜잭션을 깨뜨림");
} catch (RuntimeException e) {
// rollback 발생
}
// wait: 충분한 대기 시간
Thread.sleep(15000);
// then
List<Answer> answers = answerMapper.findAll();
List<AnswerFeedback> feedbacks = feedbackMapper.findAll();
System.out.println("Answers count: " + answers.size());
System.out.println("Feedbacks count: " + feedbacks.size());
assertThat(answers).isEmpty(); // 롤백됨
assertThat(feedbacks).isNotEmpty(); // rollback 안됨
}
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
🐛 Bug버그 수정 및 오류 해결버그 수정 및 오류 해결