2 minute read

AOP (Aspect Oriented Programming)

  • 관점 지향 프로그래밍
  • 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화해 재사용할수 있도록 지원하는 것

  • Aspect : 관심사를 모듈화 한 것
  • Target : 클래스, 메서드 등 Aspect를 적용하는 곳
  • Advice : 실질적인 부가기능을 담은 구현체
  • JointPoint : Advice가 적용될 수 있는 모든 위치로 추상적 개념
  • PointCut : JointPoint중 Advice가 적용될 위치를 선별

JDK Dynamic Proxy

  • JDK의 java.lang.reflect 패키지에서 제공하는 동적 프록시 기술
  • 인터페이스를 구현한 클래스를 동적으로 생성하여 프록시 객체를 생성하는 방법 (타깃의 인터페이스 기준)
  • 프록시 객체는 실제 객체를 대신하여 클라이언트 요청을 처리하고, 필요에 따라 추가적인 로직을 수행할 수 있음

특징

  • 인터페이스를 구현한 클래스만 프록시 객체를 생성할 수 있음
  • 동적으로 생성되기 때문에 프록시 객체의 클래스 파일이 생성되고, 메모리에서 로딩되는 과정이 필요함
  • 메소드 호출 시 프록시 객체는 InvocationHandler를 호출하고, InvocationHandler는 실제 객체의 메소드를 호출하여 처리함

활용

  • AOP(Aspect Oriented Programming) 구현에 많이 사용
  • 실제 객체의 동작 이전 및 이후에 공통적인 로직을 구현할 때 유용하다

단점

  • 인터페이스를 구현한 클래스만 대상으로 하기 때문에, 인터페이스가 없는 클래스나 메소드에는 적용할 수 없음
  • 동적으로 생성된 클래스이기 때문에 디버깅이 어렵고, 성능에도 영향을 미칠 수 있음
  • 생성된 프록시 객체는 한 번에 하나의 인터페이스만 구현할 수 있음

CGLIB (Code Generation Library)

  • 자바 바이트코드를 사용하여 런타임 시에 클래스를 동적으로 생성하는 라이브러리
  • 객체 지향 프로그래밍에서 AOP 구현에 많이 사용됨

특징

  • Dynamic Proxy와 비슷한 방식으로 클래스의 메소드를 호출하고, 필드에 접근할 수 있음
  • 상속을 통해 클래스를 생성하므로 인터페이스와 클래스 모두를 대상으로 적용 가능함
  • 프록시 객체를 생성할 때, 원본 객체를 상속받은 클래스를 생성하여 프록시 객체를 생성함
    • 생성된 프록시 객체는 원본 객체의 메소드를 재정의하고, 필요에 따라 추가적인 로직을 수행할 수 있음

활용

  • Java Spring은 CGLIB를 활용하여 프록시 객체를 생성하고, AOP 구현에 사용함
  • 스프링 빈(Bean)에 대한 메소드 호출 시, 빈의 메소드를 실행하는 대신 CGLIB를 사용하여 프록시 객체의 메소드를 호출함
  • 프록시 객체는 메소드 호출 전/후에 공통 로직(예: 로깅, 보안 등)을 수행할 수 있음

한계

  • 클래스를 상속받아야 하므로, final 클래스와 메소드에는 적용할 수 없음
  • default 생성자가 필요하다. (Spring 3.2 이상에서는 해결되었다.)

interceptor

  • 컨트롤러에 들어오거나 나가는 요청과 응답을 가로채는 역할
  • 컨트롤러 호출 전후에 추가적인 로직 수행 및 반환된 결과 가공

활용

  • 컨트롤러 요청 전/후에 공통 로직을 처리하고, 요청 파라미터를 검증하는 등의 기능을 제공
  • HandlerInterceptor 인터페이스를 구현하여 사용할 수 있으며, preHandle(), postHandle(), afterCompletion() 메소드를 오버라이딩하여 컨트롤러 요청 전/후에 처리할 로직을 구현
  • 필터(Filter)와 비슷한 역할을 하지만, 컨트롤러의 메소드를 직접 호출하여 처리하므로, 컨트롤러의 상태나 뷰(View)에 직접적으로 영향을 미칠 수 있음

장단점

  • 컨트롤러 로직을 분리하여 유지보수성을 높이고, 공통 로직을 한 곳에서 관리할 수 있음
  • 많이 사용하면 로직의 복잡도가 증가할 수 있으며, 컨트롤러와 인터셉터 간의 상호작용을 고려해야 함

filter와 차이점

  • Interceptor는 컨트롤러의 메소드를 직접 호출하여 처리하므로, 컨트롤러와 뷰(View)에 직접적으로 영향을 미칠 수 있음
  • Filter는 요청과 응답의 헤더 정보만을 처리하기 때문에, 컨트롤러와 뷰(View)에 영향을 미치지 않음
  • Interceptor는 Filter와 달리 DispatcherServlet에서 호출되며, HandlerMapping 정보를 참조할 수 있음

Spring 전체 동작과정

  1. 클라이언트에서 요청이 발생
  2. 요청을 DispatcherServlet이 받아들임
  3. DispatcherServlet은 HandlerMapping을 통해 요청을 처리할 컨트롤러를 찾음
  4. HandlerAdapter가 컨트롤러를 실행하고, 결과를 ModelAndView 객체로 반환
  5. ModelAndView 객체가 ViewResolver를 통해 실제 View 객체로 변환
  6. 변환된 View 객체가 클라이언트에게 응답으로 전송

Leave a comment