본문 바로가기

IT

스프링 AOP(Aspect Oriented Programming) step1

728x90

이전에 Transactio을 어떻게 로직을 분리하는지 메소드 분리부터, 프록시와 데코레이터패턴, 다이내믹 프록시, 프록시 팩토리 빈, 자동 프록시 생성 순서로 알아보았고 이것은 부가기능의 모듈화가 목적인 것을 파악했다. 결론적으로 AOP를 입문하게 되었다. 

https://sh970901.tistory.com/category/Spring/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EA%B3%BC%20AOP

 

'Spring/트랜잭션과 AOP' 카테고리의 글 목록

 

sh970901.tistory.com

토비의 스프링 3.1을 읽고 해석해서 풀어 쓴 글이다. 아직 이 책이 없다면 필자는 꼭 사서 두고두고 보는 것을 추천한다.

 

AOP : 애스펙트 지향 프로그래밍

애스펙트란 그 자체로 애플리케이션의 핵심기능을 담고 있지는 않지만, 애플리케이션을 구성하는 중요한 한 가지 요소이고 핵심기능에 부가되어 의미를 갖는 특별한 모듈이다. 

애스펙트는 부가될 기능을 정의한 코드인 어드바이스와, 어드바이스를 어디에 적용할지를 결정하는 포인트 컷을 함께  가지고 있다. -> 어드바이저 (애스펙트+어드바이스)

어드바이저는 아주 단순한 형태의 애스펙트라고 볼 수 있다. 

이전에 예시로 설명한 트랜잭션의 경우 트랜잭션 매니저를 설정해 메소드 사이에 commit, rollback 을 추가한 이 부분이 부가기능 즉 어드바이스가 되는 것이고 적용할 클래스, 메소드 등을 필터링하는 것이 포인트 컷이라고 설명했다.

public void upgradeLevels() throws Exception {
	TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
	
	try {
	List<User> users = userDao.getAll();
	for (User user : users){
			if(canUpgradeLevel(user)){
				upgradeLevel(user);
            }
        }

		this.transactionManager.commit(status);
	} catch (Exception e) {
		this.transactionManager.rollback(status);
		throw e
	}
}

이 부분을 어떻게 더 가독성있고 객체지향 원리를 지키는지, 중복된 문제를 어떻게 처리할 것인지 등을 고민하며 이 트랜잭션 로직과 비즈니스 로직을 분리하는 과정을 계속 설명하였고 장단점을 파악했다. 이렇게 애플리케이션의 핵심적인 기능에서 부가적인 기능을 분리해서 애스펙트라는 독특한모듈로 만들어서 설계하고 개발하는 방법을 AOP(Aspect Oriented Programming) 이라고 한다. AOP는 OOP를 돕는 보조적인 기술이지 OOP를 완전히 대체하는 새로운 개념이 아니다. AOP는 애스펙트를 분리함으로써 핵심기능을 설계하고 구현할 때 객체지향적인 가치를 지킬 수 있도록 도와주는 것이라고 보면 된다. 트랜잭션의 경우 핵심 로직 대신 트랜잭션 경계설정이라는 관점에서 바라보고 그 부분을 모듈화하여 집중해서 설계하고 개발할 수 있게 된다는 뜻이다. 이렇게 애플리케이션을 특정한 관점을 기준으로 바라볼 수 있게 해준다는 의미에서 AOP (관점 지향 프로그래밍) 라고 불리게 된 것이다.

 

스프링 AOP는 프록시를 사용해 부가기능을 담은 어드바이스가 적용되는 대상은 오브젝트의 메소드다. 어드바이스가 구현하는 MethodInterceptor 인터페이스는 다이내믹 프록시의 InvocationHandler와 마찬가지로 프록시로부터 메소드 요청정보를 전달받아서 타깃 오브젝트의 메소드를 호출한다. 타깃의 메소드를 호출하는 전후에 다양한 부가기능을 제공할 수 있다. 이 말이 이해가 되지 않는다면 다이내믹 프록시에 대해 다시 공부할 필요가 있다고 생각한다. 

