상세 컨텐츠

본문 제목

Spring Triangle - AOP 개요

Spring

by 흥많은 개발자 2023. 12. 13. 13:41

본문

Spring 로고

AOP 는 Spring Triangle 의 한 축을 담당하는 개념일 뿐만 아니라, 소프트웨어 공학에서 굉장히 중요한 요소입니다.
이번 글에서는 AOP 자체에 대해 개괄적으로 다루어 보도록 하겠습니다.

AOP

AOP 는 Aspect Oriented Programming 의 약자로 '관점 지향 프로그래밍' 으로 해석합니다. 조금 더 풀어 해석하면 '관점을 중심으로 소프트웨어을 바라보는 개발 패러다임' 정도가 되겠습니다.
풀어 해석해도 먼가 애매모호한 것 같습니다. AOP 의 개념을 정확히 이해하려면 Aspect(관점) 에 대한 이해에서 출발해야 합니다.

핵심기능과 부가기능

그 전에 먼저 핵심기능과 부가기능이라는 개념을 짚어 보겠습니다.
핵심기능은 OOP 에서 각각의 객체들의 고유한 기능을 의미합니다. 주문 서비스의 주문 처리, 회원 서비스의 회원 등록과 같은 기능들이 이에 해당합니다.
부가기능은 각각의 객체가 자신이 핵심 기능을 수행하는 과정에서 부가적으로 적용하는 기능을 의미합니다. 주문 처리, 회원 등록을 하는 과정에서 데이터 정합성을 위해 적용하는 트랜잭션 기능이나, 성능 측정을 위해 적용하는 로깅 기능 등이 이에 해당합니다.

부가기능과 SRP

핵심기능과 부가기능이 모두 적용된 주문 서비스는 아래와 같은 형태를 가질 것입니다.

fun processOrder() {
    start logging
    start transaction
    process order
    end transaction
    end logging
}

그런데 책임과 구현이라는 관점에서 보면 processOrder 의 구현부 중에 '주문 처리' 라는 책임과 직접적으로 관련이 있는 것은 "process order" 부분 뿐입니다. 나머지 구현부는 모두 주문처리와 직접적으로 연관된 코드는 아닙니다. 주문처리 라는 책임을 수행하기 위한 구현체에 주문처리와 직접 관련이 없는 코드들이 섞여있기 때문에 단일 책임 원칙(SRP) 에 위배되는 코드라고 볼 수 있습니다.

부가기능과 횡단관심사

부가기능에 대해 주목할만한 또다른 요소는 부가기능은 여러 객체에서 같은 방식으로 적용이 될 수 있다는 점입니다. 예를 들어 주문 처리와 회원 등록 모두 트랜잭션 기능을 동일한 방식으로 적용합니다. 단순히 트랜잭션을 시작하고, commit 하거나 rollback 하는 것이죠. 로깅의 경우도 마찬가지입니다. 성능 측정용 로깅이라면, 어떤 메서드에서 사용되든 시작시간과 종료시간을 측정해서 로그를 남기는 방식으로 동작합니다. 이를 그림으로 표현하면 아래와 같습니다.
횡단관심사
이렇게 애플리케이션의 여러 요소에서 동일하게 사용하는 기능을 횡단관심사(cross-cutting concerns)라고 합니다. 대부분의 부가기능은 횡단관심사로서 기능합니다.
문제는 위의 pseudo code 와 같은 방식으로 부가기능을 적용하면 똑같은 코드를 회원 등록 구현부에도 넣어야 한다는 것입니다.

fun registerMember() {
    start logging
    start transaction
    register member
    end transaction
    end logging
}

당연한 얘기지만 또다른 객체에 이 부가기능들을 적용하고 싶다면 해당 객체에도 같은 작업을 해주어야 합니다. 더 큰 문제는 부가기능 자체의 인터페이스에 변경 사항이 발생하면 이를 적용한 모든 객체에 수정이 발생한다는 것입니다. 그리고 또다른 중요한 문제가 한가지 더 있는데, 부가기능의 적용대상을 바꾸고 싶을 때(ex) 회원 관리 DB 가 NoSql 로 바뀌어서 트랜잭션 기능을 빼야 하는 경우) 에도 애플리케이션의 여러 요소에 변경을 유발할 수 있다는 것입니다.

