[기술정리] 유효성 검사 - 어노테이션, AOP

이나겸's avatar
Nov 25, 2024
[기술정리] 유효성 검사 - 어노테이션, AOP
💡

유효성 검사

  • 입력 데이터가 특정 조건이나 형식에 부합하는지 확인하는 과정
  • 데이터 무결성 보장, 잘못된 데이터가 시스템에 저장되거나 처리되지 않도록 방지

유효성 검사 어노테이션(@)

@Valid

  • 객체의 유효성 검사에 사용해서 요청 데이터가 올바른지 검증
  • 컨트롤러 메소드의 매개 변수, 엔티티, DTO 클래스와 함께 사용
  • 유효성 검사에 실패하면 자동으로 예외가 발생하고, 이를 통해 적절한 에러 메시지를 반환
  • @Valid를 사용하는 위치
    • Controller 메소드의 파라미터 : 요청을 받을 때 DTO 객체에 대해 유효성 검사를 수행
    • Service 계층 또는 리포지토리 계층 메소드 : 필요한 경우 여러 계층에서 추가로 유효성 검사를 수행
    • 내부 객체의 유효성 검사 : @Valid를 중첩하여 객체 내의 객체 필드도 함께 유효성 검사를 수행
 

@NotNull

  • 값이 null이 아니어야 함을 명시
@NotNull private String name;
 

@Size

  • 문자열, 컬렉션 등의 크기를 제한
@Size(min = 2, max = 30) private String name;
 

@Min, @Max

  • 숫자의 최소 및 최대값을 지정
@Min(18) @Max(65) private Integer age;
 

@Pattern

  • 정규 표현식 패턴에 맞는지 확인
@Pattern(regexp = "^[A-Za-z0-9]+$") private String username;
 

@Email

  • 이메일 형식인지 확인
@Email private String email;
 

사용 예제

예제1 - Controller에서의 유효성 검사

  • @Valid를 @RequestBody와 함께 사용하여 요청 본문에 대한 유효성 검사 수행
  • UserDTO의 필드에 정의된 유효성 검사 어노테이션 기준으로 검사 수행
  • 유효성 검사를 통과하면 로직 실행
  • 통과하지 못해서 예외 발생하면 @ExceptionHandler인 handleValidationExceptions 메소드 호출되서 에러 메세지 반환
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.http.ResponseEntity; import org.springframework.http.HttpStatus; import java.util.stream.Collectors; @RestController public class UserController { // 유효성 검사 성공 시 @PostMapping("/users") public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO user) { return ResponseEntity.ok("User created successfully"); } // 유효성 검사 실패 시 예외 처리 @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<String> handleValidationExceptions(MethodArgumentNotValidException ex) { String errors = ex.getBindingResult().getFieldErrors().stream() .map(error -> error.getField() + ": " + error.getDefaultMessage()) .collect(Collectors.joining(", ")); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Validation failed: " + errors); } }

예제2 - DTO 클래스에서 유효성 검사

  • String name 필드
    • null이 아님을 보장, null일 경우 메세지 출력
    • 문자열 길이 2 ~ 30자로 제한
  • Integer age
    • null이 아님을 보장, null일 경우 메세지 출력 (null 판단해야해서 int가 아닌 Integer)
    • 최소 18 이상이어야 함을 설정
  • String email
    • 이메일 형식 확인, 형식이 맞지 않을 경우 메세지 출력
import javax.validation.constraints.*; public class UserDTO { @NotNull(message = "Name cannot be null") @Size(min = 2, max = 30, message = "Name must be between 2 and 30 characters") private String name; @NotNull(message = "Age cannot be null") @Min(value = 18, message = "Age should be at least 18") private Integer age; @Email(message = "Email should be valid") private String email; }
 

AOP

💡

AOP (관점 지향 프로그램)

관점에 따라서 다른 행위를 만듦
  • 관리하고자 하는 핵심 코드를 제외한 부가적인 로직을 분리(관점 분리)해서 핵심 로직에만 집중
  • 동일한 모듈을 이용해야함
    • 행단 관심사 : 여러 모듈에서 반복적으로 필요로 하는 기능
    • 공통 기능을 행단 관심사로 분리하여 코드 중복을 줄이고, 모듈성을 높이는 것을 목표로 함
  • 예시 - 옷을 입다( ) 메소드를 생성했다고 가정
    • 격식있게 입다, 편한 복장을 입다, 젠틀하게 입다 ⇒ 옷을 입다라는 행위가 관점에 따라서 달라져야 해서 만들기 어려움
    • 옷을 입다 (부가 로직 (공통 로직))
      • - 격식있게 입다 (핵심 로직 : 회사 미팅)
      • - 편하게 입다 (핵심 로직 : 운동하기)
      • - 젠틀하게 입다 (핵심 로직 : 소개팅)
    • 옷을 입다를 분리시키기 (프록시 패턴 활용)
 

@Aspect

  • AOP에서 관점을 정의
  • 해당 클래스가 특정 관점을 담당하도록 지정
  • 특정 행단 관심사에 대한 처리 담당
  • 필요한 포인트에 어드바이스 삽입 가능

포인트컷(Pointcut) 걸기

  • AOP에서 어드바이스가 적용될 지점을 선택하는 표현식
  • 특정 메서드나 클래스, 조건에 따라 관점이 실행되도록 하는 규칙을 설정
  • 어떤 지점(메서드 호출 전후, 특정 패턴을 가진 메서드 등)에 공통 기능이 적용될지를 명확히 지정 ⇒ 특정 조인포인트를 필터링 ⇒ 조인포인트 중에서 어느 시점에 에스펙트가 실행될지 결정하는 표현식
  • 이 행위가 어디에서 실행되는지 깃발(어노테이션) 꽂기

조인포인트(Joinpoint)

  • Aspect를 적용할 수 있는 구체적인 지점
  • 메소드 호출, 예외 발생 등
Share article

Nakyeom's Study