본문 바로가기
코딩도전기/Spring

AOP - Proxy Pattern

by 코도꼬마 2023. 12. 30.

AOP(Aspect Oriented Programming)

  • 관점 지향 프로그래밍
  • 여러 메서드에 중복되어 나타나지만 핵심로직이라고 할 수 없는 부가 기능을 cross-cutting concerns(횡단관심사, 흩어진관심사) 로 보고 이를 모듈화하는 것

 

프록시패턴(Proxy Pattern)

프록시(Proxy)를 번역하면 대리자, 대변인의 의미를 갖고 있다. 대리자, 대변인은 누군가를 대신해서 그 역할을 수행하는 존재이다. 이는 프로그램에도 똑같이 적용된다. 즉, 프록시에게 어떤 일을 대신 시키는 것이다.

어떤 객체를 사용하고자 할때, 객체를 직접적으로 참조하는 것이 아닌 해당 객체를 대항하는 객체를 통해 대상 객체에 접근하는 방식을 사용하면 해당 객체가 메모리에 존재하지 않아도 기본적인 정보를 참조하거나 설정할 수 있고, 실제 객체의 기능이 필요한 시점까지 객체의 생성을 미룰 수 있다.


사진출처: 위키백과

[프록시 패턴의 장단점]

프록시패턴 장점

  • 사이즈가 큰 객체가 로딩되기 전에도 프록시를 통해 참조를 할 수 있다.
  • 실제 객체의 public, protected 메소드를 숨기고 인터페이스를 통해 노출시킬 수 있다.
  • 로컬에 있지 않고 떨어져있는 객체를 사용할 수 있다.
  • 원래 객체에 접근에 대해 사전처리를 할 수 있다.

프록시패턴 단점

  • 객체를 생성할 때 한 단계를 거치게 되므로, 빈번한 객체 생성이 필요한 경우 성능이 저하될 수 있다.
  • 프록시 내부에서 객체 생성을 위해 스레드가 생성, 동기화가 구현되어야 하는 경우 성능이 저하될 수 있다.
  • 로직이 난해해져 가독성이 떨어질 수 있다.

 

참고블로그

 

JAVA AOP를 구현하는 3가지 방법

  • JDK dynamic proxy, CGLib, AspectJ 이다.

 

JDK dynamic proxy, CGLib

  • 완전한 AOP 솔루션은 아니지만 프록시 패턴으로 작동하며 AOP기능을 구현할 수 있다. Runtime Weaving을 지원한다.

 

AspectJ

  •  AOP를 자바에서 사용하기 위한 구현체
  • 완전한 AOP 솔루션을 제공하는 것이 목표(사실상 자바 표준)
  • Compile Time Weaving, Load Time Weaving, Post-compile weaving(컴파일 후 위빙)을 지원

 

Weaving

  • 모듈화한 부가 기능을 타켓에 적용해 핵심 기능과 연결하는 과정
  • RTW, CTW, LTW 3가지가 있다.

 

  • Runtime Weaving(RTW)
    • 프록시 패턴을 활용한 위빙 방식
    • Proxy객체를 생성해 실제 타깃 오브젝트의 변형없이 런타임 중 메서드 호출이 일어나는 시점에 위빙을 수행
    • 메소드 호출에 대해서만 어드바이스를 적용 할 수 있다는 단점이 있다.
  • Compile Time Weaving(CTW)
    • 특수한 컴파일러를 활용해 컴파일 과정에서 바이트 코드 조작을 통해 Advisor 코드를 직접 삽입하여 위빙을 수행
    • AspectJ에는 AJC (AspectJ Compiler)라는 컴파일러가 있다.
  • Load Time Weaving(LTW)
    • java 파일을 컴파일한 결과물인 자바 클래스가 JVM에 로드될 때 바이트 코드 조작을 통해 위빙되는 방식
    • RTW처럼 소스파일과 클래스 파일에 조작을 가하지 않아 컴파일 시간은 상대적으로 CTW보다 짧다.
    • 하지만 오브젝트가 메모리에 올라가는 과정에서 위빙이 일어나기 때문에 런타임 시, 시간은 CTW보다 상대적으로 느리다.
  • Post-Compile Weaving
    • 컴파일 후 생성된 class파일을 바이트코드 조작을 통해 위빙하는 방식

 

성능 차이

CTW > LTW > RTW 순이다. 역시 컴파일 타임 위빙이 가장 빠르다.

 

spring AOP에서는 인터페이스 유무에 따라 인터페이스 기반의 프록시 생성 시 Dynamic Proxy를 사용하고 인터페이스 기반이 아닐 시 CGLib을 사용하는데 spring boot AOP에서는 CGLib을 default로 사용

 

JDK Dynamic Proxy와 CGLib

Dynamic Proxy와 CGLib은 모두 런타임 위빙 방식이며 프록시 패턴으로 동작한다. 따라서 메서드 실행 시에만 위빙이 가능하다. 그래서 Dynamic Proxy와 CGLib를 사용하는 스프링 AOP도 메서드 실행 조인포인트만 지원한다.

Proxy Pattern이란?

