Custom Error 처리

세모네모동굴배이·2025년 8월 6일
@Import(EndpointExceptionHandler::class)
@SpringBootApplication
class Application {
    companion object {
        const val VERSION: String = "v1"
    }
}
package net.test.exception

import io.jsonwebtoken.ExpiredJwtException
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice


@RestControllerAdvice
class EndpointExceptionHandler {

    @ExceptionHandler(ApplicationException::class)
    fun handleResponse(t: ApplicationException): ResponseEntity<MessageResponse> = t.response(t.classify.statusCode)

    private fun ApplicationException.response(status: Int): ResponseEntity<MessageResponse> = ResponseEntity.status(
        status,
    ).body(MessageResponse(this.classify.code, this.message, this.classify.innerCode))

    data class MessageResponse(
        val classify: String,
        val message: String?,
        val innerCode: Int,
    )
}

class ApplicationException(
    val classify: ErrorCode,
    override val cause: Throwable? = null,
) : RuntimeException(classify.label) {

    override val message: String get() = classify.label
}

fun throwError(error: ErrorCode, t: Throwable? = null): Nothing {
    if (t is ExpiredJwtException) {
        throw ApplicationException(CommonErrorCode.TokenExpired, t)
    }

    throw ApplicationException(error, t)
}
interface ErrorCode {
    val code: String
    val label: String
    val statusCode: Int
    val innerCode: Int
}
package net.test.exception

import org.apache.http.HttpStatus

object CustomErrorCode {

    object ParameterError : ErrorCode {
        override val code = "PARAMETER_ERROR"
        override val label = "데이터를 올바르게 입력해주세요"
        override val statusCode = HttpStatus.SC_BAD_REQUEST
        override val innerCode = 4000
    }
    object NotFoundUser : ErrorCode {
        override val code = "NOT_FOUND_USER"
        override val label = "사용자를 조회할 수 없습니다."
        override val statusCode = HttpStatus.SC_NOT_FOUND
        override val innerCode = 4001
    }

    object DuplicateUser : ErrorCode {
        override val code = "DUPLICATE_USER"
        override val label = "이미 등록된 사용자입니다."
        override val statusCode = HttpStatus.SC_BAD_REQUEST
        override val innerCode = 4002
    }

    object PasswordNotMatch : ErrorCode {
        override val code = "PASSWORD_NOT_MATCH"
        override val label = "비밀번호가 일치하지 않습니다."
        override val statusCode = HttpStatus.SC_UNAUTHORIZED
        override val innerCode = 4010
    }

    object UserSuspended : ErrorCode {
        override val code = "USER_SUSPENDED"
        override val label = "이용정지된 사용자입니다."
        override val statusCode = HttpStatus.SC_UNAUTHORIZED
        override val innerCode = 4010
    }

    object InvalidToken : ErrorCode {
        override val code = "INVALID_TOKEN"
        override val label = "유효하지 않은 토큰입니다."
        override val statusCode = HttpStatus.SC_UNAUTHORIZED
        override val innerCode = 4011
    }

    object GetFailed : ErrorCode {
        override val code = "GET_FAILED"
        override val label = "조회에 실패하였습니다."
        override val statusCode = HttpStatus.SC_INTERNAL_SERVER_ERROR
        override val innerCode = 5000
    }

    object DataIsEmpty : ErrorCode {
        override val code: String = "DATA_IS_EMPTY"
        override val label: String = "데이터가 없습니다."
        override val statusCode = HttpStatus.SC_BAD_REQUEST
        override val innerCode: Int = 999
    }

}

실제사용

throwError(CommonErrorCode.TokenExpired)

0개의 댓글