[Spring Boot] 51. 스프링부트 블로그 v2 (JPA) (21) 유효성 검사

김주희's avatar
Apr 15, 2025
[Spring Boot] 51. 스프링부트 블로그 v2 (JPA) (21) 유효성 검사
???? →
notion image
@PostMapping("/join") public String join(UserRequest.JoinDTO joinDTO) { // 유효성 검사 -> AOP // 빈생성자 + setter 호출됨 boolean r1 = Pattern.matches("^[a-zA-Z0-9]{2,20}$", joinDTO.getUsername()); boolean r2 = Pattern.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*()])[a-zA-Z\\d!@#$%^&*()]{6,20}$", joinDTO.getPassword()); boolean r3 = Pattern.matches("^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$", joinDTO.getEmail()); if (!r1) throw new Exception400("유저네임은 2-20자이며, 특수문자,한글이 포함될 수 없습니다"); if (!r2) throw new Exception400("패스워드는 4-20자이며, 특수문자,영어 대문자,소문자, 숫자가 포함되어야 하며, 공백이 있을 수 없습니다"); if (!r3) throw new Exception400("이메일 형식에 맞게 적어주세요"); userService.join(joinDTO); return "redirect:/login-form"; }
 
UserController에서 유효성 검사를 하게되면 지저분하고 등등
(빈생성자 + setter로 동작)
UserRequest에서 하면 깔끔한데 DS에서 invoke할 메서드의 매개변수로 들어가는 DTO 생성? 때 이미 try-catch 처리해서 여기서는 할수없도록 막혀있음? ⇒ Spring에서 제공하는 방법을 쓰자
notion image
⇒ @Pattern @Size (Validation 클래스가 들고 있는 annotation 여러개 @NotEmpty 등 → 문서 꼭 안읽어도 GPT에 물어보면 됨 )
notion image
: 깃발이 꽂혀있는 것을 사이즈나 패턴 검사 → 문제가 생기면 에러는 어디로? 여러 개 터지면?
그리고 @Valid 붙어야 검사 reflection을 타고 @Pattern @Size 등 검사
오류가 터지면 그 다음 매개변수한테 전달함 (Errors errors) - 바로 옆 매개변수 자리에 넘겨주므로 주의!!!!!!!!!!!!!!!!!!!!!!
 
유효성 검사 : Controller → DTO의 책임
DTO는 Post와 Put Mapping일때만 body data가 있으니까 그때만 유효성 검사하면 된다.
 
<공통 모듈>
if(errors.hasErrors()) { List<FieldError> fErrors = errors.getFieldErrors(); // 에러 메세지를 유저에게 여러개 전달X for(FieldError fieldError : fErrors) { // 순서 보장X throw new Exception400(fieldError.getField()+":"+fieldError.getDefaultMessage()); // fieldError.getField() = > e.g. username } }
 
 
부가 로직 중에서도 동일하게 생긴 것 = 공통 모듈 → 그래야지 빼가지고 함수로 만들어서 재사용 가능
 
RequestMapping으로 uri if문 처리하는 거 → annotation으로 공통모듈? 해본적있음
 
(insert / update는 전부 validation 체크 해야됨??)
 
  1. 핵심로직
  1. 부가로직 (분리하려면 공통모듈이 되어야 한다.)

핵심로직을 실행하기 전에 부가로직을 호출하고 접근 (프록시 패턴)
 
이미 만들어져있는 걸 어떻게 분리? → 프록시
기존코드 손대면 OCP 위배 → 앞단에다가 무언가를 추가 (무언가는 재활용 가능)
무언가 = 대리인 = Proxy
 
 
 
Proxy에서 validiation check → 근데 framework 때문에 직접 DS와 Controller 사이에 Proxy만들 수 X 제어권이 없음 → annotation 제공함!
 
// AOP 정규표현식 한 번 찾아보기
 
interceptor는 메서드를 투영해서 분석하지 못하고 reflection X
 
 
@Before("@annotation(shop.mtcoding.blog._core.error.anno.MyBefore || @annotation(postmapping) || @annotation(putmapping)만 하면 됨!))") // 패키지명을 풀로 적는다. public void beforeAdvice(JoinPoint jp) { String name = jp.getSignature().getName(); // annotation이 어디 붙을지 모르니까 메서드일지 클래스일지 등 -> 그래서 Signature System.out.println("Before Advice : " + name); // name = 메서드명 } // 그리고 이 안에서 errors.hasErrors() ~ 공통모듈 들어가면 됨
 
 
AOP
관점지향프로그래밍 이해 → 관점부터 이해
목적인 행위는 동일한데 그 행위를 하는 관점이 다름
목적의 행위에 따라서 관점이 달라질 수 있음???
(옷을 입는데 결혼식장을 가기 위한 옷, 회사를 가기 위한 옷 근데 옷을 입는 동일한 행위를 함)
관점에 따라서 다르게 실행되는 프로그램 = aop?
 
→ 핵심로직과 부가로직을 분리 (스프링에서는 자동 - 왜? 핵심로직은 service에 넘어가니까 / 부가로직은 service의 앞뒤)
→ 부가로직을 동일한 코드로 만들어야 (공통모듈화) (패턴을 찾기 등 여러가지 방법) → 가장 좋은 방법 : reflection으로 구현
 
공통모듈로 만든거 advice로 뺏음
부가로직 = advice? (공통모듈이 들어있는 행위)
aspect = 관점을 가지고 있는애 → class에 붙이면 됨 → 관점에 따라 다르게 행동할 거기 때문에
프록시에 실행되어야 하는건 advice
PointCut = 어디서 실행할지? advice를 어디다가 꽂을건지 → 가장 좋은 방법은 깃발을 만들어서 꼽는 것
 
 
관점은 여러개 일 수 있고
유효성에 대한 관점
notion image
notion image
 
@PointCut 굳이 사용X
 
포인트컷 표현식 문법 공부 필요하지만 gpt가 알려주긴 함
notion image
updateForm(@LoginUserApp? User sessionUser)
→ LoginUserApp~ type 찾아서 sessionUser (2: 20: 00)?
코드 설명 gpt
 
 
관점에 따라 다르게 실행 → but 공통모듈로 만들어내야
공통모듈 만들기가 제일 어려움
 
 
 
@NotNull @NotEmpty @NotBlank GPT 물어봐서 정리하기
우리는 @NotEmpty만 쓴다!
integer는 빈 문자열을 전달할 수 없으므로 notnull 써야됨
Share article

jay0628