AOP
AOP는 Aspect-Oriented-Programming의 약자를 뜻합니다. 서로 다른 클래스라 하더라도 비슷한 기능을 담당하는 부분은 존재할 수 있습니다.
예를 들어 다음과 같은 A B C 클래스가 존재한다고 가정해보겠습니다. 클래스안의 색깔 블록은 특정 기능을
수행하는 기능입니다. 만약 보라색 블록을 수정한다면 A B C 모든 클래스에서 일일이 수정해줘야 하기 때문에
유지 보수 측면에 있어서 굉장히 어려워지게 됩니다.
이런식으로 소스 코드 상에서 계속 반복해서 사용되는 부분들을 흩어진 관심사라고 합니다.
이를 해결하고자 나온게 AOP입니다.
흩어진 관심사를 모듈화를 통해 모아주고 어느 클래스에서 사용하는지 입력만 해주면 됩니다.
위 그림과 같이 클래스로 부터 블록들을 뺴와서 Aspect에 담아주었습니다. 각각이 하나의 모듈이 된 셈입니다.
Advice와 PointCut과 같은 용어들은 무엇을 뜻할까요?
Aspect - 흩어진 관심사를 모듈화 한 것
Target - Aspect를 적용하는 곳 (클래스 또는 메서드가 될 수 있습니다.)
Advice - 실질적으로 어떤 일을 해야 할 지에 대한 것
Join Point - Advice가 적용 될 위치를 뜻합니다. 스프링에서 Join Point는 언제나 메서드 실행 시점을 뜻합니다.
Point Cut - Join Point의 상세한 스펙을 정의한 것입니다.
스프링 AOP
스프링 AOP는 프록시 기반으로 동작합니다. 또한 스프링 Bean에만 적용될 수 있는 특징이 있습니다.
코드로 한번 살펴보겠습니다.
위와 같은 컨트롤러가 있다고 가정해봅시다. /example이라는 요청이 들어오면 Thread를 1000 밀리세컨드간 중단하고
응답값으로 "테스트"를 내보내주는 간단한 메서드입니다.
만약 이와 같은 메서드에 처리하는데 걸리는 시간을 알려면 어떻게 해야될까요?
위와 같이 코드를 수정하면 될 것 입니다. 하지만 걸리는 시간을 알고싶은 메서드들이 많이 존재한다면
해당 코드를 일일이 수정해줘야 할 것입니다. 만약에 시간 계산 방식에 변경을 주고자 한다면 작성했던 메서드들을
하나하나 바꿔줘야 하기 떄문에 유지보수적인 측면에서 매우 안좋을 수 있습니다. 이럴 경우 AOP를 활용한다면
효과적으로 해당 문제를 해결 할 수 있습니다.
위의 코드는 처리 시간을 알려주는 AOP 클래스입니다. 스프링 AOP는 스프링 빈에서만 사용될 수 있기 때문에
자신도 Component 어노테이션을 통해 스프링 빈으로 등록되어야 합니다.
@Aspect를 통해 해당 클래스가 흩어진 관심사를 모아주는 모듈(AOP)임을 선언하고
@Around 어노테이션을 메서드단위에 붙여 어느 클래스 또는 메서드에 적용할 것인지 명시해줍니다.
위와 같은 경우는 timelog라는 어노테이션을 사용하여 해당 메서드를 사용한다고 명시해주었습니다.
ProceddingJoinPoint라는 인터페이스를 인자로 받고 있는데, 이는 적용할 메서드를 어느 지점에 실행할 것인지
정해주는 기능을 수행합니다. 위와 같은 경우 현재 시각과 처리 후의 시간 사이에 joinPoint.proceed(); 를 통하여
메서드 실행 시점을 명시해주었습니다.
해당 메서드를 실행하게 되면 결과값이 반환되는데 해당 결과값은 return 해주어야 실제 적용된 메서드에서
반환값을 받을 수 있습니다.
그 뒤 원래 컨트롤러에 다음과 같이 @TimeLog 어노테이션을 붙으면 AOP 적용이 끝납니다. 실제로 PostMan을 통해
해당 컨트롤러에 요청을 하게 되면
다음과 같이 메서드 수행하는데 걸리는 시간이 콘솔에 찍히게 됩니다.
실제로 AOP가 적용된 Test컨트롤러와 AOP가 적용되지 않은 Board 컨트롤러의 클래스 타입을 다음과 같이 찍어보면
다음과 같이 결과값이 서로 다른것을 확인할 수 있습니다.
스프링 AOP는 프록시 기반으로 동작한다고 위에서 언급했는데, 실제 AOP가 적용된 클래스는 다음과 같이
프록시 기반의 객체 타입으로 스프링 빈에서 관리하게 됩니다.
따라서 AOP가 적용되지 않은 BoardController는 원래 클래스 타입이 나오지만
AOP가 적용된 TestController는 프록시를 뜻하는 CGLIB이 뒤에 붙게 되는 것입니다.
AOP가 사용되는 예시
Transactional 어노테이션이 가장 흔하게 사용되는 AOP가 적용된 어노테이션의 예시입니다.
보통 서비스 레이어에 해당 어노테이션을 붙여서 사용하게 되는데, 데이터베이스의 커넥션 획득과 커넥션 닫기
뿐만아니라 문제가 생길 경우 RollBack 까지 해주는 기능을 수행합니다.
만약 Transactional 어노테이션을 사용하지 않는다면 개발자가 이를 일일이 메서드에 작성해야 되는 어려움이
있을 겁니다. 이를 AOP기반의 Transactional 어노테이션이 효과적으로 해결해줍니다.
실제로 클래스 타입을 찍어보면 다음과 같이 @Transactional 어노테이션이 붙은 TestService의 클래스 타입 또한 프록시 타입으로 나오는것을 확인할 수 있습니다.
이상으로 AOP에 대한 정리를 마치겠습니다.
글 읽어주셔서 감사합니다.
참고 블로그
https://code-lab1.tistory.com/193
[Spring] AOP(Aspect Oriented Programming)란? 스프링 AOP란?
AOP (Aspect Oriented Programming)란? AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불린다. 관점 지향은 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그
code-lab1.tistory.com
'Spring' 카테고리의 다른 글
생성자 주입 방식을 써야하는 이유 (0) | 2023.05.03 |
---|---|
Bean과 Component 뜯어보기 (0) | 2023.03.22 |
BeanFactory와 ApplicationContext의 차이점 (0) | 2023.02.21 |
스프링 빈의 쓰레드 안정성에 대하여 (0) | 2023.02.21 |
스프링 시큐리티 아키텍처에 대하여 (0) | 2023.01.29 |