- 그동안 진행해왔던 사이드프로젝트에서 사용해왔던 기술을 정리하는 차원에서 기본기를 다시 다지는 토이프로젝트를 진행하였다.
- 향후 실제 프로젝트를 진행할 때 참고할 수 있는 기술노트 성격으로도 활용하고자 한다.
- 이번 포스트에서는 다양한 애플리케이션에 적용 가능한 공통 응답, 에러처리 형태를 정리하였다.
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 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
)
)
}
}