본문 바로가기

👩‍💻 BackEnd/🍃 스프링부트 [SpringBoot]

[SpringBoot] 21강 전처리와 후처리

전처리 후처리 로직

 

회원 가입 시 사용자의 입력 값을 받는데 제약조건 위배로 인한 오류는 두가지가 발생할 수 있다고 가정하자.

 

1. 동일한 username이 존재함.

2. username 의 길이가 조건을 벗어남. 

 

각각 그림의 초록색, 파란색 박스가 있는 곳에서 오류가 발생한 것을 확인할 수 있다. 

즉, 길이의 경우 사용자가 입력을 완료하면 길이가 조건을 벗어나는지 바로 확인이 가능하고, 

동일한 username 이 존재하는지는 서버 -> JPA -> DB 까지 가서 확인을 해야 중복 값이 존재하는지 알 수 있다는 것이다. 

 

따라서 이 오류를 각각 처리를 해줘야하는데 이때 파란색 박스의 경우에는 전처리, 초록색 박스에는 후처리라고 부를 때

 

전처리의 경우에는 Validation (유효성 검사) 

후처리의 경우에는 Exceptionhandler 

 

회원가입 로직을 하나의 핵심 기능이라고 할 수 있는데 이 핵심 기능에 필요한 전처리, 후처리를 공통 기능이라고 한다. 

 

이를 AOP(관점지향프로그래밍) 라고 한다. 

 

이 전처리, 후처리의 로직을 서비스 로직에 작성하면 코드가 매우 복잡해지기 때문에 다른 곳에 작성을 해주는 것이 좋다. 

 


Validation

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.4.4</version>
</dependency>

 

  • @Size : 문자열의 최소, 최대 크기를 검증
    @Size(min=10, max=100) 과 같이 사용할 수 있으며, 기본값은 min=0, max=정수형의 최대값
  • @NotNull : 해당 필드에 null값을 불허한다.
  • @NotEmpty : 해당 필드에 null, ""을 불허한다.
  • @NotBlank : 해당 필드에 null, "", " " 을 불허한다. 즉 최소 1글자

 

DTO 에서는 Validation 어노테이션을 검색해서 필요한 유효성 검사 어노테이션을 달아주고, 

 

Entity에서는 Column 어노테이션 괄호 안에 필요한 제약 사항들을 입력해준다. 

 

 


BindingResult 

 @PostMapping("/auth/signup")
    public String signup(@Valid SignupDto signupDto, BindingResult bindingResult){

		// Error 가 있을 경우 Map에 담아 
        if(bindingResult.hasErrors()){
            Map<String, String> errorMap = new HashMap<>();
            // Error 를 리스트 형태로 리턴 
            for (FieldError error:bindingResult.getFieldErrors()){
                errorMap.put(error.getField(), error.getDefaultMessage());
            }
            throw new CustomValidationException("유효성 검사 실패함", errorMap);
        }else {
            log.info(signupDto.toString());

            User user = signupDto.toEntity();
            log.info(user.toString());

            User userEntity = authService.join(user);
            log.info(userEntity.toString());
            return "auth/signin"; // 회원가입 성공 시 로그인 페이지로 이동
        }


    }

 

 


Exception 처리 

@ControllerAdvice : Exception 이 발생하면 모두 낚아채도록 설정 

@RestController : Exception 이 발생하면 데이터를 리턴해야하므로 RestController 로 설정 

@ExceptionHandler(CustomValidationException.class) : CustomValidationException 이 발생할 때 모든 예외를 해당 메서드가 감지함. 

@RestController // 데이터를 리턴 -> 응답
@ControllerAdvice // 모든 예외를 낚아 챔.
public class ControllerExceptionHandler {
    @ExceptionHandler(CustomValidationException.class)    // RuntimeException 이 발생하는 모든 예외를 이 메서드가 가로챔.
    public String validationException(CustomValidationException e) {
        // CMRespDto, Script 비교
        // 1. 클라이언트에게 응답할 때는 Script 가 좋음
        // 2. AJax 통신 - CMRespDto
        // 4. Android 통신 - CMRespDto
        return Script.back(e.getErrorMap().toString());
    }
}

 

 

기존의 RuntimeExceprion 은 매개변수로 String 만 받을 수 있도록 되어있기 때문에 커스텀 예외를 만들어주는 것임! 

public RuntimeException(String message) {
       super(message);
}

 

 

public class CustomValidationException extends RuntimeException{
    // 객체를 구분할 때 사용
    private static final long serialVersionUID = 1L;

    private Map<String, String> errorMap;

    public CustomValidationException(String message, Map<String, String> errorMap) {
        super(message); // 부모 throwable 에 getMessage() 가 있음. 따라서 부모에게 보냄.
        this.errorMap = errorMap;
    }

    public Map<String, String> getErrorMap() {
        return errorMap;
    }
}