Spring : 관점 지향 프로그래밍(AOP)

관점 지향 프로그래밍(AOP : Aspect-Oriented Programming)

우선 AOP는 기존의 OOP(Object-Oriented Programming, 객체 지향 프로그래밍)를 보완하는 개념으로, OOP에서는 해결하기 어려운 문제들을 보다 쉽게 해결할 수 있게 도와주는 개념이다.

AOP는 관점을 기준으로 묶어 개발하는 방식을 의미하며, 여기서 관점(aspect)이란 어떤 기능을 구현할 때 ‘핵심 기능’과 ‘부가 기능’으로 구분해 각각을 하나의 관점으로 보는 것을 의미한다.

’핵심 기능’은 우리가 적용하고자 하는 핵심 비즈니스 로직이다.

‘부가 기능’은 횡단적 관심사항 (Cross-Cutting Concerns)이라고도 하며 핵심 기능을 수행하기 위해서 행해지는 로깅, 트랜잭션 관리, 보안, DB연결, 파일 입출력 등의 기능을 말한다.

AOP는 프록시 패턴을 기반으로 구현되며, 부가 기능을 핵심 기능 메소드 실행의 전후 또는 예외 발생 시점에 넣을 수 있다.

 

AOP 구현 방법

  1. 컴파일 시점에 삽입 : 컴파일 시점 적용 방식은 AspectJ 컴파일러가 일반 .java 파일을 컴파일할 때 부가기능을 넣어서 .class 파일로 컴파일해주는 것을 의미한다. 이 동작을 에스팩트와 실제 코드를 연결하는 **위빙(weaving)**이라고 부른다.
  2. 컴파일된 클래스를 로딩하는 시점에 삽입 : JVM내 클래스로더에 .class 파일을 올리는 시점에 바이트 코드를 조작해 부가기능 로직을 추가하는 방식이다.
  3. 프록시 패턴을 이용한 방식 : 컴파일, 클래스 로딩, main() 메서드의 실행 이후에 자바가 제공하는 범위내에 부가 기능을 적용하는 방식이다. 이미 런타임 중이라 코드를 조작하기 어려워 스프링, 컨테이너, DI, 빈 등 여러 개념과 기능을 총동원하여 프록시를 통해 부가 기능을 적용하는 방식이다. 프록시는 메서드 실행 시점에서만 다음 타겟을 호출할 수 있기 때문에, 런타임 시점에 부가기능을 적용하는 방식은 메서드의 실행 지점으로 제한된다.

 

AOP 용어 및 개념

● Joinpoint : ‘클래스의 인스턴스 생성 시점’, ‘메소드 호출 시점’ 및 ‘예외 발생 시점’ 과 같이 어플리케이션을 실행할 때 특정 작업이 시작되는 시점
● Weaving : 어드바이스를 핵심 로직 코드에 삽입하는 것
● Target : 핵심 로직을 구현하는 클래스
● Aspect : 여러 객체에 공통으로 적용되는 공통 관점 사항
● Advisor : 어드바이스와 포인트컷을 하나로 묶어 취급한 것
● Pointcut : 여러 개의 조인포인트를 하나로 결합한(묶은) 것
● Advice : 조인포인트에 삽입되어 동작할 수 있는 코드

Advice Type 설명
Before 조인포인트 실행 이전에 실행, 일반적으로 리턴타입 void
After returning 조인포인트 완료후 실행 (ex. 메서드가 예외없이 실행될 때)
After Throwing 메서드가 예외를 던지는 경우 실행
After (finally) 조인포인트의 동작과 관계없이 실행
Around 메서드 호출 전후에 수행(조인포인트 실행 여부 선택, 반환 값 변환, 예외 변환, try~catch~finally 구문 처리 가능 등), 가장 강력한 어드바이스이다.

 

AOP 관련 예제 (로그인)

AOP 의존성 추가

Maven (pom.xml)

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

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
</dependency>

 
Gradle (build.gradle)

implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.aspectj:aspectjweaver:1.9.19'

 

핵심 기능

package business;

import org.springframework.stereotype.Service;

@Service
public class ImportantService {
	public void process() {
		System.out.println("핵심 기능 수행");	
	}
}

 

부가 기능

package aspect;

import java.util.Scanner;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component // @Aspect는 객체를 만들어 주지 않으므로 @Component까지 걸어줌
public class LoginAspect {
	
	@Around("execution(* business.*.*(..))")
	public Object login(ProceedingJoinPoint joinPoint) throws Throwable {
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("핵심 기능 전 로그인");
		System.out.print("ID : ");
		String id = scanner.nextLine();
		
		System.out.print("PW : ");
		String pw = scanner.nextLine();
		
		if(!id.equals("AOP") || !pw.equals("123")) {
			System.out.println("로그인 실패");
			return null;
		} else {
			System.out.println("로그인 성공");
		}
		
		Object object = joinPoint.proceed(); // 핵심 기능 실행
		
		System.out.println("핵심 기능 종료");
		
		return object;
	}
}

 

💡 관점 지향 프로그래밍(AOP)
“공통의 부가 기능을 모듈화하여 핵심 비즈니스 로직 개발 중에 부가 기능이 필요할 경우 그 지점에 밀어 넣는 것이다.”
“AOP를 통해 로깅, 트랜잭션 관리, 보안 등과 같은 부가 기능을 애플리케이션의 다른 부분에 영향을 주지 않고 분리하여 관리할 수 있다.
“애플리케이션의 유지보수성과 재사용성을 향상시키는 데 큰 도움을 준다”

 

Reference

🙏 kai6666.log : [Spring] Spring AOP 개념

🙏 F-LAB : 스프링 AOP의 이해와 실제 적용 사례

🙏 새로비 : [Spring] 스프링 AOP (Spring AOP) 총정리 : 개념, 프록시 기반 AOP, @AOP