📖스프링 프레임워크의 핵심 개념 중 하나로 Aspect Oriented Programming(관점지향 프로그래밍)이다.
그렇다면 관점지향 프로그래밍은 또 무엇인가?
스프링에서는 기존 AspectJ(라이브러리)
를 차용한 개념으로 간단하게 설명하면 흩어진 관심사(Cross-Cutting Concern)
를 모듈화
할 수 있는 프로그래밍 기법이다. 이 말은 프로그램의 특정 로직을 핵심적인 관점
, 부가적인 관점
으로 나누어 보고 그 관점을 기준으로 각각 모듈화를 하겠다는 것이다.
예를 들어 쇼핑사이트에서 고객이 물품을 구매하거나 장바구니를 확인하는 등의 기능을 사용하려면 로그인이 되어있어야 하는데 프로그램은 해당 기능을 사용하려는 고객이 로그인이 되어있는지 여부를 계속 확인해야한다. 이 부분이 바로 부가적인 관점이자 흩어진 관심사가 되는 것이다.
흩어진 관심사는 횡단적 관점이라고 말하기도 한다. 프로그램의 기능들이 핵심 로직을 수행하기 위해 반드시 건너가야하는 하나의 횡단보도라고 생각하면 좋을 것 같다.
글로 설명하기에는 너무 추상적일 수 있으니 아래 그림을 보면서 다시 한번 위의 내용을 생각해보자.
위 그림에서 물품구매, 장바구니, 결제는 고객이 이용해야할 기능이다. 해당 기능들을 이용하기 위해서는 고객이 로그인이 되어있는 상태인지 확인이 필요하다. 이때 공통적으로 수행되면서 핵심 로직이라고는 할 수 없는 로그인 확인 기능이 부가적인 관점이자 흩어진 관심사로 볼 수 있는 것이다.
AOP는 OOP(Object Oriented Programming)의 단점을 보완하기 위하여 스프링에서 사용된다. 그렇다면 OOP의 단점을 간략하게 알아보자.
대표적으로 두가지만 제시를 하였지만 개발을 하다보면 이만저만 불편한게 많다. 결국은 코드가 간결하지 못하고 유지보수성이 높아진다는 것이 결론이다.
AOP의 대표적인 기능은 트랜잭션 처리라고 할 수 있다. 기존 OOP를 이용할 경우 트랜잭션을 일일이 처리해줘야하는 단점이 있지만 AOP를 사용하여 흩어진 관심사로 등록하고 필요한 시점에 자동적으로 호출되도록 하는 것이다.
결론적으로 수동적
이면서 물리적인 코드 배치
를 하게되는 기존 OOP 방식에서 흩어진 관심사의 코드를 물리적으로 분리
하고 AOP로 지정
하여 능동적
으로 해당 기능이 수행되도록 하는 것이다. 추가로 스프링의 핵심 개념 중 DI가 의존성을 약하게 한다데 그친다면 AOP는 의존성을 완전히 탈피
하는 개념인 것이다.
이제 개념적인 부분에 대해서는 어느정도 설명을 하였으니 AOP의 주요개념에 대해서 알아보자.
다음으로 스프링 AOP의 특징에 대해서 알아보자. 참고로 AOP는 스프링에만 적용되는 특수한 개념이 아니다.
프록시 패턴 기반
의 AOP 구현체로 접근 제어 및 부가기능을 추가하기에 용이스프링 Bean
에만 AOP를 적용가능. 즉 Bean이 지정되지 않은 객체는 적용 불가능스프링 @AOP를 사용하기 위해서는 의존성을 아래와 같이 추가해준다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
특정 클래스가 Aspect를 나타내는 클래스라는 것을 명시하고 스프링 Bean으로 등록
@Component //Bean으로 등록
@Aspect //관점 명시
public class Test{
@Around("execution(*com.test..*.TestService.*(..))")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
long begin = System.currentTimeMills();
...생략
}
}
@Around 어노테이션은 타겟으로 지정된 메서드를 감싸서 특정 Advice를 실행한다는 의미이다. 어노테이션 뒤의 ()안의 내용은 com.test 패키지 경로의 TestService 클래스의 모든 메서드에 해당 Aspect를 적용한다는 의미이다.
위와 같이 경로를 지정하는 방식 외에 특정 어노테이션이 붙은 포인트에 해당 Aspect를 실행할 수 있는 기능도 제공한다.
@Component
@Aspect
public class Test{
@Around("@annotation(PerLogging)")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
long begin = System.currentTimeMills();
...생략
}
}
위와 같이 ()안을 명시해주면 해당 괄호안의 어노테이션만 붙은 메서드만 Aspect가 적용된다. 이 밖에도 Aspect 실행 시점을 지정할 수 있는 어노테이션은 아래와 같다.
이번 게시글에서는 스프링의 AOP에 대해서 알아보았다. 아직 스프링을 많이 공부하지 못해서 개념적인 내용과 기본적인 사용에 대해서만 알아본 것이다.
내가 AOP를 이해한 것은 반복적이고 중복되는 기능을 하나의 부가적인 관점으로 식별하여 모듈화하는 것이다. 모듈화를 할 경우 재사용성이 올라가며 유지보수성도 올라간다. 또한 AOP는 물리적으로 코드를 배치하는 것이 아니라 관점을 지정하고 타겟을 설정하여 능동적으로 해당 관점이 수행되도록 해주는 것이다. 즉, 의존성 탈피를 달성할 수 있으며 관점으로 지정된 기능만을 수정하여 유지보수를 완료할 수도 있다는 어마어마한 장점이 생기는 것이다.
아직 AOP를 적용할 위치와 지점을 찾는 것에 익숙하지 않지만 전체적인 프로그램에서 부가적인 관점을 잘 추출해 낼 수 있다면 AOP의 이점을 최대한 활용하여 프로그램을 개발할 수 있을 것이다. 그때까지 많은 시행착오를 겪어봐야겠다.
그럼 이만.👊🏽