티스토리 뷰
AOP를 사용하면 핵심 기능과 부가 기능이 코드상 완전히 분리되어서 관리된다.
그렇다면 AOP를 사용할 때 부가 기능 로직은 어떤 방식으로 실제 로직에 추가되는걸까?
AOP가 적용되는 방식으로는 크게 3가지 방법이 있다.
- 컴파일 시점 : 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함된다. AspectJ를 직접 사용해야 한다.
- 클래스 로딩 시점 : 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함된다. AspectJ를 직접 사용해야 한다.
- 런타임 시점(프록시) : 실제 대상 코드는 그대로 유지된다. 따라서 프록시를 통해 부가 기능을 사용할 수 있다. 스프링 AOP는 이 방식을 사용한다.
컴파일 시점
.java
소스 코드를 컴파일러를 사용해서 .class
를 만드는 시점에 부가 기능 로직을 추가할 수 있다.
이때는 AspectJ가 제공하는 특별한 컴파일러를 사용해야 한다. 컴파일 된 .class
를 디컴파일 해보면 애스펙트 관련 호출 코드가 들어간다. 부가 기능 코드가 핵심 기능이 있는 컴파일된 코드 주변에 실제로 붙어 버린다고 생각하면 된다. AspectJ 컴파일러는 Aspect를 확인해서 해당 클래스가 적용 대상인지 먼저 확인하고, 적용 대상인 경우에 부가 기능 로직을 적용한다.
이렇게 원본 로직에 부가 기능 로직이 추가되는 것을 위빙(Weaving)이라 한다.
컴파일 시점의 단점
컴파일 시점에 부가 기능을 적용하려면 특별한 컴파일러도 필요하고 복잡하다.
클래스 로딩 시점
자바를 실행하면 자바 언어는 .class
파일을 JVM 내부의 클래스 로더에 보관한다. 이때 중간에서 .class
파일을 조작한 다음 JVM에 올릴 수 있다. 자바 언어는 .class
를 JVM에 저장하기 전에 조작할 수 있는 기능을 제공한다. 이 시점에 애스펙트를 적용하는 것을 로드 타임 위빙이라 한다.
클래스 로딩 시점 - 단점
로드 타임 위빙은 자바를 실행할 때 특별한 옵션(java -javaagent
)을 통해 클래스 로더 조작기를 지정해야 하는데, 이 부분이 번거롭고 운영하기 어렵다.
런타임 시점(프록시)
런타임 시점은 컴파일도 다 끝나고, 클래스 로더에 클래스도 다 올라가서 이미 자바가 실행되고 난 다음을 말한다. 자바의 main
메서드가 이미 실행된 다음이기 때문에, 자바 언어가 제공하는 범위 안에서 부가 기능을 적용해야 한다. DI
, BeanPostProcessor
같은 개념들을 사용하면 최종적으로 프록시를 통해 스프링 빈에 부가 기능을 적용할 수 있다.
프록시를 사용하기 때문에 AOP 기능에 일부 제약이 있다. 하지만 특별한 컴파일러나, 자바를 실행할 때 복잡한 옵션과 클래스 로더 조작기를 설정하지 않아도 스프링만 있으면 얼마든지 AOP를 적용할 수 있다.
AOP 적용 위치
AOP는 생성자, 필드 값 접근, static 메서드 접근, 메서드 실행에 적용할 수 있다. 이렇게 AOP를 적용할 수 있는 지점을 조인 포인트(Join point)라 한다.
AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트코드를 실제 조작하기 때문에, 해당 기능을 모든 지점에 다 적용할 수 있다.
프록시 방식을 사용하는 스프링 AOP는 메서드 실행 지점에만 AOP를 적용할 수 있다.
프록시는 메서드 오버라이딩 개념으로 동작한다. 따라서 생성자나 static 메서드, 필드 값 접근에는 프록시 개념이 적용될 수 없다. 또한, 프록시를 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한된다.
프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다.
스프링이 제공하는 AOP는 프록시를 사용한다. 따라서 프록시를 통해 메서드를 실행하는 시점에만 AOP가 적용된다. AspectJ를 사용하면 앞서 설명한 것 처럼 더 복잡하고 더 다양한 기능을 사용할 수 있다.
여기서 "스프링 AOP 보다 더 기능이 많은 AspectJ를 직접 사용해서 AOP를 적용하는 것이 더 좋지않을까?" 하는 의문이 생길 수 있다.
AspectJ를 사용하려면 공부할 내용도 많고, 자바 관련 설정(특별한 컴파일러, AspectJ 전용 문법, 자바 실행 옵션)도 복잡하다. 반면에 스프링 AOP는 별도의 추가 자바 설정 없이 스프링만 있으면 편리하게 AOP 를 사용할 수 있다. 실무에서는 스프링이 제공하는 AOP 기능만 사용해도 대부문의 문제를 해결할 수 있다.(이것만 학습하기에도 양이 엄청나다..)
Reference
김영한. 스프링 핵심 원리 - 고급편. 인프런.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8#
'Spring' 카테고리의 다른 글
[Spring] Advice 종류 (0) | 2022.05.29 |
---|---|
[Spring] AOP 용어 (0) | 2022.05.25 |
[Spring] @Aspect AOP (0) | 2022.05.23 |
[Spring] 스프링이 제공하는 빈 후처리기 (0) | 2022.05.22 |
[Spring] 메시지 컨버터(Message Converter) (0) | 2022.05.21 |
- Total
- Today
- Yesterday
- 알고리즘
- 인프런
- spring boot
- 그리디
- 데이터베이스
- 코틀린
- 구현
- 노마드
- Spring
- 스프링 부트
- MySQL
- 백준
- 코테
- leetcode
- kotlin
- Real MySQL
- 김영한
- mysql 8.0
- 정렬
- Algorithm
- Refactoring
- 스프링
- 파이썬
- 문자열
- 릿코드
- webflux
- 북클럽
- 자료구조
- 노마드코더
- 리팩토링
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |