[Spring AOP는 왜 필요할까?]
Spring으로 백엔드를 개발하다 보면 다음과 같은 코드들이 눈에 들어오기 시작한다.
@Service
public class OrderService {
public void order() {
System.out.println("로그 시작");
// 주문 처리 로직
System.out.println("로그 끝");
}
}
이러한 코드들은 처음엔 아무 문제 없어 보인다.
하지만 프로젝트가 조금만 커져도 다음과 같은 상황이 된다.
- 모든 서비스 메스드에 로그처리
- 모든 메서드에 트랜잭션 처리
- 권한 체크 코드가 여기저기 생성
이러한 상황에 놓일 때 이런 생각이 든다.
"이러한 코드들은 주문과 직접적인 관계가 없지 않나?"
이런 질문에서 출발한 개념이 바로 AOP이다.
[Spring 애플리케이션에는 두 종류의 코드가 있다]
Spring애플리케이션의 코드는 크게 보면 두 가지로 나누어 진다.
1. 핵심 관심사(Core Concern)
- 주문로직
- 회원 저장로직
- 결제 처리 로직
>>> 서비스가 진짜로 해야 할 일
2. 공통 관심사(Cross-Cutting Concern)
- 로그 남기기
- 트랜잭션 관리
- 보안 체크
- 성능 측정
>>> 여러 곳에서 반복되지만 본질은 아닌 일
1번과 2번이 하나의 메서드 안에 섞여버린다는 점이다.
[공통 관심사가 섞이면 어떠한 문제가 생기는걸까?]
로그 시작
권한 체크
트랜잭션 시작
비즈니스 로직
트랜잭션 종료
로그 종료
이런 코드가 있다고 가정하자
위 같은 상태가 된다면 코드를 읽기 힘들고, 수정할 때 실수를 할 수 도 있으며, 이 메서드가 정확히 뭘 하는지 한눈에 들어오지 않게된다,
즉, 비즈니스 로직에 집중하기 어려운 코드가 되는것이다.
Spring AOP는 이 문제를 이렇게 해결한다
"공통 관심사는 따로 빼서 필요한 순간에만 자동으로 끼워 넣자"
[그래서 Spring AOP가 뭘까?]
Spring AOP를 한 문장으로 말하면 다음과 같다.
'AOP는 공통 관심사를 핵심 로직에서 분리하는 방식이다.'
여기서 중요한 점은 "기능을 추가하되, 기존 코드는 건드리지 않는다"는 점이다.
[실제 Spring AOP코드를 읽어보자]
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service..*(..))")
public void logBefore() {
System.out.println("메서드 실행 전 로그");
}
}
이 코드를 읽어보면 다음과 같다
"service패키지 안의 모든 메서드가 실행되기 전에 이 로그를 자동으로 실행해 줘"
중요한 점은 서비스 코드는 수정하지 않고 로그는 자동실행 된다는 점에서 관심사를 완전히 분리한 것이다.
[Spring AOP는 어떻게 몰래 끼어드는 것일까?]
여기서 중요한 개념이 하나 나오는데 그것은 바로 프록시(Proxy)이다.
Spring은 실제 객체 대신 프록시 객체를 하나 더 만들어서 중간에 세운다.
클라이언트
↓
프록시 객체 (AOP 처리)
↓
실제 서비스 객체
우리는 서비스 객체를 호출한다고 하지만 실제로는 프록시가 먼저 호출된다.
그리고 프록시는 필요한 AOP로직을 실행한 후 진짜 객체에게 일을 넘긴다.
그래서 AOP가 있는지도 모른 채 코딩을 할 수 있다.
[사실 우리는 이미 AOP를 사용하고 있다]
사실 Spring을 쓰고 있다면 이미 AOP를 매일 사용하고 있는데 대표적인 예는 다음과 같다.
@Transactional
public void order() {
// 비즈니스 로직
}
이 한줄의 의미는 다음과 같다.
"메서드 실행 전 트랜잭션을 시작하고, 정상 종료라면 커밋을 예외 발생이라면 롤백을 한다."
이 모든 걸 개발자가 직접 쓰지 않아도 되는 이유가 바로 AOP로 감싸져 있기 때문이다.
[마지막 정리하며]
1. AOP는 공통 관심사를 분리하기 위한 Spring의 기술이다
2. Spring AOP는 프록시 객체로 동작한다
3. Spring AOP의 목표는 비즈니스 로직을 더 깨끗하게 만드는 것이다.
'Spring' 카테고리의 다른 글
| [SpringBoot] 스프링부트 톰캣 포트 변경하는 법 (0) | 2021.10.19 |
|---|---|
| [Spring][링크] tiles이란? (0) | 2021.01.18 |
| [Spring][MVN][링크] Spring test란? (0) | 2021.01.18 |
| [Spring] ViewResolver(뷰 합성기) (0) | 2020.12.10 |