프록시 패턴이란 소프트웨어 디자인 패턴 중 하나로 오리지널 객체(Real Object) 대신 프록시 객체(Proxy Object)를 사용해 로직의 흐름을 제어하는 디자인 패턴이다.

 

Dynamic Proxy와 CGLib는 기본적으로 프록시 패턴으로 동작하여 원래 소스코드를 수정하지 않고 프록시 객체를 생성하여 흐름을 제어해 기능을 삽입할 수 있다. 오리지널 객체의 메서드 호출 결과를 바꿀 순 없다.

 

JDK Dynamic Proxy

JDK 에서 제공하는 Dynamic Proxy는 Interface를 기반으로 Proxy를 생성해주는 방식이다.
Interface를 기반으로 Proxy를 생성해주기 때문에 인터페이스의 존재가 필수적이다.

자바에서는 리플렉션을 활용한 Proxy 클래스를 제공해주고 있다.
Java.lang.reflect.Proxy 클래스의 newProxyInstance() 메소드를 이용해 프록시 객체를 생성한다.

 

Reflection이란?

  • 구체적인 클래스 타입을 알지 못해도 그 클래스의 정보(메서드, 타입, 변수 등등)에 접근할 수 있게 해주는 자바 API
  • 자바에서는 JVM이 실행되면 사용자가 작성한 자바 코드가 컴파일러를 거쳐 바이트 코드로 변환되어 static 영역에 저장
  • Reflection API는 이 정보를 활용해 필요한 정보를 가져온다.
  • 자바의 Reflection API는 값비싼 API이기 때문에 Dynamic Proxy는 리플렉션을 하는 과정에서 성능이 좀 떨어진다는 단점이 있다.

 

CGLib

  • JDK Dynamic Proxy와는 다르게 인터페이스가 아닌 클래스 기반으로 바이트코드를 조작하여 프록시를 생성하는 방식
  • CGLib은 바이트코드 조작을 위해 ASM이라는 자바 바이트코드 조작 및 분석 프레임워크를 사용한다. ASM을 통해 클래스를 동적으로 생성하거나 수정한다.
  • 인터페이스가 아닌 클래스를 대상으로 동작 가능하고 바이트코드를 조작해 프록시를 만들기 때문에 Dynamic Proxy에 비해 성능이 우수하다는 장점이 있지만 Extends(상속) 방식을 이용해서 Proxy화 할 메서드를 오버라이딩하는 방식인만큼 final이나 private와 같이 상속된 객체에 오버라이딩을 지원하지 않는 경우 Proxy에서 해당 메소드에 대한 Aspect를 적용할 수 없다.

참고 블로그

 

JDK Dynamic Proxy와 CGLib를 알아보자 #2

Dynamic Proxy와 CGLib을 실습해보며 AOP를 이해해보았습니다.

velog.io

 

AspectJ

  • AOP를 자바에서 사용하기 위한 구현체
  • 완전한 AOP 솔루션을 제공하는 것이 목표
  • 여러 구현체가 있는데 사실상 자바 표준이라고 한다.
  • Dynamic Proxy나 CGLib처럼 런타임 위빙 방식의 프록시 패턴으로 동작해 간접적인 방법으로 AOP를 구현하는 것이 아니라 Compile Time Weaving, Load Time Weaving, Post-compile weaving(컴파일 후 위빙)을 지원하여 컴파일 시점이나 클래스파일이 로드되는 시점에 바이트코드를 조작하여 위빙을 해버린다.
  • Spring의 AOP도 포인트컷 표현식 사용시 AspectJ의 AspectHExpressionPointcut를 차용해서 사용할만큼 매우성숙하고 발전한 AOP 기술이다.

 

AOP 용어

Advice

  • 조인 포인트에 삽입되어져 실질적으로 동작하는 코드를 Advice라고 한다.

JoinPoint

  • 클래스의 인스턴스 생성 시점', '메소드 호출 시점(앞, 뒤 등)', '예외 발생 시점'과 같이 특정 시점을 조인포인트라고 한다.
    • @Around
    • @Before
    • @After
    • @AfterThrowing
    • @AfterReturning

 

Pointcut

  • JoinPoint를 적용할 영역을 지정한다.

 

Aspect

  • 여러 객체에 공통으로 적용되는 공통 관심 사항을 Aspect라고 한다.

 

Target

  • 우리가 위빙할 대상을 Target이라고 한다.

 

참고 블로그

 

Intro To AspectJ #3

AspectJ를 자바에서 실습해보고 정리하였습니다.

velog.io

 

관련 블로그

 

서비스 구현 시 인터페이스를 구현하는 형태로 하는 이유 (spring AOP)

의문점이였던 스프링에서 서비스 구현 시 인터페이스를 구현하는 형태로 하는 이유를 알아보았습니다.

velog.io

 

'코딩도전기 > Spring' 카테고리의 다른 글

Spring 교육  (0) 2024.01.18
Transaction  (0) 2023.12.30
CODO Day46_Spring(Paging)  (0) 2023.04.07
CODO Day45_Spring(AJAX)  (0) 2023.04.05
CODO Day44_Spring(PhotoBoard)  (0) 2023.04.04