본문 바로가기
BackEnd/Project

[BigData] Ch05. Redis 코드 작성 및 배포(5)

by 개발 Blog 2024. 9. 16.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

 

이번 글에서는 Redis 조회 기능에 예외 처리를 추가하여 안정적인 시스템을 구축하는 방법에 대해 다룬다. Redis에서 데이터를 조회하는 과정에서 발생할 수 있는 다양한 예외 상황을 처리하고, 적절한 응답을 반환하는 구조를 만들어볼 것이다. 예외 처리를 통해 시스템의 신뢰성을 높이고, 사용자에게 보다 명확한 에러 메시지를 제공하는 것이 이번 글의 주요 목적이다.

 

1. ExController - 전역 예외 처리

Redis에서 발생할 수 있는 예외 상황 중 중요한 부분은 데이터가 존재하지 않는 경우다. 이를 처리하기 위해 ControllerAdvice를 사용하여 ExController를 구현했다. 이 클래스는 NotFoundException이 발생했을 때 이를 잡아, 클라이언트에게 적절한 오류 메시지와 함께 HTTP 상태 코드를 반환하는 역할을 한다.

package com.example.pricecompareredis.controller;

import com.example.pricecompareredis.vo.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
@Slf4j
public class ExController {

//        @ExceptionHandler({RuntimeException.class})
//    public ResponseEntity<Object> BadRequestException(final RuntimeException ex) {
//        return ResponseEntity.badRequest().body(ex.getMessage());
//    }
//
//        @ExceptionHandler({ xxxx.class })
//    public ResponseEntity<Object> EveryException(final Exception ex) {
//        return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
//    }

    @ExceptionHandler({ NotFoundException.class })
    public ResponseEntity<Object> NotFoundExceptionResponse(NotFoundException ex) {
        return new ResponseEntity<>(ex.getErrmsg(), ex.getHttpStatus());
    }
}

이렇게 전역 예외 처리를 통해, 개별 컨트롤러에서 중복된 예외 처리 코드를 작성하지 않고도 예외 발생 시 일관된 처리가 가능해진다.

 

2. LowestPriceController - 메서드에 예외 처리 추가

LowestPriceController에서는 기존의 Redis ZSET 조회 기능에 추가적인 예외 처리를 더했다. 각 메서드는 Redis에서 데이터를 조회할 때 발생할 수 있는 다양한 예외를 처리하도록 설계되었다.

@GetMapping("/product1")
public Set GetZsetValueWithStatus (String key){
    try {
        return mlps.GetZsetValueWithStatus(key);
    }
    catch (Exception ex) {
        throw new ResponseStatusException(
                HttpStatus.NOT_FOUND, ex.getMessage(), ex);
    }
}

@GetMapping("/product2")
public Set GetZsetValueUsingExController (String key) throws Exception {
    try {
        return mlps.GetZsetValueWithStatus(key);
    }
    catch (Exception ex) {
        throw new Exception(ex);
    }
}

@GetMapping("/product3")
public ResponseEntity<Set> GetZsetValueUsingExControllerWithSpecificException (String key) throws Exception {
    Set<String> mySet = new HashSet<>();
    try {
        mySet =  mlps.GetZsetValueWithSpecificException(key);
    }
    catch (NotFoundException ex) {
        throw new Exception(ex);
    }
    HttpHeaders responseHeaders = new HttpHeaders();

    return new ResponseEntity<Set>(mySet, responseHeaders, HttpStatus.OK);
}
  • 첫 번째 메서드 (product1): 이 메서드는 Redis에서 데이터를 조회할 때, 예외가 발생하면 ResponseStatusException을 통해 404 상태 코드와 함께 에러 메시지를 반환한다. 예외 발생 시 즉각적으로 클라이언트에게 오류를 알리는 것이 목표이다.
  • 두 번째 메서드 (product2): 이 메서드는 일반적인 예외를 모두 Exception으로 던지며, 전역 예외 처리 컨트롤러에서 이를 처리하도록 설계되었다. 예외를 던지는 방식으로 클라이언트에게 더 일반적인 응답을 제공한다.
  • 세 번째 메서드 (product3): 이 메서드는 특정 예외인 NotFoundException을 처리하고, Redis에서 데이터가 없을 때 이를 발생시킨다. 또한, 추가로 HTTP 헤더와 함께 응답을 구성해 클라이언트에게 더욱 구체적인 응답을 반환하는 방식으로 동작한다.

