Burninghering's Blog
article thumbnail
Published 2022. 6. 1. 03:18
Validation Spring

위와 같은 코드에서는, 

인자가 3개밖에 없으니 코드가 짧지만

인자가 늘어나면 늘어날수록 코드(validation)가 길어지고 정상적인 로직을 짜는데 문제가 생길 수 있다. 

또 잘못 작성하면 에러가 난다.

 

Validation은 변경되면 안된다!

 

그리고 잘 처리하기 위해 스프링에서 일관되게 제공하기 위해

어노테이션으로 제공한다

 

변수에다가 붙이면 된다

 

요청을 받을 것이기 때문에

cotroller 패키지 만들고 ValidationApplication.java만듦

<java />
package com.example.validation.controller; import com.example.validation.dto.User; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/user") public Object user(@RequestBody User user){ System.out.println(user); return user; } }

 

dto의 User도 만듦

<code />
package com.example.validation.dto; public class User { private String name; private int age; private String email; private String phoneNumber; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", email='" + email + '\'' + ", phoneNumber='" + phoneNumber + '\'' + '}'; } }

 

email과 phoneNumber에 이상한 형식이 들어가도 정상적인 Response 200이 나온다..

 

ApiController의 내용을 바꿔보자

<code />
package com.example.validation.controller; import com.example.validation.dto.User; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/user") public ResponseEntity user(@RequestBody User user) { if (user.getAge() >= 90) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(user); } return ResponseEntity.ok(user); } }

100살 보내니까 에러가 난다!

 

하지만 방금처럼 코드를 짜면,

인자가 늘어날때마다 코드가 길어지니까 

Validation이 꼭 필요한 것이다.

 

User.java

<java />
import javax.validation.constraints.Email; public class User { private String name; private int age; @Email //<--어노테이션 붙여줌 private String email; private String phoneNumber;

 

User 내에 있는 변수에 Valid 어노테이션을 붙였으니,

아래 코드의 User에도 @Valid를 붙여줘야 한다. 

<java />
package com.example.validation.controller; import com.example.validation.dto.User; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/user") public ResponseEntity user(@Valid @RequestBody User user) { if (user.getAge() >= 90) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(user); } return ResponseEntity.ok(user); } }

@Valid가 붙은 객체는 그 안으로 들어가서 어노테이션(@Email)이 붙었는지 안 붙었는지 검사하기 때문

 

 

제대로 다시 보내면 성공!

 

 

 

핸드폰 번호에 대시(-)를 넣거나 안넣을 수도 있으니,

정규식을 활용해보자

<java />
"^\\d{2,3}-\\d{3,4}-\\d{4}$"

 

<code />
package com.example.validation.dto; import javax.validation.constraints.Email; import javax.validation.constraints.Pattern; public class User { private String name; private int age; @Email private String email; @Pattern(regexp="^\\d{2,3}-\\d{3,4}-\\d{4}$") private String phoneNumber;

검색을 통해 다양한 정규식으로 통제해보자!

 

 

 

지금처럼 body를 보내면 바로 error가 나는 것이 아니라,

Valid에 오류가 나면 bindingResult라는 곳으로 값을 보내줄 수 있다.

bindingResult라는 객체를 통해 새로운 변환값을 받을 수 있다.

bindingResult가 없다면 예외처리로 가능!(아직 안배움)

<java />
package com.example.validation.controller; import com.example.validation.dto.User; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/user") public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { StringBuilder sb = new StringBuilder(); bindingResult.getAllErrors().forEach(objectError -> { FieldError field = (FieldError) objectError; //형변환 String message = objectError.getDefaultMessage(); //오류 메시지도 가져오자 System.out.println("field : " + field.getField()); System.out.println(message); }); } return ResponseEntity.ok(user); } }

message의 양식을 바꿔보자

<code />
package com.example.validation.dto; import javax.validation.constraints.Email; import javax.validation.constraints.Pattern; public class User { private String name; private int age; @Email private String email; @Pattern(regexp="^\\d{2,3}-\\d{3,4}-\\d{4}$", message="핸드폰 번호의 양식과 맞지 않습니다. 01x-xxx(x)-xxxx") private String phoneNumber;

 

메세지를 바로 추가시키는 방법

<code />
package com.example.validation.controller; import com.example.validation.dto.User; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/user") public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { StringBuilder sb = new StringBuilder(); bindingResult.getAllErrors().forEach(objectError -> { FieldError field = (FieldError) objectError; //형변환 String message = objectError.getDefaultMessage(); //오류 메시지도 가져오자 System.out.println("field : " + field.getField()); System.out.println(message); sb.append("field : "+field.getField()); sb.append("message : "+message); }); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString()); } return ResponseEntity.ok(user); } }

 

이 API를 사용하는 사람이

응답만 보더라도 휴대폰 번호에 틀린 값을 잘못 넣었다는 것을 알 수 있다.

 

<code />
package com.example.validation.controller; import com.example.validation.dto.User; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/user") public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { StringBuilder sb = new StringBuilder(); bindingResult.getAllErrors().forEach(objectError -> { FieldError field = (FieldError) objectError; //형변환 String message = objectError.getDefaultMessage(); //오류 메시지도 가져오자 System.out.println("field : " + field.getField()); System.out.println(message); sb.append("field : "+field.getField()); sb.append("message : "+message); }); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString()); } //위에서 검증이 아주 잘 되었다면 //실질적으로 여기에 Logic을 짜면 된다 return ResponseEntity.ok(user); } }

 

여러가지 넣어봤다

<code />
package com.example.validation.dto; import javax.validation.constraints.*; public class User { @NotBlank private String name; @Max(value=90, message="valid 어노테이션에는 어느 곳에나 메세지를 넣을 수 있습니다") private int age;

 

컨트롤러 단에서 Validation을 사용하는 방법을 알아보았다!

변수 위에 annotation을 붙여주고, 

컨트롤러에서 객체를 검사하고 싶은 부분에는 @Valid를 붙여주면 된다~

profile

Burninghering's Blog

@개발자 김혜린

안녕하세요! 반갑습니다.