[Spring] AOP 프로그래밍
AOP(Aspect Oriented Programming)
기존의 oop(객체 지향 프로그래밍) 언어 에서는 공통 관심 사항에 해당하는 공통 코드를 완벽하게 독립적인 모듈로써
분리해내는게 어려운데, 이러한 단점을 보완한 개념 => 핵심 사항과 공통 관심 사항을 분리하여 구현
문제를 바라보는 관점을 기준으로 프로그래밍을 하는 기법을 말한다.
AOP는 문제를 해결하기 위한 핵심사항과 코드 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 어려 코드에 쉽게 적용할 수 있도록 도와준다.
AOP의 핵심 개념
: 관심 분리 (Separation of Concerns)
공통 관심 사항(Cross-cutting Concerns)
- 메소드마다 공통으로 등장하는 로깅, 예외, 트랙잭션 처리 등의 코드들
핵심 사항(Primary(Core) Concerns)
- 사용자의 요청에 따라 실제로 수행되는 핵심 비즈니스 로직
만약 공통 관심 사항, 핵심사항 두 가지 관심을 완벽히 분리할 수 있다면,
우리가 구현하는 메소드 내부 코드는 실제 비즈니스 로직만으로 구성될 수 있기 때문에
더 간결하고, 응집도가 높은 코드를 유지하는게 가능해진다.
기존의 OOP (Object-Oriented Programming, 객체지향프로그래밍) 언어에서는 . AOP는 핵심사항과 공통 관심 사항을 별도의 코드로 구현해서 최종적으로 이 둘을 조합하여 완성한다.
AOP의 장점
- 전체 코드에 흩어져 있는 공통 관심 사항이 하나의 장소의 집중이 된다는 점
- 서비스 모듈이 자신의 주요 관심 사항(핵심 사항)에 대한 코드만 집중하고, 그 외의 공통 관심 사항은 모두 빠지므로 코드가 깔끔해진다는 점.
AOP 주요 용어
핵심 관심 사항 | 비즈니스 로직(주된 업무) |
공통 관심 사항 | 부가적인 업무(보조 업무) - 횡단 관심 사항 공통 관심 사항은 누군가에게 맡겨 버리는 것이 좋다 |
code | 핵심 관심 사항을 구현한 내용 |
Advice | 공통 관심 사항을 구현한 코드 공통 관심 사항 내용을 정의하고 언제 그 작업을 수행할지를 정의하는 것을 말함 즉, 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의하고 있어야 함 |
Aspect | 무엇을 언제 어디서 할지 즉, 필요한 정보가 정의되어 있음 즉, 여러 객체에 공통으로 적용되고 있는 공통 관심 사항을 말함 트랜잭션이나 보안, 로그들이 좋은 예 |
JoinPoint | Advice가 적용될 위치(메서드 호출) Code와 Advice를 연결해주는 설정 정보를 말함 |
PointCut | JoinPoint의 부분 집합으로써 실제 Advice가 적용되는 JoinPoint를 말함 스프링에서는 정규 표현식이나 AspectJ 문법을 이용하여 정의함 |
Weaving | Code, Advice, PointCut 등을 조합하여 애플리케이션을 만들어 가는 과정 |
* 스프링은 자체적인 프록시(대행) 기반의 AOP를 지원
- 스프링은 공통 관심 사항(Aspect)의 적용 대상이 되는 객체에 프록시를 만들어서 제공을 하며,
대상 객체를 사용하는 코드는 대상 객체에 직접 접근하기 보다는 프록시를 통해서 간접적으로 접근을 함
스프링에서 AOP를 구현하는 방법
- 설정 파일을 이용하는 방법(XML 기반의 구현 방법)
- 애노테이션을 이용하는 방법(@AspectJ 애노테이션 기반의 AOP 구현)
- 스프링 AOP 사용 시 필요한 라이브러리 등록(pom.xml)
* artifactId가 aspectjweaver 인 라이브러리를 등록해야 함.
- 스프링 AOP 프록시 사용 시 필요한 라이브러리 등록(pom.xml)
* artifactId가 cglib 인 라이브러리를 등록해야 함.
- 공통 기능 클래스 제작 - Advice 역할을 하는 클래스
XML(설정 파일을 이용하는 방법) 파일에서 Advice 종류
<aop:before> | 핵심 기능이 실행되기 전에 Advice(공통 관심 사항)를 실행 코드의 실행 자체에는 관여할 수 없음. |
<aop:after-returning> | 정상적으로 핵심 기능이 실행된 이후에 Advice(공통 관심 사항)를 실행 모든 실행이 정상적으로 이루어진 후에 동작하는 코드임. |
<aop:after-throwing> | 핵심 기능이 실행 중에 Exception이 발생 시 Advice(공통 관심 사항)를 실행 예외가 발생한 후에 동작하는 코드임. |
<aop:after> | 핵심 기능이 실행 후에 Advice(공통 관심 사항)를 실행. ==> Exception 이 발생하더라도 정상적으로 실행되거나 예외가 발생했을 때 구분 없이 실행되는 코드임. |
<aop:around> | 핵심 기능 실행 전/후 및 Exception 발생 시 Advice(공통 관심 사항)를 실행. ==> 가장 많이 사용됨. |
Aspect PointCut 표현식
- PointCut 을 지정할 때 사용하는 표현식으로 AspectJ 문법을 사용한다.
PointCut으로 표현할 수 있는 명시자에는 여러 종류가 있지만, 일반적으로 가장 많이 사용하는 명시자는 execution 명시자이다. 그 외에도 within, bean 명시자가 있다.
※ execution 명시자 : Advice를 적용할 메서드를 명시할 때 사용함
- * : 모든
- . : 현재
- .. : 0개 이상
예시)
* execution(public void get*(..))
==> public void 이고, 메서드 이름이 get으로 시작하는 메서드이고, 인자가 있는 경우
* execution(* con.test.aop.*.*())
==> com.test.aop. 패키지의 모든 클래스에 파라미터(인자)가 없는 모든 메서드
* execution(* com.test.aop..*.*())
==> com.test.aop 패키지 및 com.test.aop 패키지의 하위 패키지의 모든 클래스의 파라미터(인자)가 없는 모든 메서드
* execution(* com.test.aop.Staff.*())
==> com.test.aop 패키지 안의 Staff 클래스 안에 파라미터(인자)가 없는 모든 메서드
AOP 라이브러리 추가
AOP를 적용하기 위해서는 pom.xml 파일에 AOP 관련 라이브러리를 추가해야 한다.
여기서 Aspectjweaver, cglib 라이브러리 태그 다운
각각 태그 다운 받아서 pom.xml에 라이브러리 추가
<!-- Spring AOP Aspectjweaver 라이브러리 -->
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
<!-- Spring AOP cglib 라이브러리 : 동적으로 자바 클래스의 프록시를 생성해주는 라이브러리 -->
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
이외에도 Spring JDBC, Connection Pool 라이브러리가 추가되어 있다.
저장한 뒤, "Maven Dependencies" 로 가서 아래와 같이 라이브러리가 추가되었는지 확인
설정 파일을 이용하는 방법(XML 기반의 구현 방법)
/*
* 남자(청소년)
* - 학교 수업 후 집에 와서 문을 열고 집에 들어갑니다. ==> 공통 관심 사항(이전)
* - 컴퓨터로 게임을 합니다. ==> 핵심 기능
* - 잠을 잡니다. ==> 공통 관심 사항(이후)
* - 화재 발생 : 119에 신고 ==> 공통 관심 사항(이후-예외)
* - 아침에 일어나서 문을 열고 집을 나옵니다. ==> 공통 관심사항(이후)
*/
package com.sist.aop02;
public interface Person {
public void doSomething();
}
package com.sist.aop02;
public class Boy implements Person {
@Override
public void doSomething() { // 핵심 사항
System.out.println("컴퓨터로 게임을 합니다.");
}
}
애노테이션을 이용하는 방법(@AspectJ 애노테이션 기반의 AOP 구현)
공통 기능 클래스 제작하는 방법 - Advice 역할을 하는 클래스