AOP(Aspect Oriented Programming)

D A S H B O A R D
D E V E L O P
S E C U R I T Y
 AOP란?
 공통 관심 사항 vs 핵심 관심 사항
 AOP 동작 방식
 사용 방법
Reference

 AOP란?

AOP는 공통 관심 사항(cross-cutting conern)과 핵심 관심 사항(core concern)으로 분리해 모듈화를 진행하겠다는 의미이다. 즉, 함수의 호출 전후, 예외 발생 시, 메소드의 실행 시간 등과 같이 핵심 관심 사항 외에 부가적인 작업을 수행하기 위해 부가적이고 반복되는 코드를 하나로 묶어 반복되는 코드를 줄이겠다는 목적으로 사용
AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍 라고 한다.

 공통 관심 사항 vs 핵심 관심 사항

그림에서 같은 색의 사각형 박스는 같은 코드이자, DB 연결, 로깅, 시간측정 등과 같은 부가적인 코드로 쉽게 말해 공통 관심 사항(흩어진 관심사, Crosscutting Concerns)이라고 한다. 이러한 코드가 반복적으로 존재할 시, SOLID원칙을 위배하며 유지보수를 어렵게 만든다.
이러한 흩어진 관심사들을 가각의 기준에 따라 모듈화 시키는 것이 AOP 관점에서의 할 일이다.
모듈화를 진행하면 핵심 관심 사항과 공통 관심 사항의 분리도 이루어질 뿐 아니라, 어디에 적용할지만 정의해주면 되기 때문에 유지보수도 간편해진다.
그림 아래 Aspect X, Y, Z가 모듈화된 모습으로 이를 Aspect라고 부른다.
공통 관심 사항 vs 핵심 관심 사항
공통 관심 사항 : 부수적인 코드 → DB 연결, 로깅, 시간 측정, 파일 입출력 등
핵심 관심 사항 : 비즈니스 로직 → 비즈니스와 관련된 핵심 로직

 AOP 동작 방식

AOP 적용 전

AOP 적용 후

AOP가 적용되기 전에는 Controller가 바로 핵심 로직을 호출하는 방식으로 진행되지만 AOP 적용 시에는 Controller는 항상 Proxy를 통해 핵심 로직을 호출한다. 즉 Proxy를 통해 Advice를 실행하고 JoinPoint.preceed()를 이용해 다음 실행될 핵심 로직을 실행시킨다. 이를 통해 핵심 로직과 부수적인 로직을 분리할 수 있다.
관련 용어
Aspect : 흩어진 관심사를 모듈화 한 것.(Advice와 Point Cut을 포함)
Target : Aspect를 적용하는 곳 == 부가기능을 부여할 대상, 핵심 기능을 담당하는 Service
Advice : 실질적으로 어떤 일을 해야 할 지에 대한 것, 실질적인 부가기능을 담은 구현체
Join Point : Advice가 적용될 위치 혹은 끼어들 수 있는 시점. 메서드 진입 시점, 생성자 호줄 시점, 필드에서 꺼내올 시점 등 끼어들 시점을 의미. 참고로 스프링에서 Join Point는 언제나 메서드 실행 시점을 의미 한다.
Point Cut : Join Point의 상세한 스펙을 정의한 것. "A란 메서드의 진입 시점에 호출할 것"처럼 구체적으로 Advice가 실행될 시점을 정함. 즉, 어드바이스가 적용될 대상(매서드)을 지정하는 역할

 사용 방법

Ex. 시간 측정

package com.boot.lecture1.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; //@Component @Aspect public class TimeTraceAop { @Around("execution(* com.boot..*(..))") public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); System.out.println("START: " + joinPoint.toString()); try{ return joinPoint.proceed(); } finally { long finish = System.currentTimeMillis(); long timeMs = finish - start; System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms"); } } }
Java
복사
@Aspect 어노테이션을 붙여 이 클래스가 Aspect를 나타내는 클래스라는 것을 명시
@Around 어노테이션은 타겟 메서드를 감싸서 특정 Advice를 실행한다는 의미 (Point Cut, Join Pont) → "execution(* com.boot..*(..))" 해당 부분은 com.boot 부터 하위 모든 패키지에 있는 모든 매서드에 Aspect를 적용하겠다는 의미 → 여러 문법이 있으니 찾으면서 사용하길 바란다.
AOP도 스프링 컨테이너 안에 Bean으로 존재하여야 하기 때문에 @Component 를 붙여 컴포넌트 스캔을 통해 스프링 Bean으로 등록할 수 있지만, 해당 AOP 코드가 있음을 알 수 있도록 SpringConfig와 같은 곳에 직접 코드로 스프링 Bean에 등록해주는 것이 좋다.
@Bean public TimeTraceAop timeTraceAop() { return new TimeTraceAop(); }
Java
복사
Aspect 실행 시점을 지정할 수 있는 어노테이션(Join Point)
@Before (이전) : 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
@After (이후) : 타겟 메소드의 결과에 관계없이(즉 성공, 예외 관계없이) 타겟 메소드가 완료 되면 어드바이스 기능을 수행
@AfterReturning (정상적 반환 이후)타겟 메소드가 성공적으로 결과값을 반환 후에 어드바이스 기능을 수행
@AfterThrowing (예외 발생 이후) : 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행
@Around (메소드 실행 전후) : 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 호출전과 후에 어드바이스 기능을 수행