Project/Todo

[Refactoring] RequestBody Null or Empty 예외 처리

lakelight 2022. 7. 27. 10:49
728x90
반응형
포스트맨으로 테스트 중 아래와 같은 오류 발생
Request로 요청하던 데이터 중 null값으로 잘못보내서 500에러가 발생하였습니다.

2022-07-26 14:53:24.937 ERROR 32748 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: eq(null) is not allowed. Use isNull() instead; nested exception is java.lang.IllegalArgumentException: eq(null) is not allowed. Use isNull() instead] with root cause

java.lang.IllegalArgumentException: eq(null) is not allowed. Use isNull() instead

 

결론

만약 Request로 받은 데이터가 null이거나 비어있는 값(isEmpty)이라면
BadRequest Error 400번 오류를 반환하여 예외처리를 해주었습니다.

 

[MemberController.java]

package hooyn.todo.api.controller;

import hooyn.todo.api.request.member.*;
import hooyn.todo.api.response.Response;
import hooyn.todo.domain.Member;
import hooyn.todo.function.PrintDate;
import hooyn.todo.service.MemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import static com.querydsl.core.util.StringUtils.isNullOrEmpty;

@RestController
@RequiredArgsConstructor
@Slf4j
public class MemberController {
    private final MemberService memberService;
    private final PasswordEncoder passwordEncoder;

    private final PrintDate now = new PrintDate();

