유효성 검사와 예외 처리

JeongMin·2023년 5월 18일
0

✍‘익명 게시판’의 기능 추가 (유효성 검사, 예외 처리)


📄 요구 사항

✔ 1. 게시글 작성 기능

  • 게시글 제목, 내용은 필수적으로 포함해야 한다.
  • 제목은 1글자 이상 15글자 이하여야 한다.
  • 내용은 1글자 이상 1000글자 이하여야 한다.
  • 제목은 공백으로만 이루어질 수는 없다.

Title

@Getter
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Title {

    private final static int TITLE_MAX_LENGTH = 15;

    @Column(name = "title", nullable = false)
    private String value;

    public Title(String value) {
        validate(value);
        this.value = value;
    }

    private void validate(String value) {
        if (value == null || value.isBlank()) {
            throw new InvalidTitleException();
        }
        if (value.length() > TITLE_MAX_LENGTH) {
            throw new InvalidTitleException();
        }
    }

}

Content

@Getter
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Content {

    private final static int CONTENT_MAX_LENGTH = 1000;

    @Column(name = "content", nullable = false)
    @Lob
    private String value;

    public Content(String value) {
        validate(value);
        this.value = value;
    }

    private void validate(String value) {
        if (value == null) {
            throw new InvalidContentException();
        }
        if (value.length() > CONTENT_MAX_LENGTH) {
            throw new InvalidContentException();
        }
    }

}
  • 제목, 내용 별로 세부 속성을 다루기 위해 값 타입을 사용했습니다.
  • @Embeddable 애노테이션을 사용해 해당 클래스가 다른 엔티티 클래스의 일부인 컴포지트 객체임을 알려준다.
  • 또한, 요구 사항에 맞는 검증 메서드를 추가한다. 검증 메서드를 통해서 해당 검증에 대한 예외를 던져, 오류 메시지가 클라이언트에게 전달될 수 있도록 한다.

BadRequestException

@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class BadRequestException extends RuntimeException{

    public BadRequestException(String message) {
        super(message);
    }
}
  • RuntimeException 생성자를 호출해 예외 메시지를 설정한다. 예외 객체가 생성 될 때 해당 메시지가 나오게 됩니다.

InvalidContentException

public class InvalidContentException extends BadRequestException {

    private static final String MESSAGE = "내용은 1글자 이상 1000글자 이하여야 합니다.";

    public InvalidContentException() {
        super(MESSAGE);
    }
}

InvalidTitleException

public class InvalidTitleException extends BadRequestException {

    private static final String MESSAGE = "제목은 1자 이상 15자 이하여야 합니다.";

    public InvalidTitleException() {
        super(MESSAGE);
    }
}

PostNotFoundException

public class PostNotFoundException extends BadRequestException {

    private final static String MESSAGE = "존재하지 않는 게시글 입니다.";

    public PostNotFoundException() {
        super(MESSAGE);
    }
}
  • super를 통해 상위 클래스인 BadRequestException의 생성자를 호출하고 MESSAGE 변수를 인자로 전달한다. 해당 예외 객체가 생성되면 예외에 맞는 메시지가 나오게 된다.

PostExControllerAdvice

@RestControllerAdvice
public class PostExControllerAdvice {

    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<ErrorResult> badRequestExHandle(BadRequestException e) {
        return ResponseEntity.badRequest().body(new ErrorResult(e.getMessage(), "400"));
    }
}
  • 예외에 대한 응답을 처리하는 RestControllerAdvice 생성한다. 이 클래스를 통해 BadRequestException 에 담긴 오류 메시지로 응답할 수 있다.

PostRequest

@Getter
public class PostRequest {

    @NotBlank(message = "제목은 1자이상 15자 이하여야 합니다.")
    private String title;

    @NotBlank(message = "내용은 1자이상 1000자 이하여야 합니다.")
    private String content;

    private String error_message;

    private LocalDateTime regTime;

}
  • 게시글을 작성할 때, 제목과 게시글은 필수로 작성해야 하기 때문에, 요청 Dto에서 @NotBlank 애노테이션을 통해 검증한다.

결과



  • 요청 사항에 대한 예외 처리, 유효성 검사를 통해 오류 메시지로 전달한 것을 볼 수 있다.

✔ 2. 게시글 작성 기능

  • 게시글의 id(PK, primary key)로 특정 게시글을 조회했을 때, 존재하지 않는 게시글일 경우 에러 메시지로 응답하기

PostService

public class PostService{
	
    ...
    public PostResponse findPost(Long id){
        Post post = getFindByIdPost(id);

        return new PostResponse(post);
    }
    ...
    
     private Post getFindByIdPost(Long id) {
        return postrepository.findById(id)
                .orElseThrow(() -> new PostNotFoundException());
    }

}
  • 특정 게시글 id로 조회를 했을 때 PostNotFoundException() 객체를 생성하여 오류에 대한 메시지를 남기고 예외를 던진다.

결과


✔ 3. 특정 게시글 수정 기능

  • 게시글 작성할 때의 유효성 검사 조건과 동일하게 가져가야 한다.

요구 사항 1번과 동일


✔ 4. 특정 게시글 수정 기능

  • 게시글의 id(PK, primary key)로 특정 게시글을 삭제하기 위해 조회했을 때, 존재하지 않는 게시글일 경우 에러 메시지로 응답하기

요구 사항 2번과 동일


✔ 5. 게시글 검색 기능

  • 검색 키워드는 공백을 제외한 1글자 이상이어야 한다.

Keyword

@Getter
public class Keyword {

    private final String value;

    public Keyword(String value) {
        this.value = value;
    }

    public static Keyword validKeyword(String value) {
        if (value.trim().length() == 0) {
            throw new InvalidKeywordException();
        } else {
            return new Keyword(value);
        }
    }
}
  • keyword에 대한 속성을 다루기 위해 컴포지트 객체를 사용했다. 다만, keyword는 게시글과 종속적인 개념이 아닌 검색을 위해서만 사용되기 때문에 독립적이다.

InvalidKeywordException

public class InvalidKeywordException extends BadRequestException {

    private final static String MESSAGE = "검색 키워드는 빈칸 없이 1개 이상의 단어를 입력해 주세요";

    public InvalidKeywordException() {
        super(MESSAGE);
    }
}
  • 해당 예외 클래스에 대한 내용이다.

결과

📒 나의 생각

  • 값 타입과 정적 팩토리 메서드를 적용하여 프로젝트 구조를 만들다보니 역할이 제대로 분리된 구조로 만들 수 있었다.
  • 반복되는 메서드 수정, API 스펙에 Entity가 노출되지 않도록 변경과 같은 리팩토링도 피드백을 받고 나서 진행중이다. 혼자서 코드를 보다보면 놓치는 부분이 많은데, 다른 사람과 코드를 같이 보면 부족했던 부분을 알 수 있어 스터디가 매우 유익했다!
  • 디자인 패턴에 대해서도 깊게 공부해보고 코드로 직접 구현해 보는 시간을 가져야 할 것 같다!

0개의 댓글