AOP에서의 Aspect는 부모들이 가지고 있는 아기의 건강 같은 공통 관심사와 마찬가지로 애플리케이션에 필요한 기능 중에서 공통적으로 적용되는 공통 기능에 대한 관심과 관련이 있다.
애플리케이션을 개발하다보면 애플리케이션 전반에 걸쳐 공통적으로 사용되는 기능들이 있는데, 이러한 공통 기능들에 대한 관심사를 바로 공통 관심 사항(Cross-cutting concern)이라고 한다.
핵심 관심 사항에 반대되는 개념으로 공통 관심 사항을 부가적인 관심 사항이라고 표현하기도 한다.
그리고 우리가 흔히들 말하는 비즈니스 로직 즉, 애플리케이션의 주목적을 달성하기 위한 핵심 로직에 대한 관심사를 핵심 관심 사항(Core concern)이라고 한다.
CASE : 커피 주문을 위한 애플리케이션
커피 전문점의 주인이 고객에게 제공하는 커피 메뉴를 구성하기 위해 커피 종류를 등록하는 것과 고객이 마시고 싶은 커피를 주문하는 기능은 애플리케이션의 핵심 관심 사항에 해당한다.
하지만 커피 주문 애플리케이션에 아무나 접속하지 못하도록 제한하는 애플리케이션 보안에 대한 부분은 애플리케이션 전반에 공통적으로 적용되는 기능이기 때문에 공통 관심 사항에 해당한다.
공통 관심 사항의 기능들이 애플리케이션의 핵심 로직에 전반적으로 두루 사용된다는 의미다.
또한, 공통 관심 사항은 핵심 관심 사항에서 분리되어 있다.
결국 AOP라는 것은 애플리케이션의 핵심 업무 로직에서 로깅이나 보안, 트랜잭션 같은 공통 기능 로직들을 분리하는 것이다.
public class Example2_11 {
private Connection connection;
public void registerMember(Member member, Point point) throws SQLException {
connection.setAutoCommit(false); // (1)
try {
saveMember(member); // (2)
savePoint(point); // (2)
connection.commit(); // (3)
} catch (SQLException e) {
connection.rollback(); // (4)
}
}
private void saveMember(Member member) throws SQLException {
PreparedStatement psMember =
connection.prepareStatement("INSERT INTO member (email, password) VALUES (?, ?)");
psMember.setString(1, member.getEmail());
psMember.setString(2, member.getPassword());
psMember.executeUpdate();
}
private void savePoint(Point point) throws SQLException {
PreparedStatement psPoint =
connection.prepareStatement("INSERT INTO point (email, point) VALUES (?, ?)");
psPoint.setString(1, point.getEmail());
psPoint.setInt(2, point.getPoint());
psPoint.executeUpdate();
}
}
애플리케이션 전반에 걸쳐서 트랜잭션 관련한 중복된 코드가 수도 없이 나타난다면 중복된 코드를 공통화해서 재사용 가능하도록 만들어야 한다. 그리고 이 공통화 작업은 AOP
를 통해서 할 수 있다.
@Component
@Transactional // (1)
public class Example2_12 {
private Connection connection;
public void registerMember(Member member, Point point) throws SQLException {
saveMember(member);
savePoint(point);
}
private void saveMember(Member member) throws SQLException {
// Spring JDBC를 이용한 회원 정보 저장
}
private void savePoint(Point point) throws SQLException {
// Spring JDBC를 이용한 포인트 정보 저장
}
}
트랜잭션 처리를 위한 코드들이 모두 사라지고 순수하게 비즈니스 로직을 처리하기 위한 saveMember(member)
와 savePoint(point)
만 남은 것을 볼 수 있다.
바로 (1)의 @Transactional
애노테이션 하나만 붙이면 Spring 내부에서 이 애노테이션 정보를 활용해서 AOP 기능을 통해 트랜잭션을 적용한다.
이처럼 AOP를 활용하면 애플리케이션에 전반에 걸쳐 적용되는 공통 기능(트랜잭션, 로깅, 보안, 트레이싱, 모니터링) 등을 비즈니스 로직에서 깔끔하게 분리하여 재사용 가능한 모듈로 사용할 수 있다.