[포토그램] 1. 회원가입 - 전처리 & 후처리

kiwonkim·2021년 9월 14일
0

이전 포스팅

Form 태그 입력결과를 비밀번호 해시까지 진행 후 DB에 저장하였다.
입력 ID에 길이 제한을 두거나, Unique한 ID만 들어오게 하려면 어떻게 해야할까?

20자 이하인 경우는 1번에서 전처리로 처리 할 수 있다.
하지만 unique 한지 확인하려면 JPA를 통해 DB를 거쳐야 하므로 2번의 후처리를 통해서만 처리 가능하다.

전처리는 보통 Validation 으로, 후처리는 Exception Handler를 통해 처리하는데 이에 대해 알아보자.



Validation

1. if문 추가를 통한 검증

AuthController 의 @PostMapping 부분.
if문 추가로 username 길이 검증을 진행한다.
Controller가 지저분해지는 문제가 있다.



2. Valid 어노테이션 사용

1) porm.xml에 Spring-boot-Validation 라이브러리를 추가한다.


2) signupDto에 제약조건들을 지정한다. (Validation)

Spring-boot-Validation의 어노테이션들

Annotation조건
@Notnullnull 불가
@Nullnull만 가능
@NotEmpty빈 문자열 불가
@Size(min =, max = )문자열, 배열의 크기 제약조건
@Pattern(regex=)정규식 만족여부
@Max(숫자)지정 값 이하만 가능
@Min(숫자)지정 값 이상만 가능
@Positive양수만 가능
@PositiveOrZero양수 or 0만 가능
@Negative음수만 가능
@NegativeOrZero음수 or 0만 가능
@Email이메일 형식만 가능
@DecimalMax(value= )지정된 값(실수) 이하만 가능
@DecimalMin(value= )지정된 값(실수) 이상만 가능
@AssertFalsefalse만 가능
@AssertTruetrue만 가능

3) User에서 DB 삽입시 제약조건도 지정한다.(JPA)


4) Controller 에서 검증 오류시 처리를 지정한다.

  • SignupDto에 @Valid 추가.
  • BindingResult 객체를 함께 넘겨줌.
    BindingResult.hasErrors()는 검증 오류 발생시 True 반환
    BindingResult.getFieldErrors()는 검증 오류를 FieldError 객체로 저장한 리스트를 반환
    -FieldError.getField() 는 발생필드를, FieldError.getDefaultMessage()는 검증오류 발생시 출력할 기본 메시지를 반환한다.
  • {발생필드 : 기본 메시지} 형태로 해시맵인 errorMap에 저장하여 사용한다.

5) 20글자 넘는 Username 삽입 시 오류 메시지 출력

상단의 FieldError DefaultMessage와. 하단의 User의 JPA로 DB제약조건을 걸어놓아 DB삽입시 에러를 뱉는 것을 확인할 수 있다.



Validation 보완

@Valid를 통해 검증을 추가하고 검증 오류 발생시 별도의 처리를 할 수 있게 되었다. 이 때 오류 발생시는 @ResponseBody로 메시지를 반환하고, 오류가 없다면 뷰를 넘겨주려면 어떻게 해야할까?

@ResponseBody를 메서드에 추가하면 모든 반환이 Body 반환이 되기에 ViewResolver가 동작하지 않게된다. 따라서 오류 발생시 Exception 을 던지고 처리해야한다.


1) Controller 에서 Valid 위반 존재시 RuntimeException을 던진다


2) ControllerExceptionHandler 클래스를 생성한다.

@ControllerAdvice 어노테이션을 추가하면 모든 Excepction을 가로챈다.

@ExceptonHandler 어노테이션을 추가하면 해당 Exception 발생시 처리를 지정할 수 있다.

여기서는 e.getMessage()를 리턴하는데 @RestController 기에 뷰 반환이 아닌 메시지 자체를 사용자에게 전송하게된다.

수행 결과이다. 유효성검사 실패함이 아닌 HashMap의 ErrorField별 메시지를 반환하려면 어떻게 해야할까? Exception 의 매개변수로는 String 밖에 넘길 수 없다.



Validation 보완 v2

bindingResult 에 error 가 존재한다면 RuntimeException을 던졌다.
ControllerExceptionHandler 클래스에서 @ControllerAdvice로 모든 Exception을 가로채서 RuntimeException 이면 Exception.getMessage로 예외메시지를 반환하도록 해주었다.
그런데 Exception 객체는 String 밖에 담을 수 없어 예외메시지 밖에 반환할 수 없다. error 내용을 반환하려면 어떻게 해야할까?

1) RuntimeException을 상속하는 CustomValidationException 클래스를 생성한다.

CustomValidationException 클래스는 필드로 errorMap 객체를 갖는다.


2) ExceptionHandler 가 메시지가 아닌 errorMap 객체를 반환하도록 한다.


3) Controller 에서 에러 존재시 RuntimeException 이 아닌 CustomValidationException을 던진다. 이때 errorMap을 같이 넘겨준다.


errorMap 을 반환하고, 메시지 컨버터가 Json으로 변환하여 출력된 것을 볼 수 있다.
필드 : 에러메시지가 반환되었다.


Validation 보완 v3

예외 발생 시 해시맵인 errorMap을 반환하며, 필드 : 에러미시지 형태로 반환이 진행된다.
이때 "유효성검사 실패함" 메시지와 errorMap을 함께 출력하고 싶은데 이럴땐 어떻게 해야할까?

ControllerExceptionHandler 의 반환형이 Map<String, String>이므로 현재는 errorMap만 반환 가능한 상태이다. 따라서 둘 다 출력하기 위한 새로운 Dto를 만들어줘야 한다.

1) CMRespDto 클래스를 생성한다. 필드로 String 과 Map<String, String>을 갖는다.


2) ControllerExceptionHandler 에서 CMRespDto 객체를 반환하도록 변경한다.


message와 errorMap이 동시에 출력된다.



Validation 보완 v4

메시지와 errorMap을 동시에 출력할 수 있게 되었다.
errorMap 말고 User 같은 다른 타입의 데이터를 출력하고 싶을 땐 어떻게 해야할까?

1) CMRespDto 에서 제네릭 추가. data의 타입은 제네릭으로 결정.


2) ControllerExceptionHandler 에서 제네릭 타입을 결정하여 사용한다. errorMap은 Map<String,String> 을, String 이면 <String>으로 제네릭 결정.
반환형은 <?> 으로 제네릭 추론 사용.


제네릭으로 <String>을 사용하면 문자열도 잘 반환하는 모습이다.



Validation 보완 v5

이제 회원가입 validation 처리결과를 code, message, 그리고 원하는 데이터를 CMRespDto 객체에 담아 반환할 수 있게 되었다.

그런데 이게 사용자 입장에서는 상당히 불편하다. JS를 활용한 alert가 표시되도록 변경해보자.


1) Script 클래스의 back 함수를 생성한다. back 함수는 String 을 받아 이를 alert 로 출력하고 뒤로가기 시키는 js 코드 문자열을 반환하는 함수읻.

2) ControllerExceptionHandler 에서 Script.back 메서드 수행결과 js 코드를 반환한다.


3) 수행결과

수행결과 제대로 errorMap을 출력하는 JS코드가 브라우저로 반환되어 경고창을 출력하는 것을 볼 수 있다.


Ajax나 Android 같이 응답결과를 개발자가 사용할 경우 CMRespDto 로 결과를 반환하는 것이.
클라이언트에게 결과를 전송할 경우 Script 로 결과를 반환하는 것이 유용하다.

0개의 댓글

관련 채용 정보