구성은 다음과 같다.
MemberController
@RestController
@RequestMapping("member")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@PostMapping("/signup")
public ResponseEntity signup(@Valid @RequestBody SignupRequestDto signupRequestDto) {
return memberService.signup(signupRequestDto);
}
}
SignupRequestDto
@Getter
@Setter
public class SignupRequestDto {
private String userId;
private String password;
}
Member
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String userId;
@Column(nullable = false)
private String password;
public Member(SignupRequestDto requestDto) {
this.userId = requestDto.getUserId();
this.password= requestDto.getPassword();
}
}
MemberRepository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
MemberService
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
/**
* 회원가입
*/
public ResponseEntity signup(SignupRequestDto requestDto) {
Member member = new Member(requestDto);
memberRepository.save(member);
return new ResponseEntity(member, HttpStatus.OK);
}
}
PostMan을 통해 확인해보자.
여기서 사용자가 입력한 아이디와 비밀번호의 유효성을 검증하고 싶다면 다음과 같이 작성할 수 있다.
MemberService
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
/**
* 회원가입
*/
public ResponseEntity signup(SignupRequestDto requestDto) {
String userId = requestDto.getUserId();
String password = requestDto.getPassword();
if (userId == null || password == null) {
throw new IllegalArgumentException("아이디 또는 비밀번호는 필수 입니다.");
}
if (userId.length() < 4 || userId.length() > 11 ) {
throw new IllegalArgumentException("아이디는 4~10자리로 입력해주세요.");
}
if (!(Pattern.matches("^[a-z0-9]{4,10}$", userId))){
throw new IllegalArgumentException("아이디는 4~10자리 영문 소문자와 숫자로 이루어져야 합니다.");
}
if (!Pattern.matches("^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,15}", password)){
throw new IllegalArgumentException("비밀번호는 8~15자리 영문 대소문자, 숫자, 특수문자로 이루어져야 합니다.");
}
Member member = new Member(requestDto);
memberRepository.save(member);
return new ResponseEntity(member, HttpStatus.OK);
}
}
다음과 같이 회원가입을 시도하면 에러가 발생하는 것을 볼 수 있다.
하지만 이런식으로 검증하게 되면, 로직이 길어질 수 밖에 없다.
스프링에서는 @Valid를 사용하여 클라이언트에서 넘어온 데이터를 객체와 바인딩할 때 유효성 검사를 할 수 있다.
728x90
@Valid
@Valid를 사용하기 위해 build.gradle에 다음을 추가해준다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
다음과 같이 SignupRequestDto에서 유효성 검사를 할 필드에 애노테이션을 추가해준다.
@Getter
@Setter
public class SignupRequestDto {
@NotBlank
@Size(min = 4, max = 10)
@Pattern(regexp = "^[a-z0-9]*$")
private String userId;
@NotBlank
@Size(min = 8, max = 15)
@Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,15}")
private String password;
}
그리고 MemberController에서 검증할 매개변수 앞에 @Valid를 붙여준다.
@RestController
@RequestMapping("member")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@PostMapping("/signup")
public ResponseEntity signup(@Valid @RequestBody SignupRequestDto signupRequestDto) {
return memberService.signup(signupRequestDto);
}
}
PostMan에서 비밀번호 형식이 올바르지 않은 데이터를 보내면 다음과 같은 에러가 발생한다.
Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.example.sample.controller.MemberController.signup(com.example.sample.dto.SignupRequestDto) with 2 errors: [Field error in object 'signupRequestDto' on field 'password': rejected value [1234]; codes [Size.signupRequestDto.password,Size.password,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signupRequestDto.password,password]; arguments []; default message [password],15,8]; default message [크기가 8에서 15 사이여야 합니다]] [Field error in object 'signupRequestDto' on field 'password': rejected value [1234]; codes [Pattern.signupRequestDto.password,Pattern.password,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signupRequestDto.password,password]; arguments []; default message [password],[Ljakarta.validation.constraints.Pattern$Flag;@13eaf9f9,(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\W)(?=\S+$).{8,15}]; default message ["(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\W)(?=\S+$).{8,15}"와 일치해야 합니다]] ]
@Valid 종류
@NotNull | Null이 아닌 값 |
@Null | Null인 값 |
@NotBlank | Null이 아닌 값, 공백이 아닌 문자 하나 이상 포함 |
@NotEmpty | Null이 아닌 값, 빈 문자열이 아닌 값 |
@Size(min = , max = ) | 문자열 길이가 min 이상 max 이하인 값 |
@Max(value = ) | max 이하의 값 |
@Min(value = ) | min 이하의 값 |
이메일 형식의 값 | |
@Positive | 양수인 값 |
@PositiveOrZero | 양수 또는 0인 값 |
@Negative | 음수인 값 |
@NegativeOrZero | 음수 또는 0인 값 |
@Future | 현재보다 미래의 날짜, 시간 |
@Past | 현재보다 과거의 날짜, 시간 |
@PastOrPresent | 현재 또는 과거의 날짜, 시간 |
@Pattern(regex = ) | 정규식 검증 |
@AssertTrue | true인 값 |
@AssertFalse | false인 값 |
@Degits(integer = , fraction = ) | 정수 자리수 integer 값 이하, 소수 자리수 fraction 값 이하 |
@DecimalMax(value = ) | value 이하의 값 |
@DecimalMin(value = ) | value 이상의 값 |
728x90