코딩항해기

[Spring] 관점 지향 프로그래밍 AOP (xml) 본문

Spring

[Spring] 관점 지향 프로그래밍 AOP (xml)

miniBcake 2024. 10. 15. 14:12

 

 

AOP 관점 지향 프로그래밍 Aspect Oriented Programming

Spring 프레임워크는 IoC와 AOP을 지원하는 경량의 프레임워크이다. 그 중 AOP는 관점 지향 프로그래밍을 의미하며, 횡단 관심사의 분리를 허용해 모듈성을 증가시키는 것이 목적인 프로그래밍 패러다임이다. 객체지향(OOP)의 단점(공통된 부가기능에 대한 코드가 중복, 반복되어 유지보수가 어렵다는 단점)을 해소하기 위해 등장했다.

 

https://velog.io/@mdy0102/AOP%EA%B4%80%EC%A0%90-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

 

이처럼 중복되는 횡단 기능을 분리해 모듈화하는 개념이다. 이 횡단 기능을 공통기능, 공통로직, 횡단관심 등이라고 부르기도 하며 종단 기능을 핵심기능, 핵심관심, 비즈니스 메서드, CRUD라고 부른다.

 

종단 기능은 biz의 common으로 빠지게 되며 Advice라고 한다. 이 Advice는 Service처럼 Autowired를 붙여 사용할 수도 있지만 Advice가 변경되면 유지보수가 어렵고, 비용이 발생하는 문제가 있다. (OOP의 단점)

 

이 한계를 AOP로 해결할 수 있다. Advice를 컨테이너에게 생성과 관리를 맡겨 Advice의 메서드(공통 로직)가 사용되야하는 때에 사용할 수 있도록 설정하는 방식이다. 마치 filter처럼 사용되는 형식이며 filter와는 다르지만 특정 단계에 끼어들어 해당 메서드를 거치게 한다는 점이 유사하다.

 

https://sallykim5087.tistory.com/158

 

(요청이 들어오면 Filter -> Intercepter -> AOP -> Intercepter -> Filter 순으로 거치게 된다.)

 

 

AOP 용어

조인포인트(Joinpoint) 

: 클라이언트가 호출하는 모든 비즈니스 메서드, 조인포인트 중에서 포인트컷되기 때문에 포인트컷의 후보로 생각할 수 있다.

 

포인트컷(Pointcut) 

: 특정 조건에 의해 필터링된 조인포인트, 수많은 조인포인트 중에 특정 메서드에서만 횡단 공통기능을 수행시키기 위해서 사용한다.

 

어드바이스(Advice)

: 횡단 관심에 해당하는 공통 기능의 코드, 독립된 클래스의 메서드로 작성한다.

 

위빙(Weaving)

: 포인트컷으로 지정한 핵심 관심 메서드가 호출될 때, 어드바이스에 해당하는 횡단 관심 메서드가 삽입되는 과정을 의미한다. 이를 통해 비즈니스 메서드를 수정하지 않고도 횡단 관심에 해당하는 기능을 추가하거나 변경이 가능해진다.

 

애스팩트(Aspect)

: 포인트컷과 어드바이스의 결합이다. 어떤 포인트컷 메서드에 대해 어떤 어드바이스 메서드를 실행할지 결정한다.

 

AOP 생성

환경설정

AOP를 생성하기 전에 의존성을 주입해줘야 한다. maven 의존성 태그를 추가한다.

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
</dependency>

 

추가한 dependency를 이해할 수 있도록 스키마를 추가한다. AOP는 biz에서 다룰 예정이므로, 이 스키마는 가장 먼저 실행되는 루트 컨테이너에 사용된다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/aop
                  http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                  http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context-4.2.xsd">
</beans>

 

Advice

package com.koreait.app.biz.common;

import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class LogAdvice {
    public void insertLog(){
        log.info("AOP: 글이 DB에 등록되었습니다.");
    }
}

 

등록

객체가 스프링 컨테이너에 등록되어있어야(bean) 관리 대상이 되기 때문에 사용할 Advice를 먼저 bean으로 등록한다.

<bean class="com.koreait.app.biz.common.LogAdvice" id="la"/>

 

해당 bean을 등록했다면 해당 bean을 활용해 AOP를 등록할 수 있다.

<aop:config>
	<aop:pointcut expression="execution(* com.koreait.app.biz..*Impl.insert(..))" id="logPointcut" />
	<!--설정-->
	<aop:aspect ref="la">
		<aop:after method="insertLog" pointcut-ref="logPointcut"/>
	</aop:aspect>
</aop:config>

 

AOP 설정은 aop:config 태그 안에서 진행하게 되며, 먼저 사용할 메서드를 pointcut 정규식으로 지정한다.

정규식은 execution 안에 작성해야하며 execution(아웃풋 메서드명규칙 인풋) 형식으로 작성하게 된다. 이때 아웃풋을 *로하면 모든 반환타입을 의미하고 인풋을 (..)로 작성하면 모든 인풋타입을 의미한다. 현재 작성된 메서드명을 분석하면 아래처럼 된다.

com > koreait > app > biz > 모든 폴더 > Impl로 끝나는 모든 파일 안의 insert 메서드

 

AOP 대상 설정까지 마쳤으면 aop:aspect 태그 아래에서 언제 해당 메서드를 거칠 지 설정할 수 있다.

aop:aspect에서 ref는 Advice bean객체의 id를 작성하면 된다.

 

여러가지 타이밍을 설정할 수 있는데, 그 중 자주 사용되는 타입은 5가지 정도가 있다.

aop:after 핵심관심 후에
aop:after-returning 핵심관심 반환 후에
aop:after-throwing 핵심관심 에러 발생 후에
aop:around 핵심관심 전후로
aop:before 핵심관심 전에

 

타이밍을 결정했으면 그 타이밍에 거칠 메서드와 핵심관심 대상 메서드의 id를 작성하면 된다.

이후 핵심관심 메서드를 사용해보면 정상적으로 로그가 뜨는 것을 확인할 수 있고, 핵심관심 메서드에는 관련된 설정이 없는 것을 확인할 수 있다.

 

이처럼 AOP는 공통로직을 분리해 관리할 수 있어 응집도가 높아지며, Spring 프레임워크는 IoC도 지원하기 때문에 결합도를 낮출 수 있어 Spring 프레임워크는 유지보수에 용이하다.

 

 

 

참고 블로그 : https://sjh836.tistory.com/157