Kotlin Spring + Mybatis + Mysql 샘플 데이터 토이프로젝트 -1 공통 구조 정의

선종우·2024년 4월 15일
0

Spring 노트

목록 보기
1/10
  • 그동안 진행해왔던 사이드프로젝트에서 사용해왔던 기술을 정리하는 차원에서 기본기를 다시 다지는 토이프로젝트를 진행하였다.
  • 향후 실제 프로젝트를 진행할 때 참고할 수 있는 기술노트 성격으로도 활용하고자 한다.

  • 이번 포스트에서는 다양한 애플리케이션에 적용 가능한 공통 응답, 에러처리 형태를 정리하였다.

1. 기본 공통 응답 형태 설정

  • 클라이언트와 통신하기 위한 데이터 형태를 정의하였다.
data class CommonApiResponse<T>(
      val success: Boolean = false,
      val data: T? = null,
      val errorCode: ErrorCode? = null,
      val message: String? = null
)
enum class ErrorCode(
    val code: String,
    val message: String,
    val httpStatusCode: HttpStatus,
    val logLevel: Level = Level.WARN
) {
    UNKNOWN_SERVER_ERROR("F99999", "알 수 없는 서버 에러입니다", HttpStatus.INTERNAL_SERVER_ERROR)
}

2. 기본 예외 형태 구현

  • 애플리케이션 전역에서 사용할 기본 에러 형태를 정의하였다.
// 기능별 예외를 신규로 생성할 수 있으므로 open 키워드를 사용해 상속 가능한 형태로 둔다
open class BaseServiceException(val errorCode: ErrorCode, cause: Throwable?) : RuntimeException(errorCode.message, cause) {
    constructor(errorCode: ErrorCode) : this(errorCode, null)
}

3. 기본 에러처리 구현

  • 예상치 못한 에러 대응을 위한 전역 기본 전역 예외처리 핸들러를 등록하고, 서비스 로직 수행 중 발생한 예외를 처리하기 위한 baseExceptionHandler를 등록한다
@RestControllerAdvice
class ExceptionHandlerAdvice : Log {

    @ExceptionHandler(Exception::class)
    fun unExpectedExceptionHandler(e: Exception): ResponseEntity<CommonApiResponse<Any?>>{
        log.error("UNEXPECTED_ERROR!! message: {}", e.message)

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(
            CommonApiResponse(
                success = false,
                errorCode = ErrorCode.UNKNOWN_SERVER_ERROR,
                message = ErrorCode.UNKNOWN_SERVER_ERROR.message
            )
        )
    }

    @ExceptionHandler(BaseServiceException::class)
    fun baseExceptionHandler(e: BaseServiceException, request: HttpServletRequest): ResponseEntity<CommonApiResponse<Any?>>{
        val errorMessage = e.message.orEmpty()
        val errorCode = e.errorCode

        when (errorCode.logLevel) {
            Level.TRACE -> log.trace("[ServiceException] request method: ${request.method}, request uri: ${request.requestURI}, error message: $errorMessage")
            Level.DEBUG -> log.debug("[ServiceException] request method: ${request.method}, request uri: ${request.requestURI}, error message: $errorMessage")
            Level.INFO -> log.info("[ServiceException] request method: ${request.method}, request uri: ${request.requestURI}, error message: $errorMessage")
            Level.WARN -> log.warn(
                "[ServiceException] request method: ${request.method}, request uri: ${request.requestURI}, error message: $errorMessage",
                e
            )
            Level.ERROR -> log.error(
                "[ServiceException] request method: ${request.method}, request uri: ${request.requestURI}, error message: $errorMessage",
                e
            )
        }

        return ResponseEntity.status(HttpStatus.OK).body(
            CommonApiResponse(
                success = false,
                errorCode = errorCode,
                message = errorMessage
            )
        )
    }
}

0개의 댓글