전처리와 후처리를 나누기 전 클라이언트에서 userName, Password 등 데이터를 입력해서 요청하면 서버와 DB를 걸친 뒤에 응답한다. 이런 경우, userName이나 Password에 설정한 길이 또는 userName의 동일 여부를 판단할 때 똑같이 전체의 과정으로 진행한다. 필요없는 메모리가 진행된다는 것이다. 

그래서 서버를 걸치지 않고, 전처리에서 해결하는 있는 것과 후처리 즉, 서버를 걸치고 난 후에 해결할 수 있는 것을 나누어 프로그래밍을 짠다면 더 효율적으로 할 수 있다.

 

전처리

- 전처리는 Validation인 유효성 검사로 서버를 건드리지 않고 앞에서 처리하는 것이다.

- 예를 들어, userName의 길이 제한이 20이라고 할 때, 사용자가 userName을 20 초과했다면 이건 서버를 걸치지 않고 프론트에서 처리할 수 있다. 즉, 전처리 단계에서 처리 가능

 

 

후처리

- 후처리는 Exception Handler로 꼭 서버에서 확인해야만 알 수 있는 것들 처리하는 것이다. 

- 예를 들어, userName의 동일 여부를 판단할 때에는 DB에서 저장된 userName 들을 확인해야 하기 때문이다.

 

 

AOP 관점지향 프로그래밍

[만약, userName이 20이상이면 회원강비은 진행할 필요 없기 때문에 분리해야 함]

- 관점 : 회원가입 -> 핵심 기능

- 공통 기능 : 전처리, 후처리(없어도 회원가입 되며, 있으면 깔끔해짐) 

-> 전처리, 후처리는 서비스 로직에 넣지 않고 따로 처리함. (이유 : 서비스 로직에 넣으면 복잡해지기 때문)

 

 

예를 들어, 설명

- 회원가입할 때, 프론트에서 지정한 제약 사항을 막을 수 있다. required = "required"라고 입력하면 된다.

<input type="email" name="email" placeholder="이메일" required="required" />

- 하지만, 웹상이 아닌 비정상적으로 회원가입할 경우, 포스트맨 같은 걸로 하게 되면 위와 같이 프론트에서만 설정해놓는다면 회원가입이 가능하게 된다. 

- 그렇게 때문에 백엔드에서도 막아야 한다.

- @NotBlank 사용. (null, 빈 문자열, 스페이스만 있는 건 불가능)

 

 

회원가입 

[SignupDto] = Dto : dataTransport로 통신하는 데이터라는 뜻

@Data
public class SignupDto{
	@Size(min = 2, max = 2)
    @NotBlank
    private String username;
    @NotBlank
    private String password;
    @NotBlank
    private String email;
    @NotBlank
    private String name;
    
    public User toEntity(){
    	return builder()
            .username(username)
            .password(password)
            .email(email)
            .name(name)
            .build();
    }
}

@Data : Getter, Setter

@NotBlank : null, 빈 문자열, 스페이스만 있는 거 불가능

 

Entity 클래스 : JPA에서 실제 데이터베이스의 테이블과 매칭되는 클래스

- Enity : server, db 접근 (DB 저장할 때 Dto -> Entity로 해줘야 하기 때문)

- Dto에서 Entity로 변환 : @Builder으로 toEntity() 설계 -> DB 등록

 

 

[AuthController] 

@RequiredArgsConstructor
@Controller
public class AuthController{
    private static final Logger log = LoggerFactory.getLogger(AuthController.class);
    
    private final AuthService authService;
    
    ....
    
    @PostMapping("auth/signup")
    public String signup(@Valid SignupDto signupDto, BindingResult bindingResult){
    	if(bindingResult.hasErrors()){ //Valid에서 선정한 max, notbink의 에러가 발생한다면
        	Map<String, String> errorMap = new HashMap<>();
            
            for(FieldError error : bindingResult.getFieldErrors()){
            	errorMap.put(error.getField(), error.getDefaultMessage());
           	}
            //사용자에게 보이면 좋은 UX가 아니기 때문에 Exception을 가로채는 Handler패키지 만듦
            throw new CustomValidationException("유효성검사 실패함", errorMap);
        }else{
            User user = signupDto.toEntity(); //User에 대한 데이터 넣음
            User userEntity = authService.회원가입(user);
            return "auth/singin"; //회원가입 성공 시 로그인 페이지로 이동
       	}
   }
}

@RequiredArgsConstructor //final 필드를 DI할 때 사용한다.

public AuthController(AuthService authService){

    this.authService = authService;

위와 같이 생성자를 만들어 불러와야 하는데, @RequiredArgsConstructor를 이용하면 final 필드를 이용해서 할 수 있다.

 

@Vaild 유효성 검사

-> 객체의 제약 조건을 검증하도록 지시하는 어노테이션 -> SingupDto에서 설정한 @Size과 @NotBlank의 유효성을 검사한다.

 

BindingResult는 스프링이 제공하는 검증오류를 보관하는 객체

FieldError는 필드에 오류가 있는 경우 발생하는 에

-BindingResult.getFieldErrors()를 통해 FieldError로 이루어진 List를 반환 받고, 각 원소를 돌면서 개발자가 작성한 FieldException 이라는 클래스의 각 필드에 매핑하는 작업을 수행.

 

[CustomerValidationException]

public class CustomValidationExcpetion extends RuntimeException{

	//객체 구분
    private static final long serialVersionUID = 1L;
    
    private Map<String, String> errorMap;
    
    public CustomValidationException(String message, Map<String, String> errorMap){
    	//Exception 라이브러리에서 message를 받아서 하고 있기 때문에 get함수를 만들 필요가 없어 부모한테 던짐
        super(message); 
        this.errorMap = errorMap;
    }
    
    public Map<String, String> getErrorMap(){
    	return errorMap;
    }

 

 

[ControllerExcpetionHandler]

@RestController //데이터 리턴
@ControllerAdvice //모든 Exception을 낚아챔
public class ControllerExceptionHandler{
    @ExceptionHandler(CustomValidationException.class) 
    public String validationException(CustomValidationException e){
    	return Script.back(e.getErrorMap().toString());
    }
}

@ControllerAdvice : @Controller와 handler에서 발생하는 에러들을 모두 잡아줌. @ControllerAdivce 안에서 @ExceptionHandler를 사용하여 에러를 잡아줌.

@ExceptionHandler : Controller 계층에서 발생하는 에러를 잡아서 메서드를 처리하는 기능

Script 클래스의 back메서드를 사용하여 에러메세지를 자바스크립트 타입으로 사용자에게 보여줌

'WEB > spring' 카테고리의 다른 글

JPA 연관관계 매핑 정리  (1) 2023.12.05
SecurityConfig 설정  (0) 2023.12.02
ResponseEntity 란?  (0) 2023.01.13
REST란?  (0) 2023.01.04
타일즈(Tiles)란?  (0) 2023.01.02

+ Recent posts