
AOP는 프로그래밍 패러다임 중 하나로, 핵심 비즈니스 로직과 부가 기능(로깅, 보안, 트랜잭션 처리 등)을 분리하여 모듈화하는 기법이다. 이를 통해 코드의 재사용성과 유지보수성을 높일 수 있다.
| OOP (객체 지향 프로그래밍) | AOP (관점 지향 프로그래밍) | |
|---|---|---|
| 모듈화의 핵심 단위 | 클래스 (Class) | Aspect (관점, 여러 기능의 모듈화) |
| 주요 목표 | 객체 간의 상호작용을 통해 문제 해결 | 횡단 관심사(Cross-Cutting Concerns)를 분리하여 코드 관리 |
| 중점 | 캡슐화, 상속, 다형성을 통한 재사용성, 유지보수성 향상 | 중복된 코드 제거, 비즈니스 로직과 횡단 관심사 분리 |
| 적용 시점 | 컴파일 시점 | 컴파일, 런타임 등 다양한 시점에서 적용 |
| 적용 범위 | 특정 클래스나 객체의 행위 | 여러 클래스에 걸쳐 반복되는 로직 (예: 로깅, 보안, 트랜잭션 관리) |
| 코드 관리 방식 | 비즈니스 로직 중심 | 비즈니스 로직 외에 보조적인 로직을 모듈화 |
1. (메인 기능) 실행 전 : 핵심 기능이 실행되기 전에 부가 기능 실행
ex) 로그인 시도 전에 로그 기록
2. (정상적인) 실행 뒤 : 핵심 기능이 정상적으로 실행된 후 부가 기능 실행
ex) 로그인 성공 후 환영 메시지 표시
3. (비정상적인) 실행 뒤 : 핵심 기능에서 예외가 발생한 경우 부가 기능 실행
ex) 로그인 실패 시 오류 메시지 표시
4. 종료된 이후 : 핵심 기능의 실행 여부에 관계없이 종료된 후 부가 기능 실행
ex) 로그인 시도 횟수 표시
| Advice Type | 설명 |
|---|---|
| before | target 메서드 호출 이전에 실행 |
| after | target 메서드 호출 이후에 실행, Java의 finally와 유사하게 동작 |
| after returning | target 메서드가 정상적으로 동작한 후에 실행 |
| after throwing | target 메서드에서 에러가 발생한 후에 실행 |
| around | target 메서드의 실행 시기, 방법, 실행 여부를 결정 |
+--------------------+ +------------------+ +-------------------+
| 실제 메서드 호출 | ----> | 실행 시점 | --> | 공통 기능 실행 |
+--------------------+ +------------------+ +-------------------+
\ /
\ /
\ /
+-----------+
| 적용 지점 |
+-----------+
프록시 패턴은 AOP 구현의 주요 방법 중 하나로,
핵심 관심 사항과 부가 기능을 분리하는 데 사용된다.
[ 예시 코드 ]
// 사용자 인터페이스
public interface User {
void login(String username, String password);
}
// 실제 사용자 클래스
public class RealUser implements User {
@Override
public void login(String username, String password) {
System.out.println(username + "가 로그인했습니다.");
}
}
// 프록시 클래스
public class UserProxy implements User {
private RealUser realUser;
public UserProxy(RealUser realUser) {
this.realUser = realUser;
}
@Override
public void login(String username, String password) {
// 부가 기능: 로그인 시도 기록
System.out.println("로그인 시도: " + username);
try {
realUser.login(username, password);
// 부가 기능: 로그인 성공 메시지 출력
System.out.println("로그인 성공");
} catch (Exception e) {
// 부가 기능: 로그인 실패 메시지 출력
System.out.println("로그인 실패: " + e.getMessage());
}
}
}
// 메인 클래스
public class Main {
public static void main(String[] args) {
RealUser realUser = new RealUser();
User userProxy = new UserProxy(realUser);
userProxy.login("Alice", "password123");
}
}
[ 결과 ]
로그인 시도: Alice
Alice가 로그인했습니다.
로그인 성공
[ 설명 ]
UserProxy의 login 메서드가 로그인 시도 기록 및 성공/실패 메시지를 출력하는 부가 기능을 포함하고 있다.UserProxy 클래스가 Aspect 역할을 하며, 로그인 기능을 감싸고 있다.UserProxy의 login 메서드 호출 시점이 Join Point이다.UserProxy에서 특정 메서드 호출을 타겟으로 하고 있어, 포인트컷의 역할을 하고 있다.AOP는 프록시 패턴을 통해 핵심 비즈니스 로직과 부가 기능을 효과적으로 분리하여 코드의 가독성과 유지보수성을 향상시킨다. 이를 통해 개발자는 비즈니스 로직에 집중할 수 있으며, 부가 기능은 별도로 관리할 수 있게 된다는 장점이 있다. AOP는 특히 대규모 애플리케이션에서 코드의 복잡성을 줄이고, 효율적인 유지보수 환경을 제공하는 데 기여한다.