AOP (Aspect Oriented Programming)
AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불린다. 관점 지향은 쉽게 말해 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하겠다는 것이다. 여기서 모듈화란 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것을 말한다.
AOP 주요 개념
개념 | 설명 |
Aspect | 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화 한다. |
Target | Aspect를 적용하는 곳 (클래스, 메소드,...) |
Advice | 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체 |
JoinPoint | Advice가 적용될 위치, 끼어들 수 있는 지점이다. 메소드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용 가능하다. |
PointCut | JoinPoint의 상세한 스펙을 정의한 것이다. 'A란 메소드의 진입 시점에 호출할 것'과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있다. |
AOP 특징
1. 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가 기능을 추가하기 위해서이다.
2. 스프링 빈에만 AOP를 적용 가능하다.
3. 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체들 간 관계 복잡도 증가 등)에 대한 해결책을 지원하는 것이 목적이다.
AOP 예시
이번 글에서는 특정 메소드의 실행 시간이 얼마나 걸리는지 체크해주는 어노테이션을 구현해볼 것이다. 결론부터 말하면 @LogExecutionTime 어노테이션을 붙이면 로그에 실행시간이 출력되게끔 만들 것이다.
> LogExecutionTime
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 메소드에서 어노테이션을 적용할 수 있게끔 설정한다.
@Retention(RetentionPolicy.RUNTIME) // 런타임동안 적용되게끔 한다
public @interface LogExecutionTime {
}
> LogAspect
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component // Bean으로 등록
@Aspect
public class LogAspect {
Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Around("@annotation(LogExecutionTime)") // LogExectionTime 어노테이션 주변에서 실행한다.
public Object LogExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed(); // 어노테이션이 붙어 있는 메소드가 joinPoint, 메소드를 실행시킨다.
long end = System.currentTimeMillis();
logger.info("실행 시간 : " + (end - start));
return proceed; // 실행된 메소드를 리턴해준다.
}
}
> HelloController
import com.leveloper.chacha.springbootchacha.aop.LogExecutionTime;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
@LogExecutionTime // 앞서 만든 LogExecutionTime 어노테이션 추가
public String hello(){
return "hello";
}
}
애플리케이션을 실행시켜 "/hello" 위치로 접속해보면 로그에 실행 시간이 찍히는 것을 확인할 수 있다.
마무리
이번에는 프록시 기반의 AOP를 활용하여 공통 로직을 모듈화 하는 방법에 대해 알아보았다. AOP는 위의 방법 이외에도 다양한 방법으로 활용할 수 있다. 좀 더 자세한 내용은 https://sjh836.tistory.com/157를 참고하자.
'Spring Boot' 카테고리의 다른 글
[스프링] AWS S3에 이미지 업로드 하기 (0) | 2020.02.06 |
---|---|
[스프링] 배포용 서버에 데이터베이스 Schema 및 Data 초기 설정하기 (3) | 2020.02.01 |
[스프링] IoC(Inversion of Control), DI(Dependency Injection), Spring Container, Bean 정리 (0) | 2020.01.25 |
[스프링] 오픈 api 사용해서 데이터 가져오기 (네이버 영화 검색 api) (7) | 2020.01.14 |
[스프링] Spring 웹 계층 (2) | 2020.01.03 |