공부해봅시당

[쉽게 배우자! Spring Triangle 2] AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)를 쉽게 이해해보자(feat. IoC/DI) 본문

STUDY/Spring

[쉽게 배우자! Spring Triangle 2] AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)를 쉽게 이해해보자(feat. IoC/DI)

tngus 2024. 2. 23. 00:42

Spring은 Spring Triangle이라고 부르는 핵심 3대요소를 제공해준다

이는 각각 IoC, AOP, PSA를 일컫는다

 

 

오늘은 AOP에 대해 알아보자

 


 

AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)을 [회사 생활하기]라는 비유로 이해해보자

회사에서 내가 모든 일을 해야하는 경우: 관점 지향적이지 않은 경우

나는 회사에서 근무하고 있고, 나에게 주어진 업무가 아주 많다고 해보자

보고서 작성, 회의 준비, 고객 응대, 프로젝트 관리, 심지어는 사무실 청소와 같은 일까지 모든 것을 직접 해야 한다

여기서는 내가 모든 일의 책임자이며, 모든 업무 프로세스를 직접 관리해야 한다

이런 상황에서는 핵심 업무에 집중하기보다는 다양한 부가적인 업무에 시간과 에너지를 분산시켜야 하기 때문에

업무 효율성이 떨어질 수 있다

 

결과적으로, 중요한 업무의 질이 떨어지거나, 업무 처리 시간이 길어질 수 있다

 

내가 맡은 업무에만 집중하는 경우: 관점 지향적인 경우

회사에서 모든 일을 도맡아 진행하며 지친 내가 사장에게 따져 주요 업무에만 집중할 수 있는 프로세스를 구축하도록 항의했다고 하자

 

사장은 내가 주요 업무에만 집중할 수 있도록, 부가적인 업무는 전문 팀이나 시스템이 관리하도록 변경했다

사무실 관리, IT 지원, 인사 관리와 같은 부가적인 업무는 해당 분야의 전문 팀이 담당하도록 했다

그래서 나는 보고서 작성과 프로젝트 관리와 같은 핵심 업무에 집중할 수 있게 되었다


구조가 변경되어 나는 전문성을 최대한 발휘할 수 있게 되었으며, 업무의 효율성과 만족도가 높아질 수 있었다

부가적인 업무에 신경 쓸 필요 없이, 주요 업무의 품질을 높이는 데 집중할 수 있기 때문이다

 

정리하면

회사에서 내가 모든 일을 해야하는 경우는 핵심 업무와 부가적인 업무가 분리되지 않은 상태이고,

내가 맡은 업무에만 집중하는 경우는 핵심 업무에 집중할 수 있도록 부가적인 업무는 전문 팀이나 시스템이 담당하는 상태이다

 

AOP는?

소프트웨어에서의 AOP도 동일하다

 

AOP가 소프트웨어 개발에서 공통적인 기능(예: 로깅, 보안 체크)을 핵심 비즈니스 로직과 분리하여 관리하듯, 회사 업무에서도 중요한 업무에 더 집중할 수 있도록 도와주는 것과 같다

 

여기서 여러 모듈에 나타나는 공통적인 기능을 횡단관심이라고 한다

 

은행 업무를 처리할 때 대표적인 기능은 입금, 출금, 이체가 있을 수 있다

해당 기능들은 모두 로깅과 보안, 트랜젝션이라는 공통 관심사가 존재한다

 

그러한 공통 관심사를 횡단관심이라고 부른다

 

이미지로 표현하면 아래 그림과 같다

 

 

따라서 AOP를 다시 표현하면 횡단 관심사(=공통 기능)를 분리하여 관리한다고 말할 수 있다

 

AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)

AOP는 횡단 관심사(cross-cutting concerns)를 주요 비즈니스 로직으로부터 분리하여 관리하는 프로그래밍 패러다임입니다. 로깅, 보안, 트랜잭션 관리와 같은 기능들이 애플리케이션의 여러 부분에 걸쳐 필요하지만, 이를 각각의 비즈니스 로직에 직접 구현하면 코드의 중복과 결합도가 증가합니다. AOP는 이러한 횡단 관심사를 분리하여, 애플리케이션의 핵심 로직을 깔끔하게 유지하도록 돕습니다.

 

코드로 확인해보자

위에서 은행 업무를 처리할 때 대표적인 기능은 입금, 출금, 이체가 있을 수 있고, 로깅은 여러 모듈에 나타나는 횡단관심이라고 설명한 바 있다

 

이를 코드를 통해 확인해보자

AOP 적용 전: 로깅 코드 직접 삽입

AOP를 적용하지 않았을 때, 각 메소드에 로깅 코드를 직접 삽입해야 한다

이는 코드 중복과 핵심 비즈니스 로직과의 혼합을 초래한다

 

아래에서 반복적으로 나타나는 부분이 횡단 관심 사항이다

public class BankService {
    public void deposit(double amount) {
        long startTime = System.currentTimeMillis();
        
        // 입금 처리 로직
        System.out.println(amount + "가 입금되었습니다.");
        
        long endTime = System.currentTimeMillis();
        System.out.println("deposit 실행 시간: " + (endTime - startTime) + "ms");
    }
    
    public void withdraw(double amount) {
        long startTime = System.currentTimeMillis();
        
        // 출금 처리 로직
        System.out.println(amount + "가 출금되었습니다.");
        
        long endTime = System.currentTimeMillis();
        System.out.println("withdraw 실행 시간: " + (endTime - startTime) + "ms");
    }
    
