핵심 기능과 부가 기능

현재 진행하고 있는, 옥션 프로젝트에서 보면, paymet기능, auction기능 admin 기능에서 공통적으로 접근자에 대한 권한체크
가 선행되어야 한다.
이는, 도메인에 대한 핵심 로직이 아닌 권한 체크
라는 부가 기능이다.
개발을 하면서, 이 권한 체크를 반복적으로 하게 된다면 가독성이 좋지 않고, 우리 프로젝트에서는 인증 인가가 아직 도입되지 않았지만, 도입 될 경우, 토큰을 사용하는 대부분의 엔드포인트에서 권한 체크 로직을 작성해야 된다.
외에도, 아래와 같이 다양한 문제가 발생한다.
부가 기능 적용 문제
- 부가 기능을 적용할 때 아주 많은 반복이 필요
- 부가 기능이 여러 곳에 퍼져서 중복 코드를 발생
- 부가 기능을 변경할 때 중복 때문에 많은 수정이 필요
- 부가 기능의 적용 대상을 변경할 때 많은 수정이 필요
💡 그렇다면, 여러 곳에서 공통으로 사용하고 있는 부가 기능을 모듈화
해서 한 곳에 보관할 수 없을까?
AOP
관점 지향 프로그래밍으로, 부가 기능을 핵심 기능에서 분리하고, 한 곳에서 관리해보자는 것에서 시작된 개념
⇒ 핵심 기능과 부가 기능을 분리 목적
JAVA에서 AOP를 구현할 수 있는 방법
1. AspectJ 프레임워크를 직접 이용
- AOP의 대표적인 구현으로, AspectJ 프레임워크가 있다.
2. Spring AOP 이용
schema based approach
- AOP 설정을 XML 파일에서 정의하는 방식
- 스프링 설정 파일(
applicationContext.xml
)에 <aop:config>
와 <aop:aspect>
등의 태그를 사용
@AspectJ annotaion style
- AspectJ 스타일의 어노테이션(
@Aspect
, @Before
, @Pointcut
)을 사용하여 AOP를 정의
- Spring aop는 AspectJ를 직접 사용하는 것은 아니다. AspectJ 문법을 차용했을 뿐

AOP 적용 방식
AOP를 통해 부가 기능 로직은 어떤 방식으로 실제 로직에 추가될 수 있을까?
- 컴파일 시점
- 클래스 로딩 시점
- 런타임 시점(프록시)
1. 컴파일 시점 (컴파일 타임 위빙)
- 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함
- .java 가 컴파일 되면서 .class가 되는 시점에 발생
- AspectJ 컴파일러가 컴파일 시점에, AspectJ 모듈을 적용 대상에 로직을 붙인다
- 복잡하다는 단점
- AspectJ 프레임워크를 이용해서만 구현 가능
2. 클래스 로딩 시점 (로드 타임 위빙)
- 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함
- 자바를 실행하면 자바 언어는 .class 파일을 JVM 내부의 클래스 로더에 보관한다. 이때 로더에 올리는 시점에 중간에서 .class 파일을 가로채 조작한 다음 JVM에 올림
- 복잡하다는 단점
- AspectJ 프레임워크를 이용해서만 구현 가능
3. 런타임 시점 (런타임 위빙)
- 실제 대상 코드는 그대로 유지 됨
- 컴파일이 끝나고, 클래스 로더에 클래스도 다 올라가서 이미 자바가 실행되고 난 다음(main 메서드가 이미 실행된 다음)에 Aop가 적용 됨
- 자바 언어가 제공하는 범위 안에서 부가 기능을 적용해야 함
- 프록시를 통해 스프링 빈에 부가 기능을 적용할 수 있음
- 프록시를 사용하기 때문에, 메서드 실행지점에만 적용 가능
- Spring AOP는 이 방식을 사용
AOP 적용 위치
- 적용 가능 지점(조인 포인트): 생성자, 필드 값 접근, static 메서드 접근, 메서드 실행
- 이렇게 AOP를 적용할 수 있는 지점을 조인 포인트(Join point)라 한다.
- AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트코드를 실제 조작하기 때문에 해당 기능을 모든 지점에 다 적용할 수 있다.
- 프록시 방식을 사용하는 스프링 AOP는 메서드 실행 지점에만 AOP를 적용할 수 있다.
- 프록시는 메서드 오버라이딩 개념으로 동작한다.
- 따라서 생성자나 static 메서드, 필드 값 접근에는 프록시 개념이 적용될 수 없다.
- 프록시를 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한된다
- 프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다
AOP 기본 용어

[Join Point] 어디에 적용할 것인가
- AOP를 적용할 수 있는 모든 지점을 의미한다
- 추상적인 개념
- 스프링 AOP는 프록시 방식을 사용하므로 조인 포인트는 항상 메서드 실행 지점으로 제한
- 조인 포인트는 가능한 위치를 의미하며, 실제 적용되는 지점은 포인트컷으로 필터링
- 타겟 객체의 메서드 실행 시점
- JointPoint 인터페이스의 메서드
getArgs() | 메서드 아규먼트를 반환 |
---|
getThis() | 프록시 객체를 반환 |
getTarget() | 대상 객체를 반환 |
getSignature() | 어드바이스 또는 메서드의 설명(description)을 반환 |
toString() | 어드바이스 되는 메서드의 설명을 출력한다. |
[Pointcut] 좀 더 자세히, 어디에?
- 어드바이스를 적용할 조인 포인트를 선별
- 특정 조건에 의해 필터링 된 조인 포인트
- 메서드 선택 기준이라고 생각하면 된다
- 실제 Advice가 적용되는 지점
- 스프링 AOP에서는 메서드 PointCut의 대상
- 프록시를 사용하는 스프링 AOP는 메서드 실행 지점만 포인트컷으로 선별 가능
[Target] 부가 기능을 부여할 대상
[Advice] 어떤 부가 기능을 부여할 것인가
- 특정 조인 포인트에 적용할 부가 기능
- 어느 시점에, 어떤 기능을?
- 부가 기능 실행되는 시점을 지정할 수 있다
@Before | 메서드 실행 전에 실행 |
---|
@After | 메서드 실행 후에 실행(예외 발생 되더라도 실행 됨) |
@AfterReturning | 메서드가 정상적으로 종료된 후 실행 |
@AfterThrowing | 메서드에서 예외가 발생한 후 실행 |
@Around | 메서드 실행 전후를 모두 제어 |
[Aspect] 어드바이스 + 포인트 컷을 모듈화 한 것
- Spring에서는 클래스에
@Aspect
어노테이션을 사용하여 정의
- 여러 어드바이스와 포인트 컷이 함께 존재
- 횡단 관심사를 캡슐화 한 모듈 → AOP를 모아둔 클래스
[Advisor] 하나의 어드바이스 + 하나의 포인트 컷
- 어떤 메서드에 어느 시점에 어떤 기능을 부여할 것인지?
- 스프링 AOP에서만 사용되는 용어
[Weaving] 어드바이스를 적용하는 동작
- 포인트 컷으로 결정한 타겟의 조인 포인트에 어드바이스를 적용하는 것
- 핵심 기능에 영향을 주지 않고 부가 기능을 추가할 수 있음
- 스프링 AOP에서는 Runtime Weaving을 사용
- Aspect와 애플리케이션 코드를 결합하는 과정