Aspect 와 AOP

위에서 살펴본 것처럼 부가기능을 적용하는 것은 여러가지 문제점을 가지고 있고, 이를 일반적인 OOP 기법으로 해결하기도 어렵습니다. 그래서 이를 해결하기 위해 부가기능과 관련된 코드를 독립적인 모듈의 형태로 개발하려는 시도와 연구가 있었고, 그런 과정 속에서 Aspect 라는 개념이 탄생합니다. Aspect 는 부가기능 로직과 부가기능을 어디에 적용할 지를 선택하는 로직으로 구성된 하나의 모듈입니다. 만약 언어나 프레임워크 차원에서 Aspect 를 만드는 것과 만들어진 Aspect 를 객체에 연결하는 기능을 지원한다면, 위에서 언급한 부가기능 적용과 관련된 문제들을 깔끔하게 해결할 수 있습니다.(핵심기능과 부가기능의 분리, 부가기능 중복 작업, 부가기능 적용 대상 설정 등)
결국 AOP 란, Aspect 를 지원하는 언어나 프레임워크 위에서 Aspect 를 중심으로 프로그래밍을 하는 개발 패러다임을 의미합니다. Aspect 를 사전적 의미의 관점으로 해석하면 AOP 에 대한 해석이 잘 와닿지 않지만, Aspect 를 '부가기능 모듈' 로 해석하면 그 의미가 좀 더 직관적으로 다가옵니다. 또는 AOP 를 '전통적인 객체 중심 관점' 이 아닌 '횡단관심사 관점' 으로 프로그램을 바라보는 개발 패러다임이라고 해석하기도 합니다.

OOP 와 AOP

위에서 여러번 언급했듯이 AOP 는 순수한 OOP 만으로 해결하기 어려운 부가기능 처리를 지원하기 위한 개념입니다. 하지만 이것이 OOP 와 AOP 가 서로 대결하는 개발 패러다임이라는 의미는 아닙니다. 오히려 AOP 는 OOP 기반의 프로그래밍을 보조하는 보조 패러다임이라고 볼 수 있습니다. 사실 Aspect 자체도 OOP 에서의 하나의 객체입니다. 각각의 부가기능 들을 OOP 의 설계 원칙을 지켜가면서 잘 설계해야 합니다. AOP 구현 기술은 단지 부가기능을 담당하는 객체인 Aspect 와 핵심기능을 담당하는 기존 OOP 의 객체들을 연결해주는 Low Level 의 기능을 지원하는 것이죠. 이를 그림으로 표현하면 아래와 같습니다.
횡단관심사와 AOP

AOP 지원 기술

AOP 는 OOP 뿐만 아니라 여러 개발 패러다임을 보조하는 보조 패러다임이기 때문에 굉장히 범용적으로 사용이 됩니다. 당연히 AOP 를 지원하는 구현 기술도 여러가지 종류가 있습니다. 다양한 프로그래밍 언어에서 AOP 를 언어 자체적으로 혹은 프레임워크나 라이브러리의 형태로 지원합니다. 여기서는 Java 에서의 AOP 구현 기술을 간단히 알아보겠습니다.

AspectJ

Java 언어 기반의 AOP 구현 기술의 대표 주자는 AspectJ 입니다. AspectJ는 프레임워크 자체가 AOP 를 위한 프레임워크이기 때문에 가장 많은 기능을 제공하고, 가장 강력한 기능을 제공합니다. AOP 를 적용하는 시점(컴파일 타임, 로드 타임...) 에 대해서도 다양한 옵션을 제공하며, AOP 가 적용될 수 있는 대상(생성자, static 메서드, 객체 메서드...)도 가장 광범위 합니다. 실질적인 동작 방식은 컴파일 시점에 혹은 클래스 로딩 시점에 바이트 코드를 조작해서 핵심기능과 부가기능이 합쳐진 형태로 클래스의 바이트 코드를 바꿔버립니다. 하지만 AspectJ 컴파일러나 AspectJ 클래스 로더 조작기 같은 특별한 실행 옵션이 있어야 하고, 상대적으로 Learning Curve 가 높아서 실무에서 자주 사용되지는 않습니다.

