Transactional 과 Exception 그리고 로그 저장

By | 2025년 9월 10일
Table of Contents

Transactional 과 Exception 그리고 로그 저장

예외가 발생했을 때 로그를 저장하고 예외를 발생시키려 한다.
하지만 로그가 저장이 되지 않는다.

예제

정상적으로 실행되고 로그가 저장될 것처럼 보이지만 로그는 저장되지 않는다.
Transactional 에 의해 DB 저장이 롤복되기 때문이다.

@Transactional
public LoginResponse login(LoginRequest request, String ipAddress, String userAgent) {
    String email = request.getEmail();

    Optional<User> userOptional = userRepository.findByEmail(email);
    if (userOptional.isEmpty()) {
        loginLogService.logFailedLogin(email, ipAddress, userAgent, "존재하지 않는 이메일");
        throw new LoginFailedException("이메일 또는 비밀번호가 올바르지 않습니다.");
    }

    // ......
}

@Transactional
public void logFailedLogin(String email, String ipAddress, String userAgent, String failureReason) {
    LoginLog loginLog = LoginLog.builder()
            .email(email)
            .ipAddress(ipAddress)
            .userAgent(userAgent)
            .status(LoginLog.LoginStatus.FAILURE)
            .failureReason(failureReason)
            .build();

    loginLogRepository.save(loginLog);
    log.warn("Failed login logged for email: {}, IP: {}, Reason: {}", email, ipAddress, failureReason);
}

해결

REQUIRES_NEW 를 이용해 아예 별도의 DB 연결로 분리해 주어야 한다.
다만 별도의 DB 연결이 된다는 의미는 한개의 DB 연결이 아니라 두개의 DB 연결을 필요로 한다는 의미가 된다.

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logFailedLogin(String email, String ipAddress, String userAgent, String failureReason) {
    // ......
}

답글 남기기