Home [스프링 핵심 원리 - 고급편] 스프링 AOP 개념
Post
Cancel

[스프링 핵심 원리 - 고급편] 스프링 AOP 개념

스프링 AOP 개념

  • 김영한님의 스프링 원리 - 고급편 강의를 바탕으로 AOP의 등장 배경과 주요 개념, 적용 방식, 용어 정리, 그리고 스프링 AOP와 AspectJ의 차이를 정리함



핵심 기능과 부가 기능

개요

  • 애플리케이션 로직은 크게 두 가지로 구분됨

    구분 설명 예시
    핵심 기능 해당 객체가 제공하는 고유 기능 OrderService의 주문 로직
    부가 기능 핵심 기능을 보조하기 위한 기능 로그 추적, 트랜잭션 관리
  • 부가 기능은 단독으로 사용되지 않고, 핵심 기능과 함께 사용됨

    핵심 기능과 부가 기능 흐름



횡단 관심사

개요

  • 부가 기능은 보통 여러 클래스에 걸쳐 공통으로 사용됨
  • 이처럼 여러 모듈에 공통적으로 적용되는 부가 기능을 횡단 관심사라고 함

    횡단 관심사 흐름

부가 기능 적용 시 문제점

  • 부가 기능 적용 시 수많은 반복이 발생함
  • 여러 곳에 퍼져 중복 코드가 생성됨
  • 부가 기능 변경 시 모든 클래스를 수정해야 함
  • 적용 대상 변경 시에도 대규모 수정이 필요함

일반적인 OOP 방식으로는 이 문제를 해결하기 어려움



AOP 소개 - 애스펙트 (Aspect)

부가 기능을 분리하고 한 곳에서 관리

애스펙트 적용 흐름

  • Aspect = 어드바이스(부가 기능) + 포인트컷(어디에 적용할지)
  • AOP는 OOP를 대체하는 것이 아니라, OOP의 부족한 부분(횡단 관심사 처리)을 보조하는 목적으로 개발됨

AspectJ 프레임워크

  • AOP의 대표적 구현체이며, 스프링 AOP는 AspectJ의 문법을 차용하되 기능의 일부만 제공함
  • AspectJ가 지원하는 기능
    • 횡단 관심사의 깔끔한 모듈화
    • 오류 검사 및 처리
    • 동기화
    • 성능 최적화 (캐싱)
    • 모니터링 및 로깅



AOP 적용 방식

개요

AOP 적용 방식 3가지

컴파일 시점 (Compile-time Weaving)

1
2
3
  OrderService.java
        ↓ (AspectJ 컴파일러)
  orderService.class  ← 부가 기능 코드가 실제로 삽입됨
  • AspectJ 전용 컴파일러가 필요함
  • 컴파일된 .class 파일에 부가 기능 코드가 직접 포함됨
  • 특별한 컴파일러 설정이 필요하여 복잡함

클래스 로딩 시점 (Load-time Weaving)

1
2
3
  orderService.class
        ↓ (AspectJ 클래스 로더 조작기)
  JVM 내부 → 부가 기능이 추가된 클래스로 로드됨
  • java -javaagent 옵션으로 클래스 로더 조작기를 지정함
  • .class → JVM 적재 직전에 바이트코드를 조작함
  • 수많은 모니터링 툴이 이 방식을 사용함
  • 운영 설정이 번거롭고 어려움

런타임 시점 (Runtime Proxy) - 스프링 AOP

런타임 프록시 방식 흐름

  • 자바 main 메서드가 실행된 이후 동작함
  • 스프링 컨테이너 + 프록시 + DI + 빈 후처리기를 활용함
  • 특별한 컴파일러나 JVM 옵션이 불필요함
  • 메서드 실행 지점에만 AOP 적용이 가능 (스프링 빈에만 적용됨)

비교 요약

방식 부가 기능 삽입 위치 필요 설정 적용 범위
컴파일 시점 .class 파일 내부 AspectJ 컴파일러 모든 조인 포인트
클래스 로딩 시점 .class 파일 내부 -javaagent 옵션 모든 조인 포인트
런타임 시점 (스프링) 프록시를 통한 위임 없음 (스프링만 있으면 됨) 메서드 실행만



AOP 적용 위치 (조인 포인트 범위)

  • AspectJ (컴파일/로드 타임)
    • 생성자 호출
    • 필드 값 접근
    • static 메서드 접근
    • 메서드 실행
  • 스프링 AOP (런타임)
    • 메서드 실행만 가능
  • 스프링 AOP는 프록시 방식(메서드 오버라이딩)이므로 생성자, static 메서드, 필드 값 접근에는 적용이 불가함