Spring AOP

Spring AOP 는 Spring Framework 가 Spring Bean 을 대상으로 지원하는 AOP 구현기술입니다. Spring Bean 에만 적용할 수 있고, 메서드 실행 시에만 부가 기능을 적용할 수 있는 등의 제약 사항이 있지만, Spring 기반의 Application 에서 별도의 설정 없이 바로 사용할 수 있기 때문에 매우 실용적입니다. Spring 기반의 Application 에서 대부분의 컴포넌트는 Spring Bean 이며, 부가 기능이 필요한 상황은 대부분 메서드 호출 시점이기 때문에, 위에서 언급한 제약 사항도 Spring AOP 를 Production 환경에서 사용하는데 큰 문제가 되지는 않습니다. Spring AOP 는 Spring Bean 이 로드되는 시점에 AOP 적용대상이 되는 Bean 들을 Proxy 객체로 바꿔치기 하는 방식으로 동작합니다.

AOP 용어

AOP 에는 Aspect 외에도 여러가지 개념 요소들이 존재합니다. 각 개념 요소들을 간단히 짚어 보겠습니다.

Advice

AOP 에서 다루는 각각의 부가 기능 들을 Advice 라고 합니다. 부가 기능이 대상에 적용되는 위치에 따라 Before, After, Around 와 같이 세분화 해서 표현합니다.

JoinPoint

Advice(부가 기능) 가 적용될 수 있는 대상을 JoinPoint 라고 합니다. 메서드 실행, 생성자, static 메서드 등 AOP 를 적용할 수 있는 모든 지점을 말하며, 실제로 적용 가능한 지점은 AOP 구현 기술에 따라 달라집니다.

Pointcut

JoinPoint 중에 어떤 지점에 Advice 를 적용할 지를 정의하는 요소를 Pointcut 이라고 합니다.

Target

Pointcut 에 의해 선택된 JoinPoint 를 소유하고 있는 객체를 지칭합니다.

Aspect

Advice 와 Pointcut 으로 구성된 모듈을 의미합니다.

Weaving

AOP 구현기술에 의해 Advice 가 Pointcut 으로 지정한 JoinPoint 에 연결되는 것을 Weaving 이라고 합니다. Weaving 이 동작하는 시점에 따라 Compile Time Weaving, Load Time Weaving, Run Time Weaving 으로 구분합니다.

맺음말

이번 글에서는 AOP 를 이해하기 위한 전반적인 개요를 살펴봤습니다. AOP 는 OOP 만큼이나 광범위하게 사용되는 개발 패러다임이며 Enterprise 수준의 Application 에서는 필수적으로 사용되는 요소라고 할 수 있습니다. 때문에 Spring Framework 에서도 Spring Triangle 로 부르며 AOP 를 중요하게 다루고 있습니다. AOP 를 제대로 다루기 위해서는 각 구현 기술 상세를 정확히 아는 것도 중요하지만, AOP 자체에 대한 전반적인 이해가 반드시 선행되어야 합니다. Java 언어를 잘 다루려면 OOP 에 대한 깊은 이해가 먼저 되어야 하는 것과 같은 이치죠. 이 글이 읽으시는 분들의 AOP 에 대한 이해를 높이는데 도움이 되었기를 바라면서 마치겠습니다. 감사합니다.

'Spring' 카테고리의 다른 글

Spring Triangle - IOC, DI  (0) 2023.11.03
Spring Triangle - PSA  (0) 2023.10.24

관련글 더보기