@NotNull, @NotBlank, @NotEmpty의 위치

대영·2024년 2월 26일
2

Spring

목록 보기
10/16

🙏내용에 대한 피드백은 언제나 환영입니다!!🙏

@NotNull : null만 허용하지 않는다.
=> " "(공백), ""(초기화된 String) 는 허용한다.
@NotEmpty : null과 ""를 둘다 허용하지 않는다.
=> " "(공백) 은 허용한다.
@NotBlank : null과 ""(초기화된 String), " "(공백) 모두 허용하지 않는다.
출처

개인 프로젝트를 진행 중 궁금증이 생겼다.
'@NotNull, @NotBlank, @NotEmpty는 Entity 필드에 다는게 좋을까? 아니면 DTO에 다는게 좋을까?'

DTO의 내용은 이 전글에 내용이 적혀있다. 이해가 안간다면 보고오면 좋을 것 같다.

우선 내가 내린 결론은 ' 두 곳에 다 달자! ' 이다.

아래는 뒤에서 나올 내용들 중 Service 역할과 Controller 하는 메서드이다. (글의 이해를 위해 복잡한 코드는 빼고 기본만 가지고 왔다.)

	// Service
	@Transactional
    public Long save(PostDto.Request dto) {

        Post post = dto.toEntity();
        postRepository.save(post);

        return post.getId();
    }

	// Controller
 	@PostMapping("/post/write")		// @Validated는 DTO에서 사용 예정
    public ResponseEntity<String> save(@Validated @RequestBody PostDto.Request post) {
        try {
            postService.save(post);
            return ResponseEntity.ok("게시글 작성 완료.");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("게시글 작성 실패.");
        }
    }

👉Entity 필드에 달 경우

아래와 같이 달았다고 가정해보자.

@Entity
public class Post{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    private String title;

    @NotBlank
    private String content;

그리고 Controller를 실행시켰다고 해보자.

Controller에서는 DTO를 통해서 값을 받아 게시글을 저장한다.
Entity에서 @NotBlank를 하였기에 DTO에서는 문제가 없어 postService.save(post);로 넘어간다.

넘어간 후 위에서 본 postRepository.save(post);에서 빈칸에 대한 오류가 발생하는 것이다.

👉DTO 필드에 달 경우

이번에는 아래와 같이 DTO에 달았다고 가정해보자.

public class PostDto {

    @AllArgsConstructor
    @NoArgsConstructor
    @Getter @Setter
    @Builder
    public static class Request {

        @NotBlank
        private String title;
        @NotBlank
        private String content;
        
        public Post toEntity() {
            Post post = Post.builder()
                    .title(title)
                    .content(content)
                    .build();
            return post;
        }
    }

그리고 Controller를 실행시켰다고 해보자.

@Validated 어노테이션이 있기에 postService.save(post)로 넘어가지 않고 바로 처리가 된다.

차이점❓

위에서 말한 것을 정리해보자면

Entity에 달 경우 : Service 구간까지 넘어가 DB에 넘어가기 전 발생함.
DTO에 달 경우 : Service 구간까지 가지 않고 처리 됨.

그렇다면, public Long save(PostDto.Request dto) 메서드에 추가적인 쿼리가 날아가는 코드가 있다면, Entity에 달 경우, 추가적인 쿼리를 날리게 되는 것이다.

그럼 어디가 좋은가❓ - 나의 생각

@NotNull, @NotBlank, @NotEmpty을 다는 위치에 따라서 이점이 다르다고 생각한다.

DTO의 경우에는 곧바로 오류가 처리 되기에 추가적인 코드에 대한 쿼리는 날리지 않는다는 이점.
Entity의 경우 예상치 못한 코드로 인해 DTO를 사용하지 않고 Entity를 곧바로 쓰게 되는 경우에서의 처리에 대한 이점.

보통 데이터 전달 객체인 DTO에 어노테이션을 추가하겠지만,
두 경우에 대한 결과는 같으나, 위치에 따른 사용 방법이 달라질 뿐이라고 생각한다.

그래서, 개인적으로는 두 곳 모두 사용하는 것이 좋다고 생각하지만, 이런 경우에는 중복적인 검증이 이뤄질 수 있으니 잘 고려해야 한다고 생각하고, 개발자의 성향에 따라 달라질 것이라고 생각한다.

profile
Better than yesterday.

0개의 댓글