Spring Validation과 생성자 가드

텐저린티·2023년 9월 5일
0

Spring

목록 보기
3/6
post-thumbnail
💡 같은 역할인데 왜 둘 다 쓰지?
  • 결론은 둘 다 써야 한다
  • 각자의 역할이 다르기 때문

Spring Validation

public class HumanName {
		
		@NotBlank
		private String name;

		public HumanName(String name) {
				this.name = name;
		}
	
		protected HumanName() {}

		public String getName() {
				return name;
		}
}
@PostMapping
public ResponseEntity<HumanName> createHumanName(
		@Valid @RequestBody HumanName name
) {
		...
}
  • Spring Boot 에서 지원하는 유효성 검사 도구
  • 실질적으로 hibernate validator (Bean Validation 프레임워크 구현체) 를 사용함.
  • SpringBoot 가 @Valid 매개변수 찾으면 하이버네이트 Validator를 자동으로 부트스트랩해서 매개변수 검증
  • @Valid 를 사용하지 않은 곳에서는 validation 유효성 검사하지 않음
💡 @Valid vs @Validated 차이
  • @Valid
    • Java에서 지원하는 어노테이션
  • @Validated
    • Spring 에서 지원해주는 어노테이션
    • @Valid 기능 포함
    • 유효성 검토할 그룹 지정 기능 포함
💡 의존성
  • SpringBoot 2.3 이후부터 Web 의존성 내부에 있던 validation이 사라짐
  • 따로 추가해줘야 한다

생성자 가드

public User(String name) {
		// 조건문 가드
		if (name == null || name.isBlank()) {
				throw new IllegalArgumentException("이름 이렇게 지으면 아니됨");
		}
		// Assert 가드
		Assert.isTrue(StringUtils.isNotBlank(name), "이렇게 지으면 안 된다고");
		this.name = name;
}
  • 이렇게 생성자 메소드 안에 if 조건문 혹은 Assert 클래스를 이용해 유효하지 않은 생성자 파라미터를 차단하는 것을 말한다.
  • 생성자 가드를 통해 유효하지 않은 값을 가진 객체 생성을 원천적으로 방지할 수 있으므로 프로그램 전반적인 안정성을 높일 수 있다.

조건문 방식

  • 코드가 조금 지저분할 수 있다.
  • 원하는 조건을 만들어 쉽게 만들어낼 수 있다.
  • 원하는 예외를 쉽게 던질 수 있다.

Assert 방식

  • 코드가 간단해질 수 있다.
  • IllegalArgumentException으로 제한된다.

그래서 왜 둘 다 써야해?

Validation 미사용 + 생성자 가드 사용

@PostMapping(consumes = APPLICATION_JSON_VALUE)
public String postUser(@RequestBody AddUserRequest request) {
  LoggerFactory.getLogger(getClass()).info("결과 - {}", request.getName());
  return request.getName();
}
public class AddUserRequest {

  private String name;

  public AddUserRequest(String name) {
    if (name == null || name.isBlank()) {
      throw new IllegalArgumentException("생성자 가드에 걸림!");
    }
    this.name = name;
  }

  protected AddUserRequest() {
  }

  public String getName() {
    return name;
  }
}

Validation 사용 + 생성자 가드 미사용

  • 컨트롤러에서는 문제 없지만, 프로그램 내부에서 직접 생성자로 객체를 생성하는 경우에는 유효성 판단이 불가하다.
@PostMapping(consumes = APPLICATION_JSON_VALUE)
public String postUser(@Valid @RequestBody AddUserRequest request) {
  LoggerFactory.getLogger(getClass()).info("결과 - {}", request.getName());
  return request.getName();
}
public class AddUserRequest {

  @NotBlank
  private String name;

  public AddUserRequest(String name) {
    this.name = name;
  }

  protected AddUserRequest() {
  }

  public String getName() {
    return name;
  }
}

결론

  • 둘 다 사용하는 것이 프로그램 전반적으로 유리한 일이다.
  • 그게 아니라면, 모든 validation 사용처에 @Valid 어노테이션을 달아줘야 함
profile
개발하고 말테야

0개의 댓글