AOP
- 관점 지향 프로그래밍(Aspect Oriented Programming)
- 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화함
AOP 주요 개념
- Aspect
• 위에서 설명한 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화함.
- Target
• Aspect를 적용하는 곳 (클래스, 메서드 .. )
- Advice
• 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체
- JointPoint
• Advice가 적용될 위치, 끼어들 수 있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능
- PointCut
• JointPoint의 상세한 스펙을 정의한 것. 'A란 메서드의 진입 시점에 호출할 것'과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있음
스프링 AOP 특징
- 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가기능을 추가하기 위해서임
- 스프링 빈에만 AOP를 적용 가능
- 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체들 간 관계 복잡도 증가 ...)에 대한 해결책을 지원하는 것이 목적
-> 수동으로 구현시 불필요하게 여러 개의 빈을 관리해야 할 뿐만 아니라 해당 타입의 빈이 여러 개이므로 의존성 주입 시에도 문제가 발생할 여지가 있다.
Jdk Dynamic Proxy
- Interface를 기반으로 Proxy를 생성해주는 방식

JDK 동적 프록시 방식 한계점
- 프록시를 적용하기 위해서 반드시 인터페이스를 생성해야 함
- 구체 클래스로는 빈을 주입받을 수 없고, 반드시 인터페이스로만 주입받아야 함
CGLIB
- JDK Dynamic Proxy와는 다르게 Reflection을 사용하지 않고,
Extends(상속) 방식을 이용해서 Proxy화 할 메서드를 오버라이딩 하는 방식
※ 정리
- 원래 Spring은 프록시 타깃 객체에 인터페이스가 있다면 그 인터페이스를 구현한 JDK 다이내믹 프록시 방식으로 객체를 생성하고, 인터페이스가 없다면 CGLib을 이용한 클래스 프록시를 만든다.
- 인터페이스를 구현하고 있는지 확인함
- 인터페이스를 구현하고 있으면 JDK 다이내믹 프록시 방식으로 객체를 생성
- 인터페이스를 구현하지 않으면 GCLib 방식으로 객체를 생성
Interceptor Filter와 차이점
- 컨트롤러로 들어가기 이전에 처리해야 할 작업들은 공통 관심사로 보고 분리하는 것이 것이 효율적이며, 이 때 사용할 수 있는 것이 필터(Filter)와 인터셉터(Interceptor), Spring AOP
Filter
- 스프링이 지원하는 기능이 아닌, J2EE 표준 스펙에 있는 기능으로 가장 앞단에 존재하는 프론트 컨트롤러인 디스패처 서블릿(Dispatcher Servlet)에 요청이 전/후에 부가적인 작업을 처리할 수 있는 기능을 제공

Interceptor
- 스프링(Spring)이 제공하는 기술로써 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청을 가로채서 응답을 참조하거나 가공할 수 있게 도와준다.인터셉터는 필터와 다르게 스프링 컨텍스트 내부에서 동작한다.

차이점
- 필터는 자바(Java)가 지원하는 기능이고, 인터셉터는 스프링(Spring)이 지원하는 기능이다.
- 필터는 WebApplication에서 동작하고, 인터셉터는 Spring Context에서 동작한다.
- 필터에서 발생하는 예외는 WebApplication에서 처리된다.
- 필터는 Dispatcher Servlet보다도 앞에서 동작할 수 있다.
- ServletRequest, ServletResponse를 받아서 처리하는 것이 가능하다.
- 인터셉터는 필터랑 달리 컨트롤러가 동작한 후에 작업을 처리할 수 있다.
- ex. ViewController에서 뷰를 생성한 것에 따라 동적으로 처리하는 일이 가능하다.
Spring 전체 동작과정

- 웹을 켠다
- 브라우저==> 클라이언트
- 클라이언트가 url을 매칭시켜서 View로 정보를 요청한다
- view에서 해당 요청을 수행하려고 한다
- 그러면 Dispatcher-servlet이 HandlerMapping을 동작시킴
- 해당 url이 매핑된 Controller를 검색
- 주입된 @Bean객체를 가지고 handlerMapping에 매핑되어 있는 Controller를 호출한다. (@Controller)
- @RequestMapping("url") 그 Controller안에 요청(ex: url + .do )과 일치하는 url 메소드를 찾아서 Service -> DAO -> DB 순서로 클라이언트에서 받은 어떠한 데이터들을 가지고 이동해서 조건에 맞는 쿼리를 DB에서 수행한다.
- 그 후 해당하는 자료를 다시 역순으로
DB -> DAO -> Service 순으로 Dto에 받아와서 Controller에 데이터를 반환해준다.
- 이제 반환값으로 Controller에서 출력할 viewName을 반환한다.
- 처리된 데이터를 ViewResolver에서 prefix경로의 viewName.suffix 형식이 있는지 확인한다.
- 해당하는 View가 있으면 View에 가지고있는 데이터를 전달한다.
- view는 받은 데이터를 다시 Dispatcher-Servlet에 전달해준다.
- Dispatcher-Servlet은 받은 데이터를 클라이언트로 전달한다.
- 최종 결과를 클라이언트에서 출력