article thumbnail image
Published 2023. 6. 28. 19:38

 

 

OOP 란?

=> 실제 사물을 프로그래밍으로 옮겨와 모델링하는 것

관심사 분리의 디자인 원칙을 준수해야 함

OOP 모듈화의 핵심 단위 : 클래스

 

OOP란? (현재 비공개 포스팅)

모듈
특정 기능별로 나누어지는 프로그램 덩어리

 

💡oop의 문제 

비지니스 클래스에 핵심 관심사와 횡단 관심사 공존

코드 복잡도 증가시 비즈니스 코드 파악이 어렵고, 횡단 관심사의 모듈화가 어려움

=> AOP등장

 

 

AOP  Aspect-Oriented Programming => 관점 지향 프로그래밍
스프링 DI 가 의존성(new) 에 대한 주입이라면
스프링 AOP 는 로직(code) 주입이라고 볼 수 있습니다.

 

 

어떤 작업을 하던 공통적으로 나타나는 코드 => 횡단관심사항

로깅, 보안, 트랜잭션, 로그 추적 로직 등

 

핵심 기능,객체가 제공하는 고유의 기능 => 핵심관심사항

결제 기능, 알림 기능 등

 

코드 = 횡단관심사항 + 핵심관심사항

 

 

로직(code) 주입을 한다면 어디에 주입할 수 있을까요?

객체지향에서 code 가 있는 곳은 당연히 메서드 안!!!

 

 

 

그럼 메소드에서 코드를 주입할 수 있는 곳은 몇 군데 일까요?

 

 

 

정답은 5군데~~~!!!

 

Around,

Before,

After(finally),

AfterReturning,

AfterThrowing

 

사실 @Around만 있어도 모든 기능 수행 가능하지만 고려해야할 사항이 있을 때, 정상적으로 작동이 되지 않는 경우 있음
@Before / @After 과 같은 어드바이스는 기능은 적지만 코드도 단순하고, 원하는 대로 작동하며 각각이 애너테이션만 봐도 어떤 일을 하는지 명확하게 파악 가능
=>좋은 설계는 @Around만 사용하는 것보다제약을 가지더라도 문제 자체가 발생하지 않도록 역할을 명확하게 하여 실수를 사전에 방지하는 것

 

스프링 AOP 를 통해서 어떻게 횡단관심사항을 분리해 낼 수 있는지, 

분리된 횡단관심사항(로직)을 어떻게 실행 시간에 메서드에 주입한 효과를 내는지 알아볼 것!

 

 

AOP

OOP를 적용하여도 핵심기능에서 부가기능을 쉽게 분리된 모듈로 작성하기 어려운 문제점을 AOP가해결해 준다

 

관심사(기능)의 분리와 핵심 관심사에서 횡단 관심사를 분리하여 분리한 부가 기능을 Aspect라는 모듈 형태로 만들어 설계/개발 하는 방법 => 객체 지향적 가치 ⬆️⬆️

여러 유형과 객체 간에 발생하는 문제의 모듈화를 가능하게 함

 

 

OOP모듈화의 핵심 단위 => 클래스

AOP 모듈화의 핵심 단위 => Aspect (관점)

 

📖AOP용어정리

📌타겟
핵심 기능을 담고 있는 모듈
부가기능을 부여할 대상!

📌어드바이스(Advice)
특정 조인포인트(Join Point)에서 수행될 부가기능을 정리한 코드

📌조인포인트(Join Point)
어드바이스가 적용될 수 있는 위치
타겟 객체가 구현한 인터페이스의 모든 메서드는 조인 포인트가 된다.

📌포인트컷(PointCut)
어드바이스를 적용할 타겟의 메서드를 선별하는 정규표현식
포인트컷 표현식은 execution으로 시작하고 메서드의 Signature를 비교하는 방법을 주로 이용한다.

