spring 유효성검사

2023. 12. 13. 04:49카테고리 없음

엔티티또는 받아오는 데이터에 유효성검사는 상당히 프로젝트 구성에서 중요한 역할을 하고있다.

프로젝트를 구성하던 도중 글자수 제한등에 사용되는 코드를 쓰다가 문득 무슨차이가 있을까

궁금해졌다.

 
   
   public class User {
    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "닉네임을 입력해주세요")
    @Size(min = 3, max = 50, message = "닉네임을 3자이상 입력해주세요")
    @Pattern(regexp = "^[a-zA-Z0-9]{3,50}$", message = "닉네임은 알파벳과 숫자로 입력해주세요")
    @Column(length = 50)
    private String nickname;
    }

@Size 어노테이션

@pattern 어노테이션

@column 어노테이션 역시 코딩 허접인 내게는 다 비슷비슷 하게 보여서 처음으로 구성한 코드가 위와 같았다.

 

나는 닉네임의 최소글자를 3, 최대글자수를 50으로 설정을 하려고 다음과같은 어노테이션들을 사용해 설정을

해주었는데, 문득보면 다들 비슷한 일을 수행하고 있는것으로 보였다. 

실제로 @Size 어노테이션과 @Pattern 어노테이션이 수행하고 있는 글자수 제한 이라는 역할은 거의 동일한것이 맞았다.

 

@pattern에서 정규표현식을 사용해 {3,50}등으로 이미 들어오는 값에대한 패턴 유효성 검사를 실시하고있어 

@Size 어노테이션은 제거를해도 기능적으로 차이가 발생하지 않았다.

 

 
   
   public class User {
    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "닉네임을 입력해주세요")
    @Pattern(regexp = "^[a-zA-Z0-9]{3,50}$", message = "닉네임은 알파벳과 숫자로 3자이상 입력해주세요")
    @Column(length = 50)
    private String nickname;
    }

 

1차로 수정한 엔티티 필드의 모습이었다. 

이전과같이 유효성검사가 수행되는것은 같지만 필요없는 코드를 제거해주었다.

 

그리고 문득 Column에서도 또 글자수에대한 제한을 걸어주고 있는것을 발견한나는 이것도 없앨 수 있을까? 라고 생각이 들었다.

이미 엔티티에 Pattern 어노테이션을통해 50글자수 제한을 두고있는데, 굳이 Column을통해 또 제한을 해줄필요가 있을까


이것에는 장단점이 존재했다.

@Column과 @Patern 중복사용의 장점

 

이 두가지 유효성 검사를 동시에 사용할 경우 우리는 혹시라도 잘못 길이 제한이 설정되거나 적용되지 않아서 데이터 베이스에 의도하지 않은 값이 들어가는 상황을 방지할 수 있다. 이는 애플리케이션 외부에서 데이터베이스에 직접 접근할 때 발생할 수 있는 오류를 방지할 수 있는것이다.

@Column과 @Patern 중복사용의 단점

 

단점으로는 중복된 로직이 적용되고 여러곳의 같은 변경을 수행해야하기에 유지보수에서 조금의 문제가 발생할 수 있다.

또한, 데이터베이스에서 길이 제한을 설정하면 이에 대한 검사가 런타임에 발생하게 된다고 한다.

이는 애플리케이션의 성능에 영향을 어느정도 미친다고 한다.

 

결론적으로 보안을 생각한다면 데이터베이스에서 길이제한을 함께 사용해도 괜찮다고 한다.

 

이러한 패턴을 엔티티 필드가아닌, 받아오는 DTO에서 수행하는게 좀더 건강한 코드일까?

 

알아보니 일반적으로 유효성 검사 로직은 엔티티 필드가 아닌 DTO(Data Transfer Object)에서 수행하는 것이 좋은 방법 중 하나이다. 다음과 같은 이유로 인해 DTO에서 유효성 검사를 처리하는 것이 코드의 구조를 더 건강하게 유지할 수 있다.

 

1. 클라이언트로부터의 입력을 캡슐화

 

Dto는 주로 클라이언트로부터의 입력을 캡슐화하여클라이언트로부터의 입력이 엔티티 필드로 직접 전달되지 않고, 먼저 Dto를 통과하게 된다. 그렇기에 Dto에서 유효성 검사를 수행하면 클라이언트로부터의 부적절한 입력을 미리 거부할 수 있는것이다.

 

2. Dto의 이점 활용

유효성 검사 뿐만이 아니라 엔티티는 주로 비즈니스 로직에 집중하게 만들어야 논리적 일관성을 유지할 수 있다고 한다.

.그래서 유효성검사는 Dto에서 처리하는편이 이점인 재사용성등을 이용하기 편리하다.

 

 

 

최종적으로 수정한 코드는다음과 같았다!

public class UserCreateRequestDTO {
    @NotBlank(message = "닉네임을 입력해주세요")
    @Pattern(regexp = "^[a-zA-Z0-9]{3,50}$", message = "닉네임은 알파벳과 숫자로 3자 이상 입력해주세요")
    private String nickname;
}

                                           

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 50)
    private String nickname;
}