들어가기 앞서..
[Study] Spring 정리 (IoC, DI, AOP, POJO, MVC)
[Study] Spring 정리 (IoC, DI, AOP, POJO, MVC)
Spring 이란? 정의 Spring이란 간단히 말하면 Java 기반의 웹 어플리케이션을 개발할 수 있는 오픈소스 프레임워크이다. 더욱 자세하게 용어를 풀어 설명하자면 다음과 같다. 오픈소스 : 용어에서 알
soohykeee.tistory.com
앞서 AOP에 대해 정리한 적이 있지만, 간단하게 정리하였기에 다시한번 정리해주기 위해서 글을 작성한다.
현재 진행하고 있는 Study에서 AOP를 활용하여 logging 정보를 출력하도록 사용해주기로 했다. 해당 AOP를 pet-clinic 프로젝트에 적용하기 전, 우선적으로 공부를 해보려 한다.
AOP (Aspect Object Programming)
AOP는 관점 지향 프로그래밍이라고 불리는데, 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화 하겠다는 것이다.
- 핵심적인 관점 : 개발자가 적용하고자 하는 핵심 비즈니스 로직
- 부가적인 관점 : 핵심 로직을 수행하기 위한 DB 연결, 로깅, 파일 입출력 등
- 모듈화 : 어떠한 공통된 로직이나 기능을 하나의 단위로 묶는 것
여기서 중요한 부분이 바로 부가적인 관점 이다. 비즈니스 로직과 같은 부분을 모듈화 하는 것은 AOP가 아닌 OOP이다. 인프라 혹은 부가기능 예를 들어서 로깅, 트랜잭션 이러한 기능을 따로 분리하여 모듈화 하는 것이 AOP이다.
예를 들어, 만약 A, B, C 클래스에 모두 공통적으로 반복해서 쓰는 코드가 있다고 가정해보자. (부가적인 기능을 분리한다)
: 이렇게 공통적으로 반복해서 사용하는 코드를 흩어진 관심사 (Crosscutting Concerns)라 부른다. 이 처럼 흩어진 관심사를 Aspect로 모듈화하고 핵심적인 비즈니스 로직에서 분리해서 재사용하는 것이 AOP이다.
AOP를 사용하는 이유는 무엇일까?
→ 공통의 기능을 한 곳에 모아 놓고 사용할 수 있기에 유지 보수 측면에서 용이하다. 또한 Service 모듈들이 각자의 역할에 충실하여 구현할 수 있기에 더욱 객체지향스럽다.
만일 AOP를 사용하지 않고 놔두면 어떨까?
→ 만약 A, B, C 클래스에서 공통으로 사용하는 코드의 수정이 필요할 경우, 모든 클래스에서 수정을 해줘야 한다. 이는 유지보수 측면에서 유용하지 못하다. 또한, 코드가 많아지게 되어 공통의 코드를 사용하는 다른 클래스에서 수정을 해주지 못할 가능성도 존재한다.
AOP 적용 방식
AOP 적용 방법은 크게 3가지가 존재한다.
- 컴파일 시점
- java 파일을 컴파일러를 통해 class를 만드는 시점에 부가 기능 로직을 추가하는 방식이다.
- 모든 지점에서 적용이 가능하다.
- AspectJ가 제공하는 특별한 컴파일러를 사용해줘야 하기에, 복잡하다는 단점이 있다.
-> 그렇기에 해당 방법은 권장 X
- 클래스 로딩 시점
- class 파일을 JVM 내부의 클래스 로더에 보관하기 전, 부가 기능 로직을 추가하는 방식이다.
- 모든 지점에서 적용이 가능하다.
- 특별한 옵션과 클래스 로더 조작기를 지정해야 하므로 운영이 어렵다
-> 그렇기에 해당 방법 또한 권장 X
- 런타임 시점
- 스프링 AOP가 사용하는 방법
- 컴파일이 끝나고 클래스 로더에 올라간 java가 실행 된 다음 동작하는 방식이다.
- 실제 대상 코드는 유지되고, 프록시를 통해 부가 기능이 적용된다.
- 프록시는 메서드 오버라이딩 개념으로 동작하기에, 메서드에만 적용이 가능하다.
그렇기에 스프링 빈에만 AOP를 적용할 수 있다. - 위의 컴파일 시점, 클래스 로딩 시점과 다르게 스프링만 있으면 AOP를 적용할 수 있기에 해당 방식을 권장
AOP 용어
- JoinPoint
- 추상적인 개념으로, Advice가 적용될 수 있는 모든 위치를 말한다.
- 스프링 AOP는 프록시 방식을 사용하기에 joinpoint는 항상 메서드 실행 지점에만 가능하다.
- Pointcut
- joinpoint 중에서 advice가 적용될 위치를 선별
- 스프링 AOP는 프록시 기반이기에, 메서드 실행 시점에만 가능하다.
- Target
- 부가기능을 부여할 대상
- advice의 대상이 되는 객체로, pointcut으로 결정된다.
- Advice
- 실질적인 부가 기능 로직을 정의하는 위치
- target 객체에 종속되지 않기에 부가기능에만 집중할 수 있다.
- Aspect가 무엇을 언제할지를 정의한다.
- Aspect
- Advice + pointcut을 모듈화 한 것
- @Aspect와 같은 의미
- Advisor
- 스프링 AOP에서만 사용되는 용어로 advice + pointcut 의 집합
- Weaving
- pointcut으로 결정한 target의 joinpoint에 advice를 적용하는 것
- AOP 프록시
- AOP 기능을 구현하기 위해 만든 프록시 객체
- 스프링에서 AOP 프록시는 JDK 동적 프록시 or CGLIB 프록시
- 스프링 AOP의 기본값은 CGLIB 프록시
Advice
Adivce는 프록시에서 수행하게 되는 실질적인 로직을 정의하게 되는 곳이다.
Spring에서는 해당 Advice에 관련된 어노테이션을 제공한다. 해당 어노테이션들은 메서드에 사용할 수 있고, 해당 메서드는 advice의 로직을 정의하게 되고, 어노테이션의 종류에 따라 pointcut에 지정된 대상 메서드에 advice가 실행 되는 시점을 정할 수 있다. 어노테이션을 정리해보면 다음과 같다.
- @Around
- advice에 해당하는 어노테이션을 모두 포함하는 어노테이션
- 메서드 호출 전후로 작업 명시가 가능하다.
- joinpoint 실행 여부 선택이 가능하다.
- 반환값, 예외 조작이 가능하다.
- joinpoint를 여러번 실행이 가능하다.
- @Before
- joinpoint 실행 이전에 실행된다. (실제 target 메서드 수행전에 실행된다)
- 입력값 자체는 조작이 불가능 (입력값 내부에 setter와 같은 수정자가 있다면 가능)
- @AfterReturning
- joinpoint가 정상 완료 된 후, 실행된다. (실제 target 메서드 수행 완료 후 실행)
- 반환값 자체는 조작이 불가능 (반환값 내부에 setter와 같은 수정자가 있다면 가능)
- @AfterThrowing
- 메서드에 예외가 발생한 경우 실행된다. (실제 target 메서드에 예외가 발생한 경우 실행)
- 예외 조작이 불가능
- @After
- joinpoint의 정상 실행이나 예외 발생과 무관하게 실행된다. (실제 target 메서드가 정상 실행이 되거나, 예외가 발생하거나 수행 이후에는 무조건 실행)
어노테이션 동작 순서