AOP 용어 정리

전체 구조 관계도

AOP 용어 관계도

용어 정리

용어 설명
조인 포인트 (Join point) AOP를 적용할 수 있는 모든 지점이며, 스프링 AOP는 메서드 실행으로 제한됨
포인트컷 (Pointcut) 조인 포인트 중 어드바이스를 적용할 위치를 선별하는 표현식
타겟 (Target) 어드바이스를 받는 객체이며 포인트컷으로 결정됨
어드바이스 (Advice) 실제 부가 기능 로직이며 Before, After, Around 종류가 존재함
애스펙트 (Aspect) 어드바이스 + 포인트컷을 모듈화한 것이며 @Aspect 애노테이션을 사용함
어드바이저 (Advisor) 어드바이스 1개 + 포인트컷 1개로 구성되며 스프링 AOP 전용 용어임
위빙 (Weaving) 포인트컷으로 선별한 조인 포인트에 어드바이스를 적용하는 행위
AOP 프록시 AOP 구현을 위해 생성된 프록시 객체이며 JDK 동적 프록시 또는 CGLIB를 사용함



연습 문제

  1. 부가 기능(크로스커팅 관심사)을 여러 곳에 적용할 때 기존 OOP 방식에서 어떤 문제가 발생할까요?

    a. 이 모든 문제들이 발생해요.

    • 핵심 기능 코드에 부가 기능을 직접 넣으면 코드 중복이 심해지고, 기능을 수정할 때 여러 곳을 고쳐야 하며, 적용 대상을 바꾸기도 어려워짐
    • AOP는 이런 복합적인 문제들을 해결하기 위해 등장함
  2. AOP는 OOP와 어떤 관계일까요?

    a. OOP의 한계를 보완해주는 동반자 같은 역할이에요.

    • AOP는 객체 지향 프로그래밍의 부족한 점, 특히 여러 모듈에 흩어져 있는 횡단 관심사(로깅, 트랜잭션 등)를 효과적으로 다루기 위해 나옴
    • OOP를 대체하는 것이 아니라 보완하여 더 깔끔한 설계를 돕는 관계임
  3. AOP에서 ‘애스펙트(Aspect)’는 무엇과 무엇을 묶어 놓은 모듈일까요?

    a. 어드바이스와 포인트컷

    • 애스펙트는 어떤 부가 기능(어드바이스)을 어디에 적용할지(포인트컷)를 하나로 모아둔 모듈임
    • 스프링 AOP의 핵심 구성 단위라고 할 수 있음
  4. 스프링 AOP가 부가 기능을 핵심 기능에 연결하는 방식(Weaving)은 주로 무엇을 사용할까요?

    a. 프록시 객체를 이용하는 런타임 방식

    • 스프링 AOP는 주로 애플리케이션이 실행되는 런타임 시점에 프록시 객체를 동적으로 생성하여 부가 기능을 적용함
    • 이 방식 덕분에 원본 자바 코드를 직접 수정하거나 컴파일 시점에 개입하지 않고도 기능을 확장할 수 있음
  5. 스프링 AOP는 왜 AspectJ처럼 다양한 조인 포인트(예: 생성자, 필드 접근)에 적용하기 어려울까요?

    a. AOP 프록시 방식을 사용하기 때문에

    • 스프링 AOP는 프록시 패턴을 기반으로 동작하기 때문에 프록시가 가로챌 수 있는 메서드 실행 시점에만 부가 기능을 적용할 수 있음
    • 반면 AspectJ처럼 컴파일 타임이나 로드 타임에 바이트코드를 조작하는 방식은 생성자 호출이나 필드 접근 등 더 넓은 범위의 조인 포인트를 지원함



요약 정리

  • 부가 기능이 여러 곳에 흩어지면 OOP만으로는 관리하기 어려우며, 이를 해결하기 위해 AOP가 등장함
  • AOP는 어드바이스(부가 기능)와 포인트컷(적용 대상)을 하나로 묶은 애스펙트 단위로 모듈화함
  • 스프링 AOP는 런타임 프록시 방식으로 동작하며, 별도의 컴파일러나 JVM 옵션 없이 메서드 실행 시점에 부가 기능을 적용함
  • 실무에서는 스프링 AOP만으로 대부분의 요구사항을 충족할 수 있으며, 더 넓은 범위의 조인 포인트가 필요한 경우에만 AspectJ를 고려하면 됨



Reference

Contents