일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- dto
- 플로이드 와샬
- 기술면접
- 직무면접
- bottom-up
- 동적계획법
- union-find
- Python
- Django
- BufferedReader
- top-down
- 음수가 포함된 최단경로
- 코딩테스트
- Android Studio
- kmeans
- onclick
- 엔테크서비스
- scikit-learn
- 우선순위큐
- 벨만 포드 알고리즘
- Java
- 거쳐가는 정점
- 최단경로
- disjoint set
- 다익스트라
- Controller
- compiler
- clean code
- spring boot
- 유니온 파인드
- Today
- Total
춤추는 개발자
[Spring] 다양한 관점에서 개발하는 스프링의 AOP - 3 본문
✅ AOP란 무엇인가?
지금까지 비즈니스 로직을 담은 UserService에 트랜잭션을 적용해온 과정을 정리해보겠습니다.
1. 트랜잭션 서비스 추상화
- 문제: UserService가 특정 트랜잭션 기술에 종속된 코드가 돼버림
- 트랜잭션 적용이라는 추상적인 작업 내용은 유지하고, 구체적인 구현 방법을 자유롭게 바꿀 수 있도록 서비스 추상화 기법을 적용
- 인터페이스와 DI를 통해 무엇을 하는지는 남기고, 그것을 어떻게 하는지 분리한 것
- PlatformTransactionManager
2. 프록시와 데코레이터 패턴
- 문제: 여전히 트랜잭션을 적용하는 코드가 비즈니스 로직에 남아있어서 관심사의 분리가 철저하게 이루어지지 않음, 코드 특성상 단순한 추상화와 메서드 추출 방법으로는 분리할 수 없음.
- 투명한 부가기능 부여를 가능하게 하는 데코레이터 패턴 적용
- 클라이언트가 인터페이스와 DI를 통해 접근하도록 설계 및 데코레이터 패턴을 적용해서, 비즈니스 로직을 담은 클래스의 코드에는 영향을 주지 않게 한다. 동시에 트랜잭션이라는 부가기능을 자유롭게 부여할 수 있는 구조로 만듬
- 클라이언트는 프록시 역할을 하는 트랜잭션 데코레이터를 거쳐서 타깃에 접근.
- UserService -> UserServiceTx, UserServiceImpl
3. 다이내믹 프록시와 프록시 팩토리 빈
- 문제: 비즈니스 로직 인터페이스마다 트랜잭션 기능을 부여하는 코드를 넣어 프록시 클래스를 만드는 작업이 발생함. 트랜잭션 기능을 부여하지 않아도 되는 메서드조차 프록시로서 위임 기능이 필요해서 일일이 다 구현해줘야 함.
- 프록시 클래스 없이도 프록시 오브젝트를 런타임 시에 만들어주는 JDK 다이내믹 프록시 기술을 적용. 그리고 이를 추상화한 스프링의 프록시 팩토리 빈을 이용해서 다이내믹 프록시 생성 방법에 DI를 도입.
- 부가기능을 담은 어드바이스와 메서드 선정 알고리즘인 포인트컷은 프록시에 분리되어 여러 프록시에서 공유해서 사용가능.
- ProxyFactoryBean, TransactionAdvice
4. 자동 프록시 생성 방법과 포인트컷
- 문제: 트랜잭션 적용 대상이 되는 빈마다 일일이 프록시 팩토리 빈을 설정해줘야 한다는 부담.
- 스프링 컨테이너의 빈 생성 후처리 기법을 활용. 프록시를 적용할 대상을 일일이 지정하지 않고, 패턴을 이용해 자동으로 선정할 수 있도록, 클래스를 선정하는 기능을 담은 확장된 포인트컷을 사용.
- 최종적으로 포인트컷 표현식을 사용해 깔끔한 방법으로 메서드 선정 대상을 선택.
- DefaultAdvisorAutoProxyCreator, AspectJExpressionPointcut
5. 부가기능의 모듈화
- 지금까지 코드를 분리하고, 한데 모으고, 인터페이스와 DI를 도입하고, 런타임 시에 의존관계를 만들어줌으로써 대부분의 문제를 해결했다.
- 하지만 트랜잭션 경계설정 기느은 다른 모듈의 코드에 부가적으로 부여되는 기능이라는 특징으로 간단하게 분리할 수 없었다.
- 트랜잭션 경계설정 기능을 독립된 모듈로 만들기 위해 DI, 데코레이터 패턴, 다이내믹 프록시, 빈 후처리 기술, 자동 프록시 생성, 포인트컷 등을 활용했다.
- 이러한 방식은 핵심기능을 담당하는 코드 여기저기에 흩어져있는 부가기능을 어떻게 독립적인 모듈로 만들 수 있을까를 고민한 결과다.
✅ AOP: Aspect Oriented Programming
부가기능 모듈을 객체지향 기술에서 주로 사용하는 오브젝트와 다른 이름으로 부르기 시작했다. 그것이 바로 Aspect다. Aspect란, 그 자체로 핵심기능을 담고 있지 않지만, 핵심기능에 부가되어 의미를 갖는 모듈을 의미한다.
부가될 기능을 정의한 코드인 어드바이스와, 어디에 적용할지 결정하는 포인트컷을 함께 갖고 있다. 지금까지 사용한 어드바이저는 단순한 형태의 Aspect라고 볼 수 있다.
Aspect는 단어 의미대로 어플리케이션을 구성하는 한 가지 측면이라고 볼 수 있다. 위 그림에서 왼쪽은 Aspect로 부가기능을 분리하기 전의 상태다. 객체 지향적인 관점에서는 깔끔한 구조처럼 보이지만, 부가기능과 핵심기능이 섞이면서 지저분해졌다. 반면에, Aspect로 핵심기능과 부가기능을 분리했다. 각각 성격이 다른 부가기능들은 다른 면에 존재하며 핵심기능은 온전히 그 기능을 담은 코드로만 존재한다.
물론, 런타임 시에는 왼쪽의 그림처럼 부가기능들이 자기가 필요한 위치에서 다이나믹하게 참여할 것이다. 하지만, 설계와 개발은 오른쪽 그림처럼 다른 특성을 띤 Aspect들을 독립적인 관점으로 작성하게 할 수 있다. 이렇게 어플리케이션의 핵심기능에서 부가기능을 분리하여 독특한 모듈로 만들고 설계, 개발하는 방법을 AOP라고 부른다.
✅ AOP 용어
- 타깃: 부가기능을 부여항 대상 또는 부가기능을 제공하는 프록시 오브젝트
- 어드바이스: 타깃에게 제공할 부가기능을 담은 모듈
- 조인 포인트: 어드바이스가 적용될 수 있는 위치, 스프링의 프록시 AOP에서는 메서드의 실행 단계 뿐이다.
- 포인트컷: 어드바이스를 적용할 조인포인트를 선별하는 작업 또는 그 기능을 정의한 모듈, 결국 클래스를 선정하고 그 안의 메서드를 선정하는 과정을 거치게 된다.
- 프록시: 클라이언트와 타깃 사이에 투명하게 존재하면서 부가기능을 제공하는 오브젝트
- 어드바이저: 어드바이스와 포인트컷을 하나씩 갖고 있는 오브젝트, 어떤 부가기능을 어디서 전달할 것인가를 담고 있는 AOP의 기본 모듈, 스프링의 AOP에서만 사용되는 용어
- 애스펙트: OOP의 클래스처럼 AOP의 기본 모듈, 한개 또는 그 이상의 포인트컷과 어드바이스의 조합으로 만들어지며 보통 싱글톤 형태의 오브젝트로 존재.
이외에도 스프링의 프록시 방식 AOP를 적용하려면 최소한 4가지 빈을 등록해야 한다.
- 자동 프록시 생성기 DefaultAdvisorAutoProxyCreator
- 어드바이스
- 포인트컷 AspectJExpressionPointcut
- 어드바이저 DefaultPointcutAdvisor
'Developer's_til > 스프링 프레임워크' 카테고리의 다른 글
[inflearn] 스프링 핵심 원리 - 기본편 review (0) | 2023.03.04 |
---|---|
[Spring] 트랜잭션으로 알아보는 스프링 AOP (0) | 2021.08.24 |
[Spring] 다양한 관점에서 개발하는 스프링의 AOP - 2 (0) | 2021.08.23 |
[Spring] 다양한 관점에서 개발하는 스프링의 AOP - 1 (0) | 2021.08.23 |
[Spring] 기술의 공통점을 담은 서비스 추상화(PSA) (0) | 2021.08.21 |