Spring Boot

AOP 적용 방식

작은별._. 2024. 9. 23. 14:13
728x90

AOP를 사용하면 핵심 기능과 부가 기능이 코드상 완전히 분리되어서 관리됩니다. AOP를 사용할 때 부가 기능 로직은 크게 3가지 방법으로 실제 로직에 추가될 수 있습니다.

  • 컴파일 시점
  • 클래스 로딩 시점
  • 런타임 시점(프록시)

원본 로직에 부가 기능 로직이 추가되는 것 Weaving(위빙) 이라고 합니다. 각 방식에 대해서 이번 포스팅에서 정리해 보았습니다.

 

컴파일 시점 (컴파일 타임 - 위빙)

컴파일을 하면 .java 소스 코드가 컴파일러를 통해 .class 로 변환됩니다. 이렇게 .class 를 만드는 시점에 부가 기능 로직을 추가할 수 있습니다. 이 때는 AspectJ가 제공하는 특별한 컴파일러를 사용해야 합니다. AspectJ 컴파일러는 Aspect를 확인해서 해당 클래스가 적용 대상인지 확인 후, 적용 대상인 경우에 부가 기능 로직을 적용합니다. 즉, 부가 기능 코드가 핵심 기능이 있는 컴파일된 코드 주변에 실제로 붙어 버린다고 생각하면 됩니다.

 

컴파일 시점에 부가 기능을 적용하려면 특별한 컴파일러도 필요하고 복잡하다는 단점이 있습니다.

 


클래스 로딩 시점 (로드 타임 - 위빙)

자바 컴파일이 끝나고 자바의 main 함수를 실행할 때 .class 파일을 JVM 내부의 클래스 로더에 보관합니다. 이때 중간에서 .class 파일을 조작한 다음 JVM에 올릴 수 있습니다. java instrumentation을 검색하면 더 자세한 내용을 확인할 수 있는데, 수많은 모니터링 툴들이 이러한 방식을 사용합니다. 

 

로드 타임 위빙은 자바를 실행할 때 특별한 옵션 (java - javaagent)을 통해 클래스 로더 조작기를 지정해야 하는데, 이 부분이 번거롭고 운영하기 어려운 단점이 있습니다.


런타임 시점 (로드 타임 - 위빙)

런타임 시점은 컴파일도 다 끝나고, 클래스 로더에 클래스도 다 올라가서 이미 자바가 실행되고 난 다음을 의미합니다. 즉, 자바의 main 메서드가 이미 실행된 다음입니다. 따라서 자바 언어가 제공하는 범위 안에서 부가 기능을 적용해야 하고 프록시와 DI, 빈 포스트 프로세서 같은 스프링 관련 개념들을 총 동원해야 합니다. 이렇게 하면 최종적으로 프록시를 통해 스프링 빈에 부가 기능을 적용할 수 있습니다.

 

프록시를 사용하기 때문에 AOP 기능에 일부 제약이 있지만 특별한 컴파일러나, 자바를 실행할 때 복잡한 옵션과 클래스 로더 조작기 설정 없이 스프링만 있으면 얼마든지 AOP를 적용할 수 있습니다.

 

AOP는 메서드 실행 위치뿐만 아니라 생성자, 필드값 접근 지점, static 메서드 접근 지점 등 다양한 위치에 적용할 수 있습니다.

  • AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트코드를 실제 조작하기 때문에 해당 기능을 모든 지점에 다 적용할 수 있습니다.
  • 프록시 방식을 사용하는 스프링 AOP메서드 실행 지점에만 AOP를 적용할 수 있습니다.
    • 프록시는 메서드 오버라이딩 개념으로 동작하기 때문에 생성자나 static 메서드, 필드 값 접근에는 프록시 개념이 적용될 수 없습니다.
    • 프록시를 사용하는 스프링 AOP의 Join point (aop 적용 가능 지점)는 메서드 실행으로 제한됩니다.
    • 프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있습니다.

[참고자료]

김영한, "스프링 핵심 원리 - 고급편 ", 인프런

 

728x90
반응형