유효성 검사 어노테이션(@)
@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
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
- 관리하고자 하는 핵심 코드를 제외한 부가적인 로직을 분리(관점 분리)해서 핵심 로직에만 집중
- 동일한 모듈을 이용해야함
- 행단 관심사 : 여러 모듈에서 반복적으로 필요로 하는 기능
- 공통 기능을 행단 관심사로 분리하여 코드 중복을 줄이고, 모듈성을 높이는 것을 목표로 함
- 예시 - 옷을 입다( ) 메소드를 생성했다고 가정
- 격식있게 입다, 편한 복장을 입다, 젠틀하게 입다 ⇒ 옷을 입다라는 행위가 관점에 따라서 달라져야 해서 만들기 어려움
- 옷을 입다 (부가 로직 (공통 로직))
- - 격식있게 입다 (핵심 로직 : 회사 미팅)
- - 편하게 입다 (핵심 로직 : 운동하기)
- - 젠틀하게 입다 (핵심 로직 : 소개팅)
- 옷을 입다를 분리시키기 (프록시 패턴 활용)
- 부가 로직은 프록시에서 자동 입력 5. 프록시패턴
@Aspect
- AOP에서 관점을 정의
- 해당 클래스가 특정 관점을 담당하도록 지정
- 특정 행단 관심사에 대한 처리 담당
- 필요한 포인트에 어드바이스 삽입 가능
포인트컷(Pointcut) 걸기
- AOP에서 어드바이스가 적용될 지점을 선택하는 표현식
- 특정 메서드나 클래스, 조건에 따라 관점이 실행되도록 하는 규칙을 설정
- 어떤 지점(메서드 호출 전후, 특정 패턴을 가진 메서드 등)에 공통 기능이 적용될지를 명확히 지정 ⇒ 특정 조인포인트를 필터링 ⇒ 조인포인트 중에서 어느 시점에 에스펙트가 실행될지 결정하는 표현식
- 이 행위가 어디에서 실행되는지 깃발(어노테이션) 꽂기
조인포인트(Joinpoint)
- Aspect를 적용할 수 있는 구체적인 지점
- 메소드 호출, 예외 발생 등
Share article