https://sh970901.tistory.com/117

 

스프링 트랜잭션 (Spring Transaction) step3 : 다이내믹 프록시

이전 step2 에서 비즈니스 로직과 트랜잭션 로직을 분리하기 위해 UserService(인터페이스) -> UserServiceTx(트랜잭션 로직) -> UserServiceImpl(비즈니스 로직)을 구현했다. 이 구성에는 번거러운 코드 작성과

sh970901.tistory.com

 

독립적으로 개발한 부가기능 모듈을 다양한 타깃 오브젝트의 메소드에 다이내믹하게 적용하기 위해 가장 중요한 역할을 하는 것이 프록시이다. 그래서 스프링 AOP는 프록시 방식의 AOP이다. AOP가 모두 프록시 방식은 아니다. AOP 프레임워크 중 AspectJ는 AOP의 원조이며 가장 강력한 기능을 제공하지만 프록시 처럼 간접적인 방법을 사용하지 않는다. 컴파일된 타깃의 클래스 파일 자체를 수정하거나 JVM에 로딩되는 시점을 가로채서 바이트코드를 조작하는 방식을 사용해 오브젝트의 생성 뿐아닌 필드 값의 조회와 조작, 스태틱 초기화 등의 다양한 작업에 부가기능을 제공해준다.  

 

AOP의 용어

 

타깃: 타깃은 부가기능을 부여할 대상이다. 핵심기능을 담은 클래스일 수도 있지만 경우에 따라서는 다른 부가기능을 제공하는 프록시 오브젝트일 수도있다. 

 

어드바이스: 타깃에게 제공할 부가기능을 담은 모듈이다. 어드바이스는 여러 가지 종류가 있다. MethodInterceptor처럼 메소드 호출 과정에 전반적으로 참여하는 것도 있지만 예외가 발생했을 때만 동작하는 어드바이스처럼 메소드 호출 과정의 일부에서만 동작하는 어드바이스도 있다.

 

조인포인트: 어드바이스가 적용될 수 있는 위치를 말한다. 스프링 AOP에서 조인포인트는 메소드의 실행 단계이다.

 

포인트컷: 어드바이스를 적용한 조인포인트를 선별하는 작업 또는 그 기능을 정의한 모듈을 말한다. 스프링 AOP의 조인포인트는 메소드의 실행이므로 메소드를 선정하는 기능을 갖고 있다.

 

프록시: 클라이언트와 타깃 사이에서 투명하게 존재하면서 부가기능을 제공하는 오브젝트다. 

 

어드바이저: 포인트컷과 어드바이스의 조합이다. 스프링 AOP에서만 사용되는 용어로 일반적인 AOP에서는 사용되지 않는다.

 

애스펙트: OOP의 클래스와 마찬가지로 AOP의 기본 모듈이다. 한 개 또는 그 이상의 포인트컷과 어드바이스의 조합으로 만들어지는 어드바이저로 보통 싱글톤 형태의 오브젝트로 존재한다. 

 

 

스프링의 프록시 방식 AOP를 적용하려면 최소 네가지 빈을 등록해야 한다.

 

자동 프록시 생성기 : 스프링의 DefaultAdvisorAutoProxyCreator 클래스를 빈으로 등록한다.

 

어드바이스: 부가기능을 구현한 클래스를 빈으로 등록

 

포인트컷: 스프링의 AspectJExpressionPointcut을 빈으로 등록한다.

 

어드바이저: 스프링의 DefautPointcutadvisor 클래스를 빈으로 등록해서 사용한다. 자동 프록시 생성기에 의해 자동으로 검색되어 사용된다. 

 

이중에서 부가기능을 담은 코드로 만든 어드바이스를 제외한 나머지 세 가지는 모두 스프링이 직접 제공하는 클래스를 빈으로 등록하고 프로퍼티 설정만 해준 것이다. 이 세가지 클래스를 이용해 선언하는 빈은 AOP를 적용하면 반복적으로 등장하게 된다. 

 

 

 

 

 

 

 

 

 

참고 자료 - 토비의 스프링 3.1 | 저자 이일민