    /**
     * 회원가입
     */
    @PostMapping("/join")
    public Response join(@RequestBody JoinRequest request){
    
        //----------추가된 코드----------//
        String userID = request.getUserID();
        String userNM = request.getUserNM();
        String userPW = request.getUserPW();

        if(isNullOrEmpty(userID) || isNullOrEmpty(userNM) || isNullOrEmpty(userPW)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        boolean checkID = memberService.checkDuplicatedID(userID);
        if(checkID){
            boolean checkPW = memberService.checkPasswordConstraint(userPW);
            if(checkPW){
                String data = String.valueOf(memberService.join(userNM, userID, userPW));
                log.info(data + " 회원가입 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), data, "회원가입이 정상적으로 처리되었습니다.");
            } else {
                // 302 에러
                log.error("비밀번호 제약조건 Error Code:302 " + now.getDate());
                return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호는 영문과 숫자포함 8-20자리입니다.");
            }
        } else {
            // 301 에러
            log.error("아이디 중복 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "이미 사용중인 아이디 입니다.");
        }
    }

    /**
     * 로그인
     */
    @PostMapping("/login")
    public Response login(@RequestBody LoginRequest request){
    
        //----------추가된 코드----------//
        String userID = request.getUserID();
        String userPW = request.getUserPW();

        if(isNullOrEmpty(userID) || isNullOrEmpty(userPW)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUserID(userID);
        if(member!=null){
            if(member.matchPassword(passwordEncoder, userPW)){
                log.info(member.getUuid() + " 로그인 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), member.getUuid(), "로그인 되었습니다.");
            } else {
                // 302 에러
                log.error("비밀번호 불일치 Error Code:302 " + now.getDate());
                return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호가 일치하지 않습니다.");
            }
        } else {
            // 301 에러
            log.error("아이디 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 아이디입니다.");
        }
    }

    /**
     * 비밀번호 제약조건 확인
     */
    @PostMapping("/password/constraint")
    public Response checkPasswordConstraint(@RequestBody CheckPasswordConstraintRequest request){
        
        //----------추가된 코드----------//
        String password = request.getPassword();

        if(isNullOrEmpty(password)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        boolean checkPW = memberService.checkPasswordConstraint(password);

        if(checkPW){
            log.info("비밀번호 제약조건 Success Code:200 " + now.getDate());
            return new Response(true, HttpStatus.OK.value(), null, "비밀번호를 사용 가능합니다.");
        } else {
            // 302 에러
            log.error("비밀번호 제약조건 Error Code:302 " + now.getDate());
            return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호는 영문과 숫자포함 8-20자리입니다.");
        }
    }

    /**
     * 2차 비밀번호 확인
     */
    @PostMapping("/password/same")
    public Response checkPasswordSame(@RequestBody CheckPasswordSameRequest request){
        String password = request.getPassword();
        String password_ = request.getPassword_();

        if(isNullOrEmpty(password) || isNullOrEmpty(password_)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }

        if(password.equals(password_)){
            log.info("2차 비밀번호 일치 Success Code:200 " + now.getDate());
            return new Response(true, HttpStatus.OK.value(), null, "2차 비밀번호가 일치합니다.");
        } else {
            // 302 에러
            log.error("2차 비밀번호 불일치 Error Code:302 " + now.getDate());
            return new Response(false, HttpStatus.FOUND.value(), null, "2차 비밀번호가 일치하지 않습니다.");
        }
    }

    /**
     * 비밀번호 변경을 위한 기존 비밀번호 확인
     */
    @PostMapping("/password/origin")
    public Response checkPasswordOrigin(@RequestBody ChangePasswordRequest request){
        
        //----------추가된 코드----------//
        String password = request.getPassword();
        String uuid = request.getUuid();

        if(isNullOrEmpty(password) || isNullOrEmpty(uuid)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUUID(uuid);
        if(member!=null){
            if(member.matchPassword(passwordEncoder, password)){
                log.info("회원 인증 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), member.getUuid(), "회원 인증이 되었습니다.");
            } else {
                // 302 에러
                log.error("비밀번호 불일치 Error Code:302 " + now.getDate());
                return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호가 일치하지 않습니다.");
            }
        } else {
            // 301 에러
            log.error("회원 정보 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
        }
    }

    /**
     * 비밀번호 변경
     */
    @PutMapping("/password")
    public Response changePassword(@RequestBody ChangePasswordRequest request){
        
        //----------추가된 코드----------//
        String password = request.getPassword();
        String req_uuid = request.getUuid();

        if(isNullOrEmpty(password) || isNullOrEmpty(req_uuid)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        boolean checkPW = memberService.checkPasswordConstraint(password);
        if(checkPW){
            String uuid = String.valueOf(memberService.changePassword(req_uuid, password));
            //UUID로 받으면 UUID는 null이 될 수 없기 때문에 500에러가 나옵니다. 조심조심!

            if(!uuid.equals("null")){
                log.info("비밀번호 변경 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), uuid, "비밀번호가 변경되었습니다.");
            } else {
                // 301 에러
                log.error("회원 정보 Error Code:301 " + now.getDate());
                return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
            }
        } else {
            // 302 에러
            log.error("비밀번호 제약조건 Error Code:302 " + now.getDate());
            return new Response(false, HttpStatus.FOUND.value(), null, "비밀번호는 영문과 숫자포함 8-20자리입니다.");
        }
    }

    /**
     * 아이디 중복 확인
     */
    @PostMapping("/duplicate/id")
    public Response checkDuplicateId(@RequestBody CheckDuplicateIdRequest request){
    	
        //----------추가된 코드----------//
        String id = request.getId();

        if(isNullOrEmpty(id)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//
        
        boolean check = memberService.checkDuplicatedID(id);

        if(check){
            log.info("아이디 중복 Success Code:200 " + now.getDate());
            return new Response(true, HttpStatus.OK.value(), request.getId(), "사용가능한 아이디 입니다.");
        } else {
            // 301 에러
            log.error("아이디 중복 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "이미 사용중인 아이디 입니다.");
        }
    }
}

 

[TodoController.java]

package hooyn.todo.api.controller;

import hooyn.todo.api.request.todo.*;
import hooyn.todo.api.response.Response;
import hooyn.todo.domain.Deadline;
import hooyn.todo.domain.Member;
import hooyn.todo.domain.Todo;
import hooyn.todo.dto.FindTodoDto;
import hooyn.todo.function.PrintDate;
import hooyn.todo.service.MemberService;
import hooyn.todo.service.TodoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static com.querydsl.core.util.StringUtils.isNullOrEmpty;

@RestController
@RequiredArgsConstructor
@Slf4j
public class TodoController {

    private final TodoService todoService;
    private final MemberService memberService;
    private final PrintDate now = new PrintDate();

    /**
     * 투두 작성
     */
    @PostMapping("/todo")
    public Response writeTodo(@RequestBody WriteTodoRequest request){
        
        //----------추가된 코드----------//
        String uuid = request.getUuid();
        String title = request.getTitle();
        String content = request.getContent();
        Deadline deadline = request.getDeadline();

        if(isNullOrEmpty(uuid) || isNullOrEmpty(title) || isNullOrEmpty(content) || isNullOrEmpty(deadline.getDate())){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUUID(uuid);

        if(member!=null){
            Todo todo = Todo.createTodo(title, content, deadline, member);
            Long todo_id = todoService.writeTodo(todo);

            log.info("투두 작성 Success Code:200 " + now.getDate());
            return new Response(true, HttpStatus.OK.value(), todo_id, "작성이 완료되었습니다.");
        } else {
            // 301 에러
            log.error("아이디 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
        }
    }

    /**
     * 기한에 따른 투두 조회
     */
    @PostMapping("/todo/deadline")
    public Response findTodoByDeadline(@RequestBody FindTodoRequest request, @RequestParam Integer page){
        
        //----------추가된 코드----------//
        String uuid = request.getUuid();
        Deadline deadline = request.getDeadline();

        if(isNullOrEmpty(uuid) || isNullOrEmpty(deadline.getDate())){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUUID(uuid);

        if(member!=null){
            List<FindTodoDto> data = todoService.findTodoByDeadline(uuid, deadline, page);

            log.info("투두 조회 Success Code:200 " + now.getDate());
            return new Response(true, HttpStatus.OK.value(), data, "투두 데이터가 조회되었습니다.");
        } else {
            // 301 에러
            log.error("아이디 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
        }
    }

    /**
     * 키워드에 따른 투두 조회
     */
    @PostMapping("/todo/content")
    public Response findTodoByContent(@RequestBody FindTodoRequest request, @RequestParam Integer page){
        
        //----------추가된 코드----------//
        String uuid = request.getUuid();
        String content = request.getContent();

        if(isNullOrEmpty(uuid) || isNullOrEmpty(content)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUUID(request.getUuid());

        if(member!=null){
            List<FindTodoDto> data = todoService.findTodoByContent(request.getUuid(), request.getContent(), page);

            log.info("투두 조회 Success Code:200 " + now.getDate());
            return new Response(true, HttpStatus.OK.value(), data, "투두 데이터가 조회되었습니다.");
        } else {
            // 301 에러
            log.error("아이디 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
        }
    }

    /**
     * 투두 수정
     */
    @PutMapping("/todo")
    public Response updateTodo(@RequestBody UpdateTodoRequest request){
        
        //----------추가된 코드----------//
        Long req_todo_id = request.getTodo_id();
        String uuid = request.getUuid();
        String title = request.getTitle();
        String content = request.getContent();
        Deadline deadline = request.getDeadline();

        if(req_todo_id==null || isNullOrEmpty(uuid) || isNullOrEmpty(title) || isNullOrEmpty(content) ||isNullOrEmpty(deadline.getDate())){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Todo todo = todoService.findTodoById(req_todo_id);

        if(todo!=null){

            if(todoService.checkAuthorization(uuid, req_todo_id)){
                Long todo_id = todoService.updateTodo(req_todo_id, title, content, deadline);

                log.info("투두 업데이트 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), todo_id, "업데이트가 완료되었습니다.");
            } else {
                // 302 에러
                log.error("수정 권한 없음 Error Code:302 " + now.getDate());
                return new Response(false, HttpStatus.FOUND.value(), null, "수정 권한이 없습니다.");
            }

        } else {
            // 301 에러
            log.error("투두 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 투두입니다.");
        }
    }


    /**
     * 투두 삭제
     */
    @DeleteMapping("/todo")
    public Response deleteTodo(@RequestBody DeleteTodoRequest request){
        
        //----------추가된 코드----------//
        Long req_todo_id = request.getTodo_id();
        String uuid = request.getUuid();

        if(req_todo_id==null || isNullOrEmpty(uuid)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUUID(request.getUuid());

        if(member!=null){

            if(todoService.checkAuthorization(request.getUuid(), request.getTodo_id())){
                Long todo_id = todoService.deleteTodo(request.getTodo_id());

                log.info("투두 삭제 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), todo_id, "삭제가 완료되었습니다.");
            } else {
                // 302 에러
                log.error("삭제 권한 없음 Error Code:302 " + now.getDate());
                return new Response(false, HttpStatus.FOUND.value(), null, "삭제 권한이 없습니다.");
            }

        } else {
            // 301 에러
            log.error("아이디 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
        }
    }

    /**
     * 투두 상태 변경
     */
    @PutMapping("/todo/status")
    public Response updateTodoStatus(@RequestBody UpdateTodoStatusRequest request){
        
        //----------추가된 코드----------//
        Long req_todo_id = request.getTodo_id();
        String uuid = request.getUuid();

        if(req_todo_id==null || isNullOrEmpty(uuid)){
            log.error("필수 입력값 없음 Error Code:400 " + now.getDate());
            return new Response(false, HttpStatus.BAD_REQUEST.value(), null, "필수 입력값을 입력해주세요.");
        }
        //----------추가된 코드----------//

        Member member = memberService.findUserByUUID(request.getUuid());

        if(member!=null){
            Todo todo = todoService.findTodoById(request.getTodo_id());
            if(todo!=null){
                Long todo_id = todoService.updateTodoStatus(request.getTodo_id());

                log.info("투두 상태 변경 Success Code:200 " + now.getDate());
                return new Response(true, HttpStatus.OK.value(), todo_id, "투두 상태가 변경되었습니다.");
            } else {
                // 302 에러
                log.error("투두 없음 Error Code:302 " + now.getDate());
                return new Response(false, HttpStatus.FOUND.value(), null, "등록되지 않은 투두입니다.");
            }

        } else {
            // 301 에러
            log.error("아이디 없음 Error Code:301 " + now.getDate());
            return new Response(false, HttpStatus.MOVED_PERMANENTLY.value(), null, "등록되지 않은 회원입니다.");
        }
    }
}

 

팀프로젝트 : Todo Code Github

 

GitHub - hooyn/Todo: [팀프로젝트] Todo App 서버 API

[팀프로젝트] Todo App 서버 API. Contribute to hooyn/Todo development by creating an account on GitHub.

github.com

 

728x90
반응형