본문 바로가기
스파르타 내일배움캠프/TIL(Today I learned)

에러코드 출력 관련 트러블 슈팅

by pandastic 2025. 6. 16.
반응형

 

 

 

목차

     

     

     

    ✅ 트러블 슈팅

    1. 문제 상황

    • 고의로 중복 예약을 하여 오류를 발생시켰을 때 에러 코드가 조건에 따라 설정해두었던 에러 코드로 뜨지 않는 현상 발생.

    Postman 실행 시 출력되는 에러 메시지.

     

    • 원래 출력되어야 하는 에러 메시지.
    DUPLICATED_RESERVATION(HttpStatus.CONFLICT, "이미 중복된 예약이 존재합니다."),

     

     

    2. 원인 분석

    • 분산락 설정 코드에 있던 try catch 문으로 인해서 에러 코드가 정상적으로 출력되지 않음.
    @Aspect
    @Component
    @RequiredArgsConstructor
    @Slf4j
    public class DistributedLockAspect {
    
        private final RedissonClient redissonClient;
        private final PlatformTransactionManager transactionManager;
    
        @Around("@annotation(distributedLock)")
        public Object lock(ProceedingJoinPoint joinPoint, DistributedLock distributedLock)
                throws Throwable {
            String key = distributedLock.key();
            long waitTime = distributedLock.waitTime();
            long leaseTime = distributedLock.leaseTime();
    
            RLock rlock = redissonClient.getLock(key); //락 획득할 준비
    
            boolean isLocked = false;
            try{
                isLocked = rlock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS); // 락 점유하기 위함
                if(!isLocked){ // 대기중(wait time)
                    throw new IllegalStateException("락 획득 실패 : key = " + key);
                }
    
                log.info("락 획득 성공: key = {} ", key);
                TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
                transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    
                return transactionTemplate.execute(status -> { // 트랜잭션 시작
                    try{
                        return joinPoint.proceed();
                    }catch (Throwable throwable){
                        status.setRollbackOnly();
                        throw new RuntimeException(throwable);
                    }
                }); // 트랜잭션 커밋
            } finally {
                if(isLocked && rlock.isHeldByCurrentThread()){
                    rlock.unlock();
                    log.info("락 해제: key = {}", key);
                }
            }
        }
    }



    3. 해결 방법

    • try catch문에 catch 문 추가.
    return transactionTemplate.execute(status -> { // 트랜잭션 시작
        try{
            return joinPoint.proceed();
        }catch(BaseException e) { // 예외 발생 시
            status.setRollbackOnly();
            throw e;
        }catch (Throwable throwable){
            status.setRollbackOnly();
            throw new RuntimeException(throwable);
        }
    }); // 트랜잭션 커밋
    반응형