Spring Projcect/[팀플] In & Out 가계부

회원 유효성 검증

계란💕 2022. 11. 10. 00:47

 

  • ExceptionHandler 만들기
    • 서비스 로직을 들어가기 전에 회원이 정보가 유효하지 않을 때 예외를 터뜨린다.
    • methodArgumentNotValidHandlerCustomException() 
      • MethodArgumentNotValidException를 처리해주는 핸들러가 있어야한다.
      • 이를 만들어주지 않으면?
        • 에러의 메시지가 다음과 같이 제대로 안 나온다.
<hide/>
@Slf4j
@RestControllerAdvice
public class CustomExceptionHandler {

    @ExceptionHandler(MemberException.class)
    protected ResponseEntity<MemberErrorResponse> memberHandlerCustomException(
        MemberException e) {
        MemberErrorResponse errorResponse = MemberErrorResponse.builder()
            .errorCode(e.getErrorCode())
            .message(e.getErrorCode().getDescription())
            .build();

        log.error(errorResponse.getErrorCode().toString() + " / " + errorResponse.getMessage());

        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(ValidationException.class)
    protected ResponseEntity<ValidationErrorResponse> validationHandlerCustomException(
            ValidationException e) {
        ValidationErrorResponse errorResponse = ValidationErrorResponse.builder()
                .message(e.getMessage())
                .build();

        log.error(errorResponse.getMessage());

        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    protected ResponseEntity<ValidationErrorResponse> methodArgumentNotValidHandlerCustomException(
            MethodArgumentNotValidException e) {
        ValidationErrorResponse errorResponse = ValidationErrorResponse.builder()
                .message(e.getBindingResult().getAllErrors().get(0).getDefaultMessage())
                .build();

        log.error(errorResponse.getMessage());

        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }
}

 

  • MethodArgumentNotValidException  핸들러를 만들지 않은 경우의 에러 코드

 

 

 

  • input
    • 다른 input 클래스도 다음과 같이 설정한다.
    • @NotBlank는 "", " ", null 세 가지를 모두 허용하지 않는다.
    • @NotNull, @NotEmpty와는 다르다.
      • @NotNull: null 을 허용하지 않는다.
      • @NotEmpty: "", null을 허용하지 않는다. 
<hide/>
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class JoinMemberInput {

    @Email(message = "email을 정확하게 입력하세요.")
    private String email;

    @NotBlank (message = "비밀번호는 영문자, 숫자, 특수 기호를 한 글자 이상 넣으셔야합니다.")
    private String password;

    @NotBlank(message = "닉네임을 정확하게 입력하세요.")
    private String nickName;

    @NotBlank(message = "연락처를 정확하게 입력하세요.")
    private String phone;

    @PastOrPresent(message = "생년월일을 정확하게 입력하세요.")
    private LocalDate birth;

    @NotBlank(message = "주소를 정확하게 입력하세요")
    private String address;

    @NotBlank(message = "성별을 정확하게 입력하세요")
    private String gender;
}

 

 

  • 컨트롤러
    • 컨트롤러 클래스 위에 @Validated 를 붙인다.
    • @RequestBody, @RequestPart로 들어오는 매개변수의 앞에는 @Valid를 붙인다.
<hide/>
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
@Validated
public class MemberController {

    private final MemberService memberService;

    @PostMapping("/signup")
    @ApiOperation(value = "회원 가입 API", notes = "이메일을 아이디로 사용하여 가입할 수 있다.")
    public ResponseEntity<?> signUp(
        @ApiParam(value = "회원 가입 정보 입력") @RequestBody @Valid JoinMemberInput memberInput) {
        memberService.join(memberInput);
        String message = "이메일 인증을 하시면 회원가입이 완료됩니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @PostMapping("/signup/sending")
    @ApiOperation(value = "회원 가입을 위한 이메일 인증 API", notes = "이메일을 인증하여 회원 가입 가능하다.")
    public ResponseEntity<?> emailAuth(HttpServletRequest request) {
        String uuid = request.getParameter("id");
        memberService.emailAuth(uuid);
        String message = "회원가입이 완료되었습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @GetMapping("/member/info")
    @ApiOperation(value = "회원 정보 조회 API", notes = "회원이 자신의 정보를 조회한다.")
    public ResponseEntity<?> getInfo(Principal principal) {
        String email = principal.getName();
        MemberDto memberDto = memberService.getInfo(email);
        return new ResponseEntity<>(memberDto, HttpStatus.OK);
    }


    @PutMapping("/member/info")
    @ApiOperation(value = "회원 정보 수정 API", notes = "회원이 자신의 정보를 수정하거나 프로필 이미지 사진 등록 가능하다.")
    public ResponseEntity<?> updateInfo(Principal principal,
        @ApiParam(value =  "수정할 회원 정보 입력 또는 회원 프로필 이미지 등록")
        @RequestPart  @Valid  UpdateMemberInput input,
        MultipartFile file) {
        String email = principal.getName();
        memberService.updateInfo(email, input, file);
        String message = "회원 정보를 변경했습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @PatchMapping("/member/password")
    @ApiOperation(value = "회원 비밀번호 변경 API", notes = "기존 비밀번호를 확인하고나서 회원 비밀번호를 변경한다.")
    public ResponseEntity<?> updatePassword(Principal principal,
        @ApiParam(value = "기존 비밀번호, 새로운 비밀번호 입력") @RequestBody @Valid  ChangePasswordInput input) {
        String email = principal.getName();
        memberService.changePassword(email, input);
        String message = "비밀 번호가 변경되었습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @PostMapping("/signin")
    @ApiOperation(value = "회원 로그인 API", notes = "아이디(이메일)와 비밀번호를 입력해서 로그인한다.")
    public ResponseEntity<?> signin(
        @ApiParam(value = "로그인 정보 입력") @RequestBody @Valid  LoginMemberInput input) {
        memberService.login(input);
        String message = "정상적으로 로그인 완료했습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @PostMapping("/signout")
    @ApiOperation(value = "회원 로그아웃 API")
    public ResponseEntity<?> signout() {
        memberService.logout();
        String message = "정상적으로 로그아웃을 완료했습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @PostMapping("/password/email")
    @ApiOperation(value = "아이디(이메일) 찾기 API", notes = "아이디(이메일)를 입력해서 존재하는 회원인지 확인한다.")
    public ResponseEntity<?> checkEmail(
        @ApiParam(value = "아이디(이메일) 입력") @RequestBody @Valid  FindEmailMemberInput input) {
        memberService.validateEmail(input.getEmail());
        return new ResponseEntity<>(input.getEmail(), HttpStatus.OK);
    }


    @PostMapping("/password/email/phone")
    @ApiOperation(value = "비밀번호 찾기 API", notes = "연락처를 입력하여 비밀번호를 찾을 수 있도록 한다.")
    public ResponseEntity<?> checkPhone(
        @ApiParam(value = "연락처 입력") @RequestBody @Valid FindPasswordMemberInput findPasswordMemberInput) {
        memberService.validatePhone(findPasswordMemberInput.getEmail(),
            findPasswordMemberInput.getPhone());
        String message = "이메일로 비밀번호 초기화 링크를 전송했습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @PostMapping("/password/email/phone/sending")
    @ApiOperation(value = "비밀번호 초기화 API", notes = "이메일 인증을 완료하면 새롭게 비밀번호를 설정 가능하다.")
    public ResponseEntity<?> resetPassword(HttpServletRequest request,
        @ApiParam(value = "새로운 비밀번호를 입력") @RequestBody @Valid ResetPasswordInput input) {
        String uuid = request.getParameter("id");
        memberService.resetPassword(uuid, input);
        String message = "비밀번호 초기화가 완료됐습니다.";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


    @DeleteMapping("/member/info")
    @ApiOperation(value = "회원 탈퇴 API", notes = "비밀번호를 입력하여 회원 탈퇴할 수 있다.")
    public ResponseEntity<?> delete(
        @ApiParam(value = "비밀번호 입력") @RequestBody @Valid WithdrawMemberInput input, Principal principal) {
        String email = principal.getName();
        memberService.withdraw(email, input.getPassword());
        String message = "회원 탈퇴 완료";
        return new ResponseEntity<>(message, HttpStatus.OK);
    }


}

 

 

 

  • 실행 결과
    • 멤버변수의 @valid에 넣은 메세지가 출력된다.

 

 

 

'Spring Projcect > [팀플] In & Out 가계부' 카테고리의 다른 글

회원 수정 - 이미지 업로드 API  (0) 2022.11.01
회원 비밀번호 초기화 API  (0) 2022.10.31
회원 탈퇴 API  (0) 2022.10.30
회원 이메일 인증 API  (0) 2022.10.28
회원 가입 API  (0) 2022.10.27