개발 공부 기록
[SpringBoot] @Vaild를 통해 회원가입에 Validation 적용 본문
✔️ 회원가입 과정에서 Validation 적용?
보통 회원가입을 할 때 아이디를 입력하지 않으면 "아이디를 입력해주세요." 라던가, 혹은 비밀번호를 영어로만 입력한다면 "비밀번호는 영문, 숫자를 모두 포함해야 합니다."와 같은 문구가 뜹니다. 이처럼 요청한 데이터가 어떠한 조건에 충족하는지 확인하는 작업을 유효성 검사라고 하는데, 저는 이를 @Valid를 통해 서버에서 구현해보도록 하겠습니다.
✔️ @Valid란?
@Valid 주로 입력값의 유효성 검사를 위해 메서드나 클래스에 적용됩니다. 자바의 Bean Validation API를 기반으로 하며, 이를 통해 입력값의 형식, 범위, 필수 여부 등을 간단하게 확인할 수 있어 유효하지 않은 데이터가 들어오는 것을 방지할 수 있습니다.
📝 @Vaild 사용방법
유효성을 검사하고 싶은 객체를 만들고, 각 필드에 @Valid와 관련한 유효성 검사 어노테이션을 붙여줍니다. (참고로 유효성 검사 어노테이션 종류는 아래에서 설명합니다.)
@Data
public class Request {
@NotBlank(meassage = "아이디를 입력해주세요.")
private String username;
@NotBlank(message = "비밀번호는를 입력해주세요.")
@Pattern(message = "비밀번호는 8 ~ 16자의 영문, 숫자, 특수문자를 포함하도록 입력해주세요."
, regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,16}")
private String password;
...
}
이후 객체와 관련한 controller에서 객체를 검사한다는 의미의 @Valid를 붙여줍니다. 이제 클라이언트로부터 들어오는 데이터가 컨트롤러의 메소드 매개변수로 바인딩되고, 그 후에 데이터 유효성 검사가 이루어집니다. @Valid는 기본적으로 controller에서만 작동하며, 다른 계층에서 유효성 검사를 하려면 @Validated를 사용합니다.
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping("/signup")
public void signUp(@RequestBody @Valid Requset requset) {
userService.signUp(request);
}
}
📝 자주 사용되는 유효성 검사 어노테이션
- @NotNull: 필드가 null이 아닌지 확인합니다.
- @NotBlank: 문자열 필드가 null이 아니고, 빈 문자열이 아닌지 확인합니다.
- @NotEmpty: 컬렉션이나 배열이 null이 아니고, 비어 있지 않은지 확인합니다.
- @Size: 필드나 컬렉션의 크기를 제한합니다.
- @Min: 숫자 필드의 최소값을 설정합니다.
- @Max: 숫자 필드의 최대값을 설정합니다.
- @Email: 문자열 필드가 이메일 주소의 형식을 따르는지 확인합니다.
- @Pattern: 정규 표현식을 사용하여 필드의 형식을 지정합니다.
✔️ 회원가입에 Validation 적용
1. build.gradle에 validation 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-validation'
2. 유효성 검사가 필요한 객체 내의 필드에 유효성 검사 어노테이션 적용
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class SignupRequestDto {
@NotBlank(message = "닉네임을 입력해 주세요.")
@Pattern(regexp = "^[ㄱ-ㅎ가-힣a-z0-9-_]{2,10}$", message = "닉네임은 특수문자를 제외한 2글자 이상 10글자 이하여야 합니다.")
private String nickname;
@NotBlank(message = "이메일을 입력해 주세요.")
@Pattern(regexp = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$", message = "이메일 형식이 올바르지 않습니다.")
private String email;
@NotBlank(message = "비밀번호를 입력해 주세요.")
@Pattern(regexp = "^.*(?=^.{8,16}$)(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$", message = "비밀번호는 8 ~ 16자 영문, 숫자, 특수문자를 1개 이상 포함하여 입력해주세요.")
private String password;
}
3. Controller에 @Valid 적용
@PostMapping("/signup")
public ResponseEntity<BaseResponse<SignupResponseDto>> signUp(@Valid @RequestBody SignupRequestDto requestDto) {
SignupResponseDto responseDto = userService.save(requestDto);
return ResponseEntity.ok().body(BaseResponse.createSuccess(responseDto, BaseResponseStatus.SUCCESS));
}
4. ExceptionHandler에 에러를 처리하여 응답을 반환하는 메서드 작성
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<BaseResponse<Map<String, String>>> validationExceptionHandler(BindingResult bindingResult) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(BaseResponse.createError(bindingResult));
}
5. BaseResponse에 유효성을 통과하지 못하여 발생한 에러를 정재하여 반환하는 메서드 작성
public static BaseResponse<Map<String, String>> createError(BindingResult bindingResult) {
Map<String, String> errors = bindingResult.getFieldErrors().stream()
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
return new BaseResponse<>(false, "E2003", "입력값이 유효하지 않습니다.", errors);
}
✔️ Postman을 사용하여 테스트
'Spring > Development Log' 카테고리의 다른 글
[Spring] Session 기반과 JWT 기반의 인증 (0) | 2023.12.09 |
---|---|
[SpringBoot] 이메일 발송 기능 구현하여 이메일 인증 코드 발송하기 (1) | 2023.12.05 |
[Spring] Logback을 사용하여 에러 로깅하기 (1) | 2023.12.04 |
[SpringBoot] Spring Security를 통해 회원가입 구현 (0) | 2023.09.27 |
[Spring] Spring Security란? (0) | 2023.09.25 |