3. LowestPriceService 및 구현체 - 예외 처리 추가

LowestPriceService와 그 구현체에서는 Redis의 ZSET에서 값을 조회하는 메서드에 예외 처리가 추가되었다. 기존에 데이터를 조회하던 로직에 예외 상황을 추가하여, 조회 결과가 없거나 조건에 맞지 않을 경우 적절한 예외가 발생하도록 구성했다.

 

LowestPriceService

Set GetZsetValueWithStatus(String key) throws Exception;

Set GetZsetValueWithSpecificException(String key) throws Exception;

GetZsetValueWithStatus

  • 이 메서드는 Redis ZSET에서 값을 조회한 후, 결과가 없으면 일반 Exception을 던진다. 이는 클라이언트에게 Redis에서 데이터를 찾지 못했음을 알리기 위한 처리이다. 조회된 값이 없을 경우 예외를 발생시킴으로써, 시스템이 데이터 부족 상황을 정확히 인지하고 대응할 수 있게 한다.

GetZsetValueWithSpecificException

  • 이 메서드는 조회된 데이터가 없을 때 NotFoundException을 던진다. 이 예외는 사용자 정의 예외로, Redis에 데이터가 존재하지 않는다는 구체적인 메시지를 전달하고, 함께 HttpStatus.NOT_FOUND 상태 코드를 반환한다. 이를 통해 사용자에게 더욱 명확한 정보와 상태 코드를 제공할 수 있다.

LowestPriceServiceImpl

public Set GetZsetValueWithStatus(String key) throws Exception {
    Set myTempSet = new HashSet();
    myTempSet = myProdPriceRedis.opsForZSet().rangeWithScores(key, 0, 9);
    if (myTempSet.size() < 1 ) {
        throw new Exception("The Key doesn't have any member");
    }
    return myTempSet;
};

public Set GetZsetValueWithSpecificException(String key) throws Exception {
    Set myTempSet = new HashSet();
    myTempSet = myProdPriceRedis.opsForZSet().rangeWithScores(key, 0, 9);
    if (myTempSet.size() < 1 ) {
        throw new NotFoundException("The Key doesn't exist in redis", HttpStatus.NOT_FOUND);
    }
    return myTempSet;
};

GetZsetValueWithStatus

  • Redis에서 ZSET 값을 조회한 뒤, 해당 키에 데이터가 없으면 일반 Exception을 발생시킨다. 예를 들어, 주어진 키에 아무런 값도 없을 경우 "The Key doesn't have any member"라는 메시지를 담은 예외를 던지며, 이를 통해 Redis 데이터가 없는 상황을 명확히 알릴 수 있다.

GetZsetValueWithSpecificException

  • 이 메서드는 Redis에서 ZSET 값을 조회했을 때, 해당 키에 값이 없으면 NotFoundException을 발생시킨다. 예외 메시지로는 "The Key doesn't exist in redis"가 반환되며, HTTP 상태 코드로는 HttpStatus.NOT_FOUND가 함께 반환된다. 이 예외 처리는 일반적인 예외보다 구체적으로 Redis 데이터가 없을 때의 상황을 처리하기 위해 설계되었다.

4. NotFoundException - 커스텀 예외 클래스

NotFoundException은 Redis에서 데이터를 찾지 못했을 때 발생하는 사용자 정의 예외 클래스이다. 이 클래스는 예외가 발생할 때 전달할 메시지와 HTTP 상태 코드를 함께 관리하며, 전역 예외 처리 컨트롤러와 결합되어 사용된다. 이를 통해 예외 상황을 명확하게 처리하고, 사용자에게 의미 있는 정보를 전달할 수 있다.

package com.example.pricecompareredis.vo;

import lombok.Builder;
import lombok.Data;
import lombok.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@Data
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "No Keys in Redis")
public class NotFoundException extends RuntimeException {

    private String errmsg;
    private HttpStatus httpStatus;

    public NotFoundException(String errmsg, HttpStatus httpStatus) {
        this.errmsg=errmsg;
        this.httpStatus = httpStatus;
    }

}

 

이번 글에서는 Redis에서 데이터를 조회할 때 발생할 수 있는 예외 상황에 대해 처리하는 방법을 다뤘다. 예외 처리를 통해 시스템의 안정성을 높이고, 클라이언트에게는 명확한 에러 메시지와 상태 코드를 전달할 수 있다. 이를 통해 Redis와의 통합 시스템에서 더욱 견고한 아키텍처를 구축할 수 있게 되었다.