프론트에서만 유효성 검사를 했었는데,
언제든지 우회할 수 있다고 듣고, 서버쪽에서도 유효성 검사하는 로직을 추가하려했다.
근데 스프링에서는 validation이라는 프레임워크로 편하게 할 수 있었다.
그 과정을 남기려고 한다.
- 라이브러리 설치(build.gradle)
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation', version: '2.5.2'
- 먼저 회원가입을 한다고 하면 User 엔티티가 필요하다.
@Entity
@Getter
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
@Enumerated(EnumType.STRING)
@Column
private Role role;
@Builder
public User(Long id, String name, String email) {
this.name = name;
this.email = email;
}
}
- 화면에서 받을 DTO를 만들어줬다.
@NoArgsConstructor
@Getter
public class UserRequestDto {
@NotBlank(message = "이름은 필수 입력값입니다.")
private String name;
@NotBlank(message = "이메일은 필수 입력값입니다.")
@Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$", message = "이메일 형식에 맞지 않습니다.")
private String email;
public User toEntity(){
return User.builder()
.name(name)
.email(email)
.build();
}
}
- 여기에서 @NotBlank가 유효성 검사를 해주는 어노테이션이다.
- 종류는 매우 많다.
어노테이션 | 특징 | 특이사항 |
@Size | 문자 길이 측정 | Int Type 불가 |
@NotNull | Null 불가 | |
@NotEmpty | Null 불가, "" 불가 | |
@NotBlank | Null 불가, "" 불가," " 불가 | |
@Past | 과거날짜만 | |
@PastOnPresent | 오늘이거나 과거 날짜 | |
@Future | 미래 날짜 | |
@FutureOnPresent | 오늘이거나 미래날짜 | |
@Pattern | 정규식 적용 | |
@Max | 최대값 | |
@Min | 최솟값 | |
이메일 형식으로 | ||
@AssertTrue/False | 별도 Logic 적용 | |
@Valid | 해당 Object Validation 실행 |
- 컨트롤러는 이렇게 작성했다.
@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
UserService userService;
@GetMapping("/login")
public String login(@RequestBody Map<String, String> data) {
System.out.println("data = " + data);
return "login";
}
@PostMapping("/join")
public Long join(@RequestBody @Valid UserRequestDto userRequestDto, Errors erros) {
System.out.println("userRequestDto = " + userRequestDto.getEmail());
if (erros.hasErrors()) {
System.out.println(" 에러 ");
return 0L;
}
return userService.save(userRequestDto);
}
@GetMapping("/users")
public List<UserResponseDto> findAll() {
return userService.findAll();
}
}
- 받으려는 DTO앞에 @Valid 또는 @Validation을 붙여준다.
- @Valid, @Validated 차이
1. @Valid는 Java에서 지원해주는 어노테이션이고, @Validated는 스프링에서 지원해준는 어노테이션이다.
2. @Validated는 @Valid의 기능을 포함하기 때문에 @Valid를 적용한 곳이면 @Validated로 변경할 수 있다.
3. @Validated는 유효성을 검토할 그룹을 지정할 수 있는 기능을 추가로 가지고 있다.
이러한 특징을 갖고 있다.
- Error는반드시 Request 객체 바로 뒤에 위치해야한다.
- 두 개의 객체에 validation 검사를 한다면, 각각의 객체 뒤에 errors를 받는다.
- 유효성 검사를 통과하지 못할 경우 0을 리턴해줬다.
- 지난번에 사용했던 Swagger UI로 테스트해봤다.
https://devhooney.tistory.com/93
- 이렇게 보내면
- 에러가 뜬다.
- 나는 에러라는 문자를 그대로 찍었지만, Errors 객체에 메시지들이 들어있다.
s = Field error in object 'userRequestDto' on field 'email': rejected value [];
codes [Pattern.userRequestDto.email,Pattern.email,Pattern.java.lang.String,Pattern];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [userRequestDto.email,email];
arguments [];
default message [email],
[Ljavax.validation.constraints.Pattern$Flag;@332a8d87,
^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,6}$];
default message [이메일 형식에 맞지 않습니다.]
s = Field error in object 'userRequestDto' on field 'name': rejected value [];
codes [NotBlank.userRequestDto.name,NotBlank.name,NotBlank.java.lang.String,NotBlank];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [userRequestDto.name,name];
arguments [];
default message [name]];
default message [이름은 필수 입력값입니다.]
s = Field error in object 'userRequestDto' on field 'email': rejected value [];
codes [NotBlank.userRequestDto.email,NotBlank.email,NotBlank.java.lang.String,NotBlank];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [userRequestDto.email,email];
arguments [];
default message [email]];
default message [이메일은 필수 입력값입니다.]
- Body에는
- 0이 담겨있다.
- 유효성검사를 통과할 경우 해당 id가 리턴된다.
- 제대로 넣으면 쿼리가 나가고, 리턴이 잘된다.
- 현재 회사에 개발되어 있는 모든 코드를 손봐야겠다.
참고 사이트
'개발 > Java&Kotlin' 카테고리의 다른 글
[Java] 예외처리 (0) | 2022.08.23 |
---|---|
[Spring] Message 적용해보기 (0) | 2022.08.21 |
[Spring] 스웨거(Swagger) 라이브러리 (1) | 2022.08.17 |
[Java] Generics (1) | 2022.08.17 |
[Java] 컬렉션 프레임워크 (2) (0) | 2022.08.16 |