[스프링부트]AOP(관점지향 프로그램 )

송송승현's avatar
Nov 21, 2024
[스프링부트]AOP(관점지향 프로그램 )

정의

💡
스프링 프레임워크에서 제공하는 기능 중 하나
핵심 비즈니스 로직에서 부가적인 관심사를 분리하여 코드의 모듈성 향상, 재사용성 향상,
코드의 복잡도를 줄이는데 목적을 둠
메소드안에 핵심적인 비즈니스 로직과 같이 작성하는 것이 아닌, 따로 모듈화 하여 여러객체에 공통적으로 사용할 수 있게하는 코드

핵심 개념

💡
관심사의 분리 - 핵심 비즈니스 로직과 부가적인 기능을 분리하여 코드의 모듈성 향상
재사용성 및 유지보수성 - 부가적인 기능을 애스팩트로 모듈화하여 재사용 가능하고, 유지보수성 향상
포인트 컷 : 부가적인 기능이 적용될 지점을 명시적으로 정의, 필요할 때만 적용

주요 용어

  • @Aspect : 해당 클래스를 부가적인 기능을 정의한 모듈
  • JoinPoint : Aspect가 적용될 수 있는 애플리케이션 실행 지점
  • Advice : Aspect의 실제 동적을 정의
  • @Befro, @After, @Around : 조인 포인트가 실행되기 전, 실행 후, 실행 전후 모두 실행하겠다.
  • @Pointcut : Aspect가 적용될 조인 포인트를 선택하는 표현식, 조인 포인트를 필터링하여 특정 메서드나 클래스 등에 Aspect를 적용할 수 있다.
  • Weaving : Aspect를 애플리케이션의 실제 코드에 적용하는 과정

예제

import com.example.blog._core.error.ex.Exception400; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; @Aspect @Component public class MyValidationAspect { @Before("@annotation(org.springframework.web.bind.annotation.PostMapping)") // Around는 JoinPoint가 아니라 ProceedingJoinPoint 사용 public void validationCheck(JoinPoint jp) throws Throwable { Object[] args =jp.getArgs(); for(Object arg : args) { if(arg instanceof Errors) { Errors errors = (Errors) arg; if (errors.hasErrors()) { String errMsg = errors.getFieldErrors().get(0).getField() +" : "+errors.getFieldErrors().get(0).getDefaultMessage(); throw new Exception400(errMsg); } } } } } @Data //getter,setter, toString public static class SaveDTO{ @NotBlank(message = "title을 입력해주세요") private String title; @NotBlank(message = "content를 입력해주세요.") private String content; public Board toEntity(){ Board board = new Board(null,title, content, null); return board; } } import com.example.blog._core.error.ex.Exception400; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.*; import java.util.List; // Controller의 책임 : 외부 클라이언트의 요청을 받고 그 요청에 대한 응답을 함 @Controller @RequiredArgsConstructor public class BoardController { private final BoardService boardService; @PostMapping("/board/save") public String saveV2(@Valid BoardRequest.SaveDTO saveDTO, Errors errors) { boardService.게시글쓰기(saveDTO); return "redirect:/"; } @PostMapping("/board/{id}/update") public String update(@PathVariable("id") int id, @Valid BoardRequest.updateDTO updateDTO, Errors errors) { boardService.게시글수정(id,updateDTO); return "redirect:/"; } }

설명

AOP를 사용한 유효성 검사

  • MyValidationAspect 클래스는 @PostMapping 어노테이션이 달린 메서드들에서 Errors 객체를 검사
  • 오류가 있을 경우 사용자 정의 예외(Exception400)를 던짐
  • 유효성에 대한 에러 상황에 대한 일관적 처리 가능
 
Share article

송승현의 블로그