메모장

Spring boot 유효성 검사 (1) 본문

Spring/개념정리

Spring boot 유효성 검사 (1)

Itchild 2024. 8. 7. 13:59
728x90
반응형

 

유효성 검사는 크게 두가지 파트

 

1) 클라이언트(==웹 브라우져 , 프론트 )

- html , jsp 페이지에서 주로 js 를 통해 사용자의 입력값을 검사

버튼을 눌러서 서버로 가는 순간 네트워크라는 것을 쓰는데

- 네트워크 (트래픽) 낭비를 방지 한다

네트워크를 덜 쓰니까 서버의 부하가 적어짐

- 비용적 절감은 1번 (클라이언트 쪽) 이 중요하고 -

 

2) 서버(== 백, 개발자)

- URL 을 막을수 없다. 클라이언트에선

- 잘못된 URL 호출에 대해 유효성 검사가 필요하다 .

반드시 필요한 부분 !

 

-1 번으로 필연적으로 못막는 부분은 여기서 -

 

 

Q . 사용자의 "악의적인 접근" 을 어떻게 막을까요 ?

== 잘못된 URL 호출을 어떻게 막을까요 ?

A . JS 로 막는 것은 한계가 있기 때문에 JAVA로 유효성 검사를 해야합니다.

 

 


실습

 

JSP 파일 예제 코드 - form 태그에 id, password 값을 넘겨준다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ko">
   <head>
      <meta charset = "UTF-8">
      <title> 예제 </title>
   </head>
   <body>
        <form action="test" method="POST"> // .do 는 생략한다. 
		ID <input type="text" name="id" value="${apple}">
		PW <input type="password" name ="password">
		<input type="submit" value="전송">
	</form>
	

   </body>
</html>
 

 

이 view 코드를 보고 컨트롤러가 결정해야 하는 것 !

  1. 커맨드 객체 - 멤버변수는 "id" 와 "password" 이다. 컨트롤러는 name 을 보고 판단을 한다.
  2. view 쪽으로 값을 다시 돌려 줄때 (model .add 수행시) - id 값 이름이 "apple" 이어야 한다.
  3. 해당 요청의 값이 test (POST 방식 이어야 한다)

 

컨트롤러가 view 코드 만을 보고 생각 해야 하는 것 들 이다.

 

 


 

이제 컨트롤러로 넘어가서

< 지금까지 해오던 유효성 검사 >

@RequestMapping("/test")
	public String root(VO vo, Model model) {
	///// 유효성 
	if(vo.getId() == null || vo.getId().equals("") || vo.getId().isEmpty() || vo.getId().isBlank()) {
				
	}
	if(vo.getPw().length() <= 5) {
				
	}
	/////

		
		
		model.addAttribute("apple", vo.getId());
		return "test";
	}
	
 

지금까지 해오던 유효성 검사는 컨트롤러 로직 안에 직접 작성하거나 , 모듈화를 하여 상단에 배치 하는 정도였다.

 

 

근데 !

이것을 부트에서 지원 해준다.

기본적인 유효성 검사 (null , 길이 ,,,)는 흔해서 부트에서 지원해줌 !

 

 

이제 우리는 부트가 해주는 모듈화를 배울 예정 이다 !!

 

 

< VO 객체 >
@Data // Lombok 덕분에 가능하다.
public class VO {
	private String id;
	private String password;
}
 

 

우리는 유효성을 검사할 객체의 클래스 정보를 반환 하기 위해 유효성 검사 클래스를 하나 만든다.

