AOP - 02. 간단한 AOP 만들어보기

Seok-Hyun Lee·2022년 5월 31일
0

AOP

목록 보기
2/3

AOP 구현

오늘은 간단하게 AOP 개념을 다시 떠올려보면서 적용해보는 글을 공유하려고 해요

우선, 저번 시간에 AOP 가 아래와 같이 어떤 역할에 대해 개발하는지 그 관점을 구분 짓는 것이라 하였는데요

  1. 사용자가 업무에 필요로 하는 역할
  2. 이 역할을 대상으로 부가적인 행위를 수행하는 역할

이를 한 번 만들어보도록 하겠습니다.

이전 포스트의 예시를 빌려서,
제가 만든 노래를 부를 가수를 찾는 과정에 있다고 할게요

class RnbSinger implements Singer {
	@Override
    public void sing(){
        System.out.println("RnB Singer Singing");
    }
}

class PopSinger implements Singer {
	@Override
    public void sing(){
        System.out.println("Pop Singer Singing");
    }
}

이렇게 두 명의 가수가 있다고 할게요

그런데 저는 괴짜 작곡가라 이 두 가수가 노래의 시작과 끝을 정확하게 맞추는지 확인하고 싶어서
노래를 부르는 순간과 끝나는 순간의 시간을 남기고 싶어요
그럼, 이렇게 만들 수 있겠죠?

class RnbSinger implements Singer{
	@Override
    public void sing(){
    	System.out.println(LocalDateTime.now()); // 추가
        System.out.println("RnB Singer Singing");
        System.out.println(LocalDateTime.now()); // 추가
    }
}

class PopSinger implements Singer{
	@Override
    public void sing(){
    	System.out.println(LocalDateTime.now()); // 추가
        System.out.println("Pop Singer Singing");
        System.out.println(LocalDateTime.now()); // 추가
    }
}

이렇게 되면 저희는 아래와 같은 문제에 당면해요
1. 노래 부르는 역할과는 상관없는 기능이 노래 부르는 행위에 포함
2. 시간 측정 코드의 중복
3. 시간 측정 방법이 틀렸을 때 수정의 번거로움

그리고 코드만 봤을 때도 마치 각 가수들이 자신이 노래를 부를 때
스스로가 시간을 측정하는 것과 같이 보이죠?

그래서 이걸 해결하기 위해 이렇게 나눠볼게요

class RnbSinger implements Singer {
	@Override
    public void sing(){
        System.out.println("RnB Singer Singing");
    }
}

class PopSinger implements Singer {
	@Override
    public void sing(){
        System.out.println("Pop Singer Singing");
    }
}

// AOP 를 위해 추가한 클래스
class Proxy {
	private Singer singer;
    
    public Proxy(Singer singer){
    	this.singer = singer;
    }
    
    // AOP 를 위한 메소드
    public void sing(){
    	System.out.println(LocalDateTime.now());
    	this.singer.sing();
        System.out.println(LocalDateTime.now());
    }
}

위와 같이 Proxy 라는 클래스가 새롭게 생겼고,
RnbSinger 와 PopSinger 는 가장 첫번째의 모습으로 돌아가서 본연의 업무 관련 코드만 가지고 있죠

public class Main {
	public static void main(String[] args) {
    	Singer singer = new RnbSinger();
    	Proxy proxy = new Proxy(singer);
        proxy.sing();
    }
}

이를 통해 저희는 어떤 가수가 오더라도 자신이 노래 부르는 것에만 집중하게 만드는 한편,
시간 측정은 어떤 가수가 오더라도 가수는 신경쓸 필요 없이 가수 클래스 외부에서 진행할 수 있게 되었습니다.

이때 이렇게 사용된 Proxy(프록시) 는 공통적인 부가적인 기능을 수행하기 위해 핵심 기능을 위임받은 객체이고 AOP 에서 이러한 의미로 통용됩니다.

마무리

지금까지 런타임에 생성되는 프록시 객체가 핵심 기능이외의 공통적인 부가기능을 수행하게 만들어보았습니다.
왜 AOP 가 중요한지, 그리고 어떤 상황에 활용되는 건지 조금은 감이 오셨나요?
(그렇다면 다행입니다 ㅎㅎ)

그런데 사실 AOP 를 만드는 방법은 3가지가 있어요
1. 컴파일 시점에 공통 기능 코드를 핵심 기능 코드에 삽입하는 방법
2. 클래스 로딩 시점에 공통 기능을 핵심 기능 바이트 코드에 삽입하는 방법
3. 런타임에 프록시 객체를 생성해서 핵심 기능에 공통 기능을 삽입하는 방법

그래서 다음 시간에는,
컴파일 시점과 클래스 로딩 시점에는 어떻게 AOP 가 적용되는지 공부하고 공유드리도록 하겠습니다!

profile
Arch-ITech

0개의 댓글