DesignPattern

AOP 입문자를 위한 기초 개념 : Spring을 사용하지 않는 AOP 구현 방법

Sophie소피 2022. 12. 29. 11:36

AOP란?

관점 지향 프로그래밍이란 OOP로 독립적으로 분리하기

어려운 부가 기능을 모듈화하는 방식이다.

이 글에서 트랜잭션 관리와 같은 부분이 바로 부가 기능 모듈이며,

이를 Aspect라고 한다.

 

AOP는 핵심 비즈니스 로직과 부가 기능

Aspect를 분리하는 등 OOP를 보완하는 역할을 한다.

Cross-cutting-Concern (로그처리, 보안처리, 트렌젝션처리)을

소스코드에 로그처리, 보안처리하는 코드를 다 하나하나 넣어줘야했다.

그러면 필요시에 의해서 하나하나 처리를 해줘야하기 때문에 유지보수가 힘들어진다.

 

과거의 방식을 유지보수에 용이하게 보완하기 위해 등장한 방법이 바로 AOP이다.

Cross-cutting-Concern (로그처리, 보안처리, 트렌젝션처리)과

Core Concern(주업무)을 따로 분리하여 만들어 함수를 호출하는 방식인 것이다.

 

그렇다면 먼저 Spring을 사용하지 않는 AOP 구현 방법 에 대해 알아보도록하자.

 

개발자로서 새로운 관점이 생겨서 기능에 권한을 설정한다거나

혹은 함수가 실행되는데 오래걸려서 실행시간을 찍는 로그를 찍어본다거나

이런 경우를 비슷한 경험해봤을 것이다.

 

 

아래 코드는 해당 소스코드에 실행시간 로그를 찍는 구현 방법을 구현한 것이다. 

과거에는 업무로직과 상관없는 다른 관점으로 만들어지는 코드들을

Core Concern(주업무)의 주요 로직에 코드를 넣어 프로그래밍을 하였다.

이러한 방식이 시간이 지나면서 현실적으로 불가능한 경우가 많을 것이다.

public class NewlecExam implements Exam {
	public int total(){

		long start = System.currentTimeMills();
		SimpleDateFormat dayTime = new SompleDateFormat("yyyy-mm-dd hh:mm:ss");
		String str dayTime.format(new Date(start));
		System.out.println(str);

		int result = kor+eng+math+com;
		
		long end = System.currentTimeMiles();
		
		String message (end-start)+ "ms가 걸림";
		System.out.println(message); 

		return result;

	}
}

 

그렇다면 AOP는 해당소스코드 없이

Cross-cutting-Concern (로그처리, 보안처리, 트렌젝션처리)을 사용하는걸까?

 

첫번째, Core Concern(주업무)의 주요 로직을 분리한다.

public class NewlecExam implements Exam {
	public int total(){

		int result = kor+eng+math+com;
		
		return result;
	}
}

 

두번째, Cross-cutting-Concern (로그처리, 보안처리, 트렌젝션처리)을 분리한다.

		long start = System.currentTimeMills();
		SimpleDateFormat dayTime = new SompleDateFormat("yyyy-mm-dd hh:mm:ss");
		String str dayTime.format(new Date(start));
		System.out.println(str);

		long end = System.currentTimeMiles();
		
		String message (end-start)+ "msr가 걸림";
		System.out.println(message); 

 

세번째, Proxy Class에 분리한 Cross-cutting-Concern (로그처리, 보안처리, 트렌젝션처리) 구현하기

Exam proxy = (Exam) Proxy.newProxyInstance(
    NewlecExam.class.getClassLoader()
    , new Class[]{Eaxm.class}
    , new InvovationHandler(){
			
//주업무를 호출해주는 역할 
    public (Object invoke(Object proxy Method method, Object[] args) throws Throwable{
            return null;
        }
    }
)
int total = proxy.total();
float avg = proxy.avg(); 

 

 

Proxy Class에 Cross-cutting-Concern 구현코드

public static void main(String[]args){
	Exam exam = new NewCalculator();
//Exam을 위한 Proxy를 만든다. 
Exam examproxy = (Exam) Proxy.newProxyInstance(
    NewlecExam.class.getClassLoader(),
    new Class[]{Exam.class},
    new InvocatioHandler(){
        @override
        public Object invoke(Object proxy, Method method, Object[]args) throws Throwable{

//-----------   Cross-cutting-Concern Proxy ---------------//
		long start = System.currentTimeMills();
		SimpleDateFormat dayTime = new SompleDateFormat("yyyy-mm-dd hh:mm:ss");
		String str dayTime.format(new Date(start));
		System.out.println(str);
//---------------------------------------------------------//

        //exam의 메서드를 호출하는 코드 앞뒤로 로그찍는 로직
        Object result = method.invoke(exam, args);

//-----------   Cross-cutting-Concern Proxy ---------------//
		long end = System.currentTimeMiles();
		
		String message (end-start)+ "msr가 걸림";
		System.out.println(message); 
		return result; 
//---------------------------------------------------------//
        }
// Proxy 대신에 사용 
    int result = examProxy.total();
    System.out.println("Total is" + result);
    }
	)
}

순수하게 자바코드로 AOP 를 작성한 코드이다. 

하지만 저 자바코드에서 스프링 기능을 얹게 된다면 어떻게 될까?

Proxy를 결합했다가 분리했다가 할 수는 없을 것이다. 

코드 변경과 수정의 문제가 생기게 되는데 이 문제는 Spring DI (Dependancy Injection) 의존성 주입으로 해결이 가능하다. 

 int result = examProxy.total();