Spring AOP Starter Kit(1)

jadeco·2023년 3월 22일
0

Spring AOP는 비즈니스 로직과 부가적인 기능(로깅, 보안 등)을 분리하여 모듈화하는 방식으로, 코드의 가독성과 유지보수성을 높일 수 있습니다. 이번에는 Spring AOP의 개념과 사용법, 예제에 대해 자세히 살펴보겠습니다.

Spring AOP란?

Spring AOP는 Aspect Oriented Programming(관점 지향 프로그래밍)의 약자로, 객체 지향 프로그래밍(OOP)을 보완하기 위한 프로그래밍 방식입니다. OOP는 클래스와 객체를 중심으로 프로그래밍을 하지만, AOP는 비즈니스 로직 외에 추가적인 기능(로깅, 보안 등)을 분리하여 모듈화하고, 이를 객체 지향적인 방식으로 구현하는 것입니다.

Spring AOP는 자바의 프록시 패턴을 이용하여 구현되며, Proxy 객체를 생성하여 비즈니스 로직과 부가 기능을 분리합니다. 클라이언트는 Target 객체를 호출하는 것처럼 Proxy 객체를 호출하면, Proxy 객체에서 부가 기능을 추가한 후 Target 객체의 메서드를 호출합니다.

Spring AOP 사용요소

Spring AOP에서 사용되는 요소들은 다음과 같습니다.

  1. Join Point
  • AOP가 적용되는 프로그램 실행 중의 특정 지점을 의미합니다. 메소드 실행, 예외 발생 등이 Join Point가 될 수 있습니다.
  1. Pointcut
  • Join Point를 선택하는 기준을 정의한 것입니다. 메소드 이름, 반환 타입, 매개변수 등의 정보를 이용하여 Pointcut을 정의할 수 있습니다.
  1. Advice
  • Join Point에서 수행될 부가 기능을 정의한 것입니다. Before, After, Around 등의 Advice가 있습니다.
  1. Aspect
  • Join Point와 Advice를 결합하여 하나의 모듈로 정의한 것입니다. Aspect는 Pointcut과 Advice를 모두 포함합니다.
  1. Target Object
  • 부가 기능이 적용될 대상 객체입니다.
  1. Proxy Object
  • Target Object를 대신하여 생성되는 객체로, 부가 기능이 포함된 객체입니다.
  1. Weaving
  • AOP에서 부가 기능을 Target Object에 적용하는 과정을 의미합니다. 컴파일 시점, 로드 시점, 런타임 시점에 적용할 수 있습니다.

Spring AOP에서는 위 요소들을 이용하여 부가 기능을 Target Object에 적용합니다. Aspect는 Pointcut과 Advice를 모두 포함하며, Target Object를 대신하여 Proxy Object를 생성하여 부가 기능을 추가합니다. 이를 위해 Weaving 과정을 수행합니다.

💡 Spring AOP에서 프록시 방식을 사용하는 이유는, 비즈니스 로직과 부가 기능을 분리하여 코드를 유지보수하기 쉽게 하기 위해서입니다. 프록시 객체는 Target 객체를 대신하여 호출되어, 부가 기능을 추가한 후 Target 객체의 메소드를 호출합니다.

  • 만약 프록시 객체 없이 Target 객체를 직접 참조한다면, Aspect 클래스에 정의된 부가 기능을 사용하기 위해 여러 곳에서 반복적으로 Aspect 클래스를 호출해야 하고, 이로 인해 코드의 복잡도와 유지보수성이 떨어집니다. 이를 방지하기 위해, Spring에서는 Target 객체를 상속하는 프록시 객체를 생성하여 부가 기능을 수행합니다.
  • 프록시 객체는 Target 객체와 동일한 인터페이스를 구현하므로, 클라이언트는 Target 객체인지 프록시 객체인지 구분하지 않고 사용할 수 있습니다. 이렇게 함으로써, 프록시 객체는 Target 객체에 부가 기능을 추가하면서도 Target 객체의 순수한 비즈니스 로직에 집중할 수 있도록 만들어줍니다. 따라서, 코드의 복잡도를 낮추고 유지보수성을 높일 수 있습니다.

Spring AOP 예제

Spring AOP를 예제로 살펴보겠습니다. 예제에서는 메서드 실행 전, 후에 로그 출력, 메서드 실행 시간을 측정하는 부가 기능을 실습하도록 하겠습니다.

1. autoproxy 설정(servlet-context.xml)

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<aop:aspectj-autoproxy/>
</beans:beans>

2. 의존성 추가

<!-- 
	AspectJ Weaver 
	AOP를 사용하기 위해서 추가함.
	PointCut 어노테이션, pom.xml에 버전 이슈(1.9.0) 버전 사용 필요
-->
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
	<version>1.9.0</version>
</dependency>

3. Aspect 클래스 구현(Advice 구현)

package com.kh.spring.common;

public class LogAdvice {
	public void printLog() {
		System.out.println("[공통로그 - LogAdvice] 비즈니스 로직 수행 전 동작");
	}
}
package com.kh.spring.common;

import org.aspectj.lang.ProceedingJoinPoint;

public class Log4jAdvice {

	public void printLogging() {
		System.out.println("[공통로그 - Log4j] 비즈니스 로직 수행 후 동작하긔!!");
	}
	
	public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("[BEFORE] : 비즈니스 메소드 수행 전에 처리할 내용");
		Object returnObj = pjp.proceed(); // 실행되는 메소드의 시점을 정하여 리턴해줌
		System.out.println("[AFTER] : 비즈니스 메소드 수행 후에 처리할 내용");
		return returnObj;
	}
}

4. Aspect 설정(XML 방식)

<!-- AOP XML 방식 -->
	<bean id="log" class="com.kh.spring.common.LogAdvice"></bean>
	<bean id="logger" class="com.kh.spring.common.Log4jAdvice"></bean>
	<aop:config>
		<aop:pointcut expression="execution(* com.kh.spring..*Impl.*(..))" id="allPointCut"/>
		<aop:aspect ref="logger">
			<aop:before method="printLog" pointcut-ref="allPointCut"/>
			<aop:after method="printLogging" pointcut-ref="allPointCut"/>
			<aop:around method="aroundLog" pointcut-ref="allPointCut"/>
		</aop:aspect>
	</aop:config>

결론

Spring AOP는 비즈니스 로직과 부가 기능을 분리하여 모듈화하고, 객체 지향적인 방식으로 구현하는 방식입니다. Aspect, Pointcut, Advice, Target Object, Proxy Object 등의 요소를 정의하여 사용하며, XML 설정 파일이나 Annotation을 이용하여 구현할 수 있습니다. Spring AOP를 이용하면 코드의 가독성과 유지보수성을 높일 수 있으며, 로깅, 보안 등의 부가 기능을 구현하기에 적합합니다.

profile
당신도요

0개의 댓글