package com.hong.app;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class VOValidator implements Validator {

	@Override
	public boolean supports(Class<?> clazz) {// 유효성 검사할 객체의 클래스 정보를 반환 
		return VO.class.isAssignableFrom(clazz); 
// 어떤 클래스 객체의 데이터를 볼수 있구나 정도만 잘 안씀 // 뭐에 대해서 할것인지 알려주면 됨 
	}

	@Override       		 
	public void validate(Object target, Errors errors) { 

		VO vo = (VO)target;
		String id= vo.getId();

        if(id.length()<=5) {
			System.out.println("아이디가 5글자 이하 일수 없습니다. ");
			errors.rejectValue("id", "5글자 이하로는 할 수 없습니다. "); // 에러라고 보내줘야 된다. 	
		}
	
		ValidationUtils.rejectIfEmptyOrWhitespace(errors,"id", "id값 없음"); // 공백이거나 null 이거나 하면 구분해준다는 메서드 // empty 까지만 쓰면 null 만 구분 
		
		if(id == null || id.isEmpty() || id.isBlank() || id.trim().isEmpty() || id.trim().isBlank()) { // 남은 부분을 잘라서 trim  비었니도 검사 
	         System.out.println("로그 : id값이 올바르지 않습니다. ");
	         errors.rejectValue("id", "id값 없음");
	      }
		String password = vo.getPassword(); // 단일 변수화 시키는경우도 많이 있다. 
		if(password == null || password.isEmpty() || password.isBlank() || password.trim().isEmpty() || password.trim().isBlank()) { // 남은 부분을 잘라서 trim  비었니도 검사 
	         System.out.println("로그 : password값이 올바르지 않습니다. ");
	         errors.rejectValue("password", "password값 없음");
	      }
		
	} // 부트에서 유효성 검사를 모듈화 한 클래스가 있는데 걔 이름이 VOValiidator 이다. 
// 이렇게 해야해 라고 강제 해야해 
}
 

에러(errors) 라는 친구도 커맨드 객체라 "참조 변수" 이다. 변화를 기억할 수 있는 객체

내부 메서드에서 add 되는결과값들을 기억해준다는 뜻

 

// target : 유효성 검사 할 객체를 의미 // 타겟에 vo 가 넘어옴

// errors : 검증이 통과되지 못한 경우 , 왜 통과가 안 되었는 지를 반환 이유를 반환 해주는 객체

 

errors 라는 인자는 진짜 외부에서 들어오는 값이 아님 ! , 반환을 위해 만들어짐 에러가 한두개 나는게 아니기

때문에 많은 에러를 한번에 반환할 목적으로 보내주는 방법

 

new 를 코드에다 때려박는게 유지보수에 불리하기 때문에

검사 클래스 에서는 유효성을 한 값을 보내진 않는다. 반환을 위해 거기서 new를 하는게 아니라

커맨드 객체 == 참조변수 == BindingResult 라는 객체 라는걸 참조해서 쓴다는게 중요!

(저런 단어를 외우는게 아님)

 

< 원래 로직 >
if(id == null || id.isEmpty() || id.isBlank() || id.trim().isEmpty() || id.trim().isBlank()) { // 남은 부분을 잘라서 trim 비었니도 검사

System.out.println("로그 : id값이 올바르지 않습니다. ");

errors.rejectValue("id", "id값 없음");

}

< 더 줄이기 >
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"id", "id값 없음"); 
==> 이렇게 간단하게 줄일 수 있다. 

 
package com.hong.app;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;

import jakarta.validation.Valid;

@Controller
public class CTRL {

	@RequestMapping("/")
	public String root() {
		return "test";
	}
	
	@RequestMapping("/test") // method요청 써도됨  
	public String root(VO vo, BindingResult br, Model model) { 
// 커맨드 객체 , Model model , 에러친구 커맨드 객체로 받아올 수 있게 
	
		VOValidator voV = new VOValidator(); 
		
		voV.validate(vo, br); // 검사를 했을때 검사 할게 여러가지 일 수 있는데 자바에서 그게 안되기 때문에 따로 객체를 사용할 수 있다. br 는 커맨드 객체(참조변수)를 참조하고 있다. 
		// validate 메서드 강제에 의해 만들어진 메서드

		if(br.hasErrors()) {
			System.out.println("로그 : 에러 발생함!");
		}
		
		model.addAttribute("apple", vo.getId());
		return "test";
	}

	
}
 

콘솔에 찍히는 모습 !

 

728x90
반응형