ex) @Pointcut(execution([접근제어자] 반환 타입 [패키지/클래스.] 메서드명 (파라미터 타입|"..",...) [throws 예외]
대괄호([ ])로 표시되어 있는 부분은 생략 가능
각 패턴은 * 기호를 사용하여 모든 값을 표현하는 것이 가능
점 두개 (..)를 사용하여 0개 이상의 수 표현 가능


📌Aspect
AOP의 기본 모듈이다.
여러 객체에 공통으로 적용되는 기능 (횡단 관심사)
Aspect = 어드바이스(Advice) + 포인트컷(PointCut)
싱글톤 형태의 객체로 존재


📌위빙
포인트컷에 의해서 결정된 타겟의 조인 포인트에 부가기능(어드바이스)를 삽입하는 과정
AOP가 핵심기능(타겟)의 코드에 영향을 주지 않으면서 필요한 부가기능(어드바이스)를 추가할 수 있도록
해주는 핵심적인 처리과정이다.

📌어드바이저(Advisor)
어드바이스 + 포인트컷
Spring AOP에서만 사용되는 특별한 용어

 

AOP의 특징

 

1. 스프링은 프록시 기반 AOP를 지원한다.

타겟(target) 객체에 대한 프록시를 만들어 제공

타겟을 감싸는 프록시는 실행시간(Runtime)에 생성

 

프록시 ( Proxy )

'대리' 라는 의미

특정 객체를 감싸 프로퍼티 읽기, 쓰기와 같은 객체에 가해지는 작업을 중간에서 가로채는 객체로, 가로채진 작업은 Proxy 자체에서 처리되기도 하고, 원래 객체가 처리하도록 그대로 전달되기도 한다.
프록시는 실제 객체에 대한 참조를 보관!
프록시 객체의 메소드를 호출하면, 프록시 객체는 실제 객체의 메소드를 호출한다(이떄 실제 데이터 조회)



Spring AOP에서는 어드바이스(Advice)를 타겟(Target) 객체에 적용하면서 생성되는 객체

같은 인터페이스를 구현하고 있는 실제 요청 처리 객체와 프록시 객체를 만들고,
프록시 객체가 대신하여 실제 요청 처리를 가짐 =>타겟을 감싸서 요청을 대신 받아주는 랩핑 클래스

 

2.프록시가 호출을 가로챈다(Intercept)

프록시는 타겟 객체에 대한 호출을 가로챈 다음

어드바이스의 부가기능 로직을 수행하고 난 후

타겟의 핵심기능 로직을 호출(전처리 어드바이스@Before)

또는 타겟의 핵심기능 로직 메서드를 호출한 후에 부가기능을 수행(후처리 어드바이스@After)

 

3.SpringAOP는 메서드 조인포인트만 지원

동적 프록시를 기반으로 AOP를 구현하므로 메서드 조인 포인트만 지원

핵심기능(타겟)의 메서드가 호출되는 런타임 시점에만 부가기능(어드바이스)을 적용할 수 있다.

반면에 AspectJ 같은 고급 AOP 프레임워크를 사용하면 객체의 생성, 필드값의 조회와 조작,

static 메서드 호출 및 초기화 등의 다양한 작업에 부가기능을 적용 할 수 있다.

 

 

Spring AOP의 구현 방식

1.XML 기반의 POJO클래스를 이용하여 구현

 

1)부가기능을 제공하는 Advice 클래스를 작성

2) XML 설정 파일에 <aop:config>를 이용해서 Aspect를 설정(어드바이스와 포인트컷을 설정)

 

 

2. @Aspect 애너테이션을 이용하여 구현

 

1) @Aspect 애너테이션을 이용하여 부가기능을 제공하는 Aspect클래스 작성

(이 때, Aspect 클래스는 어드바이스를 구현하는 메서드와 포인트컷을 포함)

 

2)XML 설정 파일에 <aop:aspectj-autoproxy />를 설정

 

pojo?
Java로 생성하는 순수한 객체

pojo프로그래밍?
POJO를 이용해서 프로그래밍 코드를 작성

단순 순수 자바 객체를 사용하는 것이 아닌
(1) 객체지향의 원리에 충실하며
(2) 다른 환경과 기술에 종속되지 않고
(3) 다른 기술과 규약에 얽매이지 않은 객체
를 사용하여 코드를 작성

 

 

 

 Aspect 클래스 선언 및 설정하기 

Aspect클래스에

4가지 유형(Before, AfterReturning, AfterThrowing, After)의 Advice와 PointCut 을 설정하여

타겟 객체의 파라미터와 리턴값, 예외 발생 시 예외 메시지를 출력하는 기능을 제공하는 클래스

 

-@Aspect 어노테이션 

Aspect 클래스를 선언할 때 @Aspect 어노테이션을 사용

XML 설정 파일에 Advice 와 pointcut을 설정하는 것이 아니라 클래스 내부에 정의할 수 있다!

 

-@Component 어노테이션 

Aspect 클래스를 Aspect로 사용하려면 Bean으로 등록해야 하기 때문에 @Component 어노테이션도 함께 정의해준다!

Advice 정의하는 어노테이션 

@Before("pointcut")

: Target 객체의 메서드가 실행되기전에 호출되는 Advice 

joinpoint를 통해 파라미터 정보를 참조할 수 있다. 

 

@After("pointcut")

: Target 객체의 메서드가 정상 종료됐을 때와 예외가 발생했을 때 모두 호출되는 Advice 

하지만 리턴값이나 예외를 직접 전달할 수는 없다!

 

@Around("pointcut")

: Target 객체의 메서드가 호출되는 전체 과정 모두 담을 수 있는 가장 강력한 기능을 가진 Advice

 

@AfterReturning(pointcut ="", returning ="") 

: Target 객체의 메서드가 정상적으로 실행을 마친 후에 호출되는 Advice이다.

리턴값을 참조할 때는 returning 속성에 리턴값을 저장할 변수 이름을 지정해야한다. 

 

@AfterThrowing(pointcut ="", Throwing="")

: Target 객체의 메서드가 예외가 발생하면 호출되는 Advice이다. 

발생된 예외를 참조할 때는 throwing 속성에 발생한 예외를 저장할 변수 이름을 지정해야한다.

 

 

복사했습니다!