    public void transfer(double amount) {
        long startTime = System.currentTimeMillis();
        
        // 이체 처리 로직
        System.out.println(amount + "가 이체되었습니다.");
        
        long endTime = System.currentTimeMillis();
        System.out.println("transfer 실행 시간: " + (endTime - startTime) + "ms");
    }
}

 

AOP 적용 후: 로깅 로직 분리 및 자동 적용

AOP를 제대로 적용하기 위해서는 build.gradle에 aop를 implements 해주어야 한다

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-aop'
}

 

주의!
'spring-boot-starter-web'를 build.gradle에서 이미 implements하고 있는 경우(아래와 같은 상황), 'spring-boot-starter-aop'를 적용하지 않아도 aop 코드가 정상동작한다
dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' }

하지만 AspectJ와 관련된 고급 AOP 기능을 모두 사용하기 위해서는 명시적으로 작성해주는 것이 좋다
'spring-boot-starter-web'에 포함되어 있는 aop 기능만으로는 AspectJ의 고급 기능이나 일부 AOP 기능이 제한될 수 있다

 

 

AOP를 적용하면, 로깅 로직을 별도의 Aspect로 정의하고 은행 업무 처리 메소드에 자동으로 적용할 수 있다

이는 코드의 중복을 방지하고, 업무 로직과 로깅 로직을 분리한다

@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.example.service.BankService.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        Object result = joinPoint.proceed(); // 핵심 비즈니스 메소드 실행
        
        long endTime = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature().getName() + " 실행 시간: " + (endTime - startTime) + "ms");
        
        return result;
    }
}

 

BankService.java는 아래와 같이 변경된다

public class BankService {
    // 입금 처리
    public void deposit(double amount) {
        // 입금 처리 로직
        System.out.println(amount + "가 입금되었습니다.");
    }
    
    // 출금 처리
    public void withdraw(double amount) {
        // 출금 처리 로직
        System.out.println(amount + "가 출금되었습니다.");
    }
    
    // 이체 처리
    public void transfer(double amount) {
        // 이체 처리 로직
        System.out.println(amount + "가 이체되었습니다.");
    }
}

 

 

 


IoC/DI vs AOP

(IoC와 DI에 대해서는 이전 포스팅에 작성되어 있으니 참고하길 바란다)

공부를 하다보면 IoC/DI와 AOP가 어떤 관계가 있는지 헷갈릴 수 있다

 

따라서 IoC/DI와 AOP에 대해 명확하게 정리하고자 한다

각각의 개념부터 다시 확인해보자

개념 이해하기

IoC (Inversion of Control) / DI (Dependency Injection)

IoC는 프로그램의 제어 흐름을 직접 관리하는 대신, 외부 컨테이너나 프레임워크에 위임하는 프로그래밍 원칙이다

이를 통해 프로그램의 유연성과 확장성을 높일 수 있다

DI는 IoC의 가장 대표적인 실현 방법 중 하나이다

객체가 필요로 하는 의존성을 외부(프레임워크나 컨테이너)에서 직접 주입해주는 방식을 말한다

이를 통해 객체 간의 결합도를 낮추고, 테스트와 유지보수를 용이하게 한다

 

AOP (Aspect-Oriented Programming)

AOP는 애플리케이션의 핵심 로직과 분리하여 관심사(예: 로깅, 보안, 트랜잭션 관리 등)를 모듈화하는 프로그래밍 패러다임이다

AOP는 IoC의 원칙을 "활용"한다

따라서 AOP 자체를 IoC의 한 형태라고 보기보다는, AOP는 IoC 원칙을 기반으로 한 별도의 접근 방식이라고 이해하는 것이 더 적절하다

AOP와 DI의 관계 이해하기

DI(의존성 주입)를 이용하여 IoC(제어의 역전) 구현

객체의 생성과 의존성 관리를 외부에 위임함으로써, 제어의 역전을 실현한다

DI는 객체 간의 결합을 줄이고, 의존성 관리를 외부(예: 스프링 컨테이너)에 맡긴다

 

IoC(제어의 역전)를 활용하여 AOP(관점 지향 프로그래밍) 구현

IoC를 활용하여 AOP를 구현한다는 것을 풀어서 말하면 아래와 같다

IoC를 활용하여 == 프로그램이 스스로 중요하지 않은 일을 처리하도록 만들어서(IoC, 제어의 역전)
AOP를 구현한다 == 프로그래머가 더 중요한 일에 집중할 수 있도록 돕는 방법(AOP, 관점 지향 프로그래밍)

 

즉, AOP는 애플리케이션 전반에 걸친 공통 관심사의 구현을 외부(예: 프레임워크 등)위임(예: 스프링 AOP를 통한 어드바이스 정의 및 적용)함으로써 IoC 원칙을 활용한다

이 경우 개발자는 핵심 비즈니스 로직에 집중할 수 있으며, 공통 관심사는 분리된 어스펙트(Aspect)를 통해 관리된다

 

 

정리하면

DI는 IoC의 구현 방법 중 하나로 객체 간의 의존성을 관리하는 데 초점을 맞추고,

AOP는 IoC 원칙을 활용하여 애플리케이션의 공통 관심사를 모듈화하고 관리하는 데에 사용된다

 

이 둘은 IoC의 원칙 아래에서 각각 다른 문제를 해결하기 위해 사용되는 기술이다

 


참조

https://expert0226.tistory.com/200

 

008. AOP - Aspect? 관점? 핵심관심사항? 횡단관심사항?

스프링의 핵심 그 두번째는 AOP 입니다. AOP 의 풀영문은 Aspect-Oriented Programming 이고 이걸 한글화 했더니 관점 지향 프로그래밍이 되어버립니다. 그럼 관점이란 또 무엇이냐를 따지고 싶겠지만 그

expert0226.tistory.com