인프런 커뮤니티 질문&답변

YUNHA PARK님의 프로필 이미지

작성한 질문수

스프링 DB 2편 - 데이터 접근 활용 기술

트랜잭션 전파 활용7 - 복구 REQUIRES_NEW

트랜잭션 전파 시 체크 예외를 활용한 복구 처리 관련 문의

작성

·

549

3

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]

"회원 가입을 시도한 로그를 남기는데 실패하더라도 회원 가입은 유지 되어야 한다." 이 요구사항을 만족하기 위한 방법1.2 이외에 체크 예외를 활용하는 방법3 관련 문의입니다.

방법1. REQUIRES_NEW로 선언해서 물리 트랜잭션 분리

방법2. MemberFacade 구조를 사용하여 물리 트랜잭션 분리

방법3. 체크 예외를 던져서 오류 관련 내용 커밋(9.스프링 트랜잭 션 이해 / 예외와 트랜잭션 커밋, 롤백 - 활용)


질문. 체크예외를 활용하면 코드에 명시적으로 오류 상황에 대 한 처리를 할 수 있어서 개발자가 오류를 코드 레벨에서 인지할 수도 있고 오류를 받을 때 로그 상태를 저장할 수 도 있다는 장점 이 있을 것 같은데 비즈니스 적으로 의미가 있는 경우에는 체크예외를 사용하고 그 외에는 방법1,2를 선택하면 되는지 궁금합니 다. (오류 처리로 서비스 코드를 지저분하게 만들게 하고 싶지 않 는 경우 방법1,2를 사용하는지?)

참고) 아래는 위 내용을 테스트 할 때 작성한 코드 입니다.

체크예외를 사용하는 서비스 메소드 내용

@Transactional
public void joinV3(String username) throws Exception {
    Member member = new Member(username);
    Log logMessage = new Log(username);

    log.info("== memberRepository 호출 시작 ==");
    memberRepository.save(member);
    log.info("== memberRepository 호출 종료 ==");

    log.info("== logRepository 호출 시작 ==");
    try {
        logRepository.saveV2(logMessage);
    } catch (Exception e) {
        log.info("log 로그 저장에 실패했습니다. logMessage={}", logMessage.getMessage());

        logRepository.saveV2(new Log("체크예외발생!!"));
        log.info("joinV3: 체크 예외가 발생하였습니다!!!");
    }
    log.info("== logRepository 호출 종료 ==");
}

체크예외를 던지는 logRepository.saveV2 내용

@Transactional
public void saveV2(Log logMessage) throws Exception {
    log.info("log 저장");

    if (logMessage.getMessage().contains("로그예외")) {
        log.info("log 저장시 예외 발생");
        throw new Exception("예외 발생");
    }

    em.persist(logMessage);
}

회원가입요청 서비스를 테스트하는 코드 내용

/**
 * MemberService    @Transactional: ON
 * MemberRepository @Transactional: ON
 * LogRepository    @Transactional Checked Exception
 */
@Test
void recoverCheckedException_success() throws Exception {
    // given
    String username = "로그예외_outerTxOn_fail";
    String errorUsername = "체크예외발생!!";

    // when
    memberService.joinV3(username);

    // then: member 저장, log 오류내용 저장
    assertTrue(memberRepository.find(username).isPresent());
    assertTrue(logRepository.find(errorUsername).isPresent());
}

답변 1

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. YUNHA PARK님

생각하신 것 처럼 진행하셔도 됩니다.

참고로 꼭 체크 예외가 아니어도 강의에서 설명드린 것 처럼 @Transactional에 커밋하고 싶은 예외를 지정할 수 있습니다.

감사합니다.

YUNHA PARK님의 프로필 이미지
YUNHA PARK
질문자

넵 답변 감사합니다!!