코틀린 스프링 4번째 시간입니다.
저번에 받는 데이터를 정형화 해봤는데요.
이번엔 반대로 서버에서 보내주는 값도 정형화하면서 예외처리도 같이 진행 해보겠습니다.
이 기록 겸 강의는 초보자 기준으로 작성이 되었고, 새로 시작하게 된 코틀린 스프링 유저에게 많은 도움이 될 수 있었다면 좋겠다는 마음으로 시작합니다.
틀린 부분이 있다면 알려주시면 감사하겠습니다.
시작하기 전에 Exception에 대해 알아보겠습니다.
들어오는 값을 Request, 나오는 값을 Response라고 합니다.
Requset가 잘못 되었거나, 서버의 상태의 대한 오류, 접근 불가등등 여러 이유로 오류가 발생할 수 있는데요.
그게 바로 Exception입니다.
하지만 따로 만들어주지 않을 경우 읽기가 어려운 경우가 많기 때문에 읽기 쉽고 문제점을 바로 알 수 있도록 수정을 해보겠습니다.
파일을 만들어주시고 진행 하겠습니다.
status > EnumStatus.kt
enum class ResultCode(val msg: String) {
SUCCESS("정상 처리 되었습니다."),
ERROR("에러가 발생했습니다.")
}
정상 처리와 에러 처리를 enum 클래스 새로 선언해줍니다.
dto > BaseResponse
data class BaseResponse<T> (
val resultCode: String = ResultCode.SUCCESS.name,
val data: T? = null,
val message: String = ResultCode.SUCCESS.msg,
)
정형화 된 값을 반환 해주기 위해 담을 틀을 만들고 아무런 값이 없을 경우 담길 기본 값을 넣어 줬습니다.
exception > InvalidInputException
class InvalidInputException(
val fieldName: String = "",
message: String = "Invalid Input"
) : RuntimeException(message)
정형화 된 값을 검사하는 @Valid가 아닌 곳에서 사용될 것을 만들었습니다.
이것들을 포함해서 이제 Cumstom을 해보겠습니다.
exception > CustomExceptionHandler
@RestControllerAdvice
class CustomExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException::class)//정형화된 값이 아닐 때
protected fun handleValidationExceptions(ex: MethodArgumentNotValidException):
ResponseEntity<BaseResponse<Map<String, String>>> {
val errors = mutableMapOf<String, String>()
ex.bindingResult.allErrors.forEach { error ->
val fieldName = (error as FieldError).field
val errorMessage = error.getDefaultMessage()
errors[fieldName] = errorMessage ?: "Not Exception Message"
}
return ResponseEntity(BaseResponse(
ResultCode.ERROR.name,
errors,
ResultCode.ERROR.msg
), HttpStatus.BAD_REQUEST)
}
@ExceptionHandler(InvalidInputException::class) // 잘못된 정보를 보냈을 때
protected fun invalidInputException(ex: InvalidInputException):
ResponseEntity<BaseResponse<Map<String, String>>> {
val errors = mapOf(ex.fieldName to (ex.message ?: "Not Exception Message"))
return ResponseEntity(BaseResponse(
ResultCode.ERROR.name,
errors,
ResultCode.ERROR.msg
), HttpStatus.BAD_REQUEST)
}
@ExceptionHandler(Exception::class)//위에 해당사항이 없을때
protected fun defaultException(ex: Exception):
ResponseEntity<BaseResponse<Map<String, String>>> {
val errors = mapOf("미처리 에러 " to (ex.message ?: "Not Exception Message"))
return ResponseEntity(BaseResponse(
ResultCode.ERROR.name,
errors,
ResultCode.ERROR.msg
), HttpStatus.BAD_REQUEST)
}
}
@ExceptionHandler라는 걸 스프링에게 알려줘서 예외가 일어났을 경우 해당하는 Exception을 찾아 실행 시켜줍니다.
그리고 추가적으로 회원 가입로직에 불편하게 사용 되는 부분이 있어 수정하겠습니다.
fun signUp(memberDtoRequest: MemberDtoRequest): String{
var member: Member? = memberRepository.findByLoginId(memberDtoRequest.loginId)
if(member != null){
return "이미 등록된 ID 입니다."
}
member = Member(
null,
memberDtoRequest.loginId,
memberDtoRequest.password,
memberDtoRequest.name,
memberDtoRequest.email,
memberDtoRequest.area
)
memberRepository.save(member)
val memberRole = MemberRole(null, ROLE.MEMBER, member)
memberRoleRepository.save(memberRole)
return "회원 가입 완료"
}
member객체에 각각의 값을 따로 넣어주는건 좀 불편해보이기 때문에 수정하는건데요
memberDtos를 수정해줍니다.
data class MemberDtoRequest(
/**
* 전 내용과 동일
*/
) {
/**
* 전 내용과 동일
*/
fun toEntity(): Member =
Member(id, loginId, password, name, email, area)
}
서비스 로직에서 담지 않고 memberDtoRequest.toEntity()를 이용해 담을 수 있도록 해줍니다.
service를 수정해줍니다.
fun signUp(memberDtoRequest: MemberDtoRequest): String{
var member: Member? = memberRepository.findByLoginId(memberDtoRequest.loginId)
if(member != null){
return "이미 등록된 ID 입니다."
}
member = memberDtoRequest.toEntity()
memberRepository.save(member)
return "회원 가입 완료"
}
이를 이용해서 간단하게 수정해줬습니다.
새로 만든 기능을 이용해서 정형화된 값으로 반환을 하기위해 controller를 수정해보겠습니다.
@PostMapping("signup")
fun signUp(@RequestBody @Valid memberDtoRequest: MemberDtoRequest): BaseResponse<Unit>{
val resultMsg : String = memberService.signUp(memberDtoRequest)
return BaseResponse(message = resultMsg)
}
이렇게 수정을 하고 알맞은 값을 보낸다면
BaseResponse<Unit>라는 객체엔 아래와 같은 내용이 담겨서 사용자에게 돌아간다고 볼 수 있습니다
- resultCode : SUCCESS
- data : null
- message : 회원가입완료
이렇게 오늘은 정형화된 값으로 반환 해줄수 있도록 변환해 봤습니다.
- 비밀번호 암호화
- 로그인 및 다른 기능들
오류 제어- 그 이외의 것들
다음은 로그인과 보안쪽을 해보려고 합니다.
부족한 글 읽어 주셔서 감사합니다.
피드백은 언제든 환영입니다.
'BackEnd > 코틀린 스프링' 카테고리의 다른 글
[Kotlin Spring] 프로젝트 04. JWT를 이용해 로그인 구현하기 01: JWT토큰 생성 (1) | 2024.11.04 |
---|---|
[Kotlin Spring] 프로젝트 Extra00. InteliJ에서 http통신 보내기 (0) | 2024.10.29 |
[Kotlin Spring] 프로젝트 02. 회원 가입 데이터 값 확인 (0) | 2024.10.28 |
[Kotlin Spring] 프로젝트 01. 회원 가입 만들기 (1) | 2024.10.28 |
[Kotlin Spring] 프로젝트 00. 프로젝트 초기 설정 (4) | 2024.10.27 |