본문 바로가기

TIL

[SpringFramework][AOP]

728x90
  • AOP(Aspect Oriented Programming : 관심 지향 프로그래밍)란?

OOP(object Oriented Programming)란 객체지향 프로그래밍 즉, 객체 간의 관계를 지향하는 프로그래밍 방식

관심(Aspect)을 지향하는 프로그래밍에서 관심은 ?

위 그림처럼 아기를 키우는 부모들의 육아방식이나 교육방식은 제각각 다를 수 있다 어떤 부모는 아기를 재우기 위해 아기띠를 하는 반면, 어떤 부모는 침대에 눕혀놓고 재우기도 한다. 그리고 어떤 부모들은 언어의 발달을 위해서 책을 읽어주는 시간을 많이 가지는 반면, 어떤 부모 들은 책 보다 동요를 더 많이 들려주는 방식으로 아기의 언어 발달을 도우려 한다.

부모들의 키우는 방식이 각자 다를 수 있지만 공통되는 부분도 있다 그것은 아기의 건강이다

어떤 식으로 아기를 키우든지 아기를 키우는 방식과 별개로 아기가 아프지 않고 잘 자라주었으면 하는 바램은 대부분 부모의 공통 관심사이다.

AOP에서 Aspect는 부모들이 가지고 있는 아기의 건강 같은 공통 관심사와 마찬가지로 애플리케이션에 필요한 기능 중에서 공통적으로 적용되는 공통 기능에 대한 관심과 관련이 있다.

공통 관심 사항과 핵심 관심사항

애플리케이션을 개발하다 보면 애플리케이션 전반에 걸쳐 공통적으로 사용되는 기능들이 있기 마련인데, 이러한 공통 기능들에 대한 관심사를 바로 공통 관심 사항이라고 한다

그리고 우리가 흔히들 말하는 비즈니스 로직 즉, 애플리케이션의 주목적을 달성하기 위한 핵심 로직에 대한 관심사를 핵심 관심사항이라고 한다

 

핵심 관심사항에 반대되는 개념으로 공통 관심사항을 부가적인 관심사항이라고 표현하기도 한다.

 

커피 주문을 위한 애플리케이션을 예로 들면

커피 전문점의 주인이 고객에게 제공하는 커피 메뉴를 구성하기 위해 커피 종류를 듬뿍하려는 것과 고객이 마시고 마시고 싶은 커피를 주문하는 기능은 애플리케이션의 핵심 관심 사항에 해당된다.

하지만 커피 주문 애플리케이션에 아무나 접속하지 못하도록 제한하는 애플리케이션 보안에 대한 부분은 애플리케이션 전반에 공통적으로 적용되는 기능이기 때문에 공통 관심사항에 해당된다.

 

로깅, 보안, 트랜잭션 같은 공통 관심 사항 기능들의 화살표가 애플리케이션의 핵심 관심사항들을 관통하고 있다. 이것은 공통 관심사항의 기능들이 애플리케이션의 핵심 로직에 전반적으로 두루 사용된다는 의미이다.

그리고 그림에서 보면 공통 관심사항이 핵심 관심사항에 멀찌감치 떨어져 있는 것을 볼 수 있는데 이는 공통 관심사항이 핵심 관심 사항에서 분리되어있다는 것을 의미한다.

결국 AOP라는 것은 애플리케이션의 핵심 업무 로직에서 로깅이나 보안, 트랜잭션 같은 공통 기능 로직들을 분리하는 것이라 생각하면 된다.

 

  • AOP가 필요한 이유
  1. 코드의 간결성 유지
  2. 객체지향 설계 원칙에 맞는 코드 구현
  3. 코드의 재사용

애플리케이션의 핵심 로직에 공통적인 기능의 코드들이 여기저기 보이면 코드 자체가 복잡해진다. 코드 구성이 복잡해짐에 따라 버그가 발생할 가능성도 높아지고 유지 보수도 어려워지는 코드가 될 가능성이 높다

그리고 이런 공통 기능들에 수정이 필요하게 되면 애플리케이션 전반에 적용되어 있는 공통 기능에 해당하는 코드를 일일이 수정해야 되는 치명적인 문제가 발생할 가능성이 높다.

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();
    }
}

코드 1. AOP가 적용되지 않는 JDBC 트랜잭션 예 

 

트랜잭션이란 데이터를 처리하는 하나의 작업 단위를 의미한다. 예를 들어 데이터베이스에 A데이터와 B데이터를 두 번에 걸쳐 insert 하는 작업을 하나의 트랜잭션으로 묶는다면 A데이터와 B데이터는 모두 데이터베이스에 저장되던가 아니면 둘 중에 하나라도 오류로 인해 저장되지 않는다면 A, B데이터 모두 데이터베이스에 반영되지 않아야 한다 (All orNothing)

이러한 처리를 위해 일반적으로 트랜잭션에는 커밋 또는 롤백이라는 기능이 있다. 

커밋은 모든 작업이 성공적으로 수행되었을 때 수행한 작업을 데이터 베이스에 반영한 것이고

롤백은 작업 하나라도 실패한다면 이전에 성공한 작업들을 작업 수행 이전에 상태로 되돌리는 것을 말한다

 

그리고 코드 1에서는 Java의 JDBC API를 사용했는데 JDBC API를 사용할 일은 없지만 AOP를 설명하기에 적절한 예시여서 코드의 흐름만 이해하면 된다.

코드 1의 registerMember() 메서드는 커피 주문 애플리케이션을 사용할 회원 정보를 등록하는 기능을 한다.

registerMember() 메서드 내에서 실제로 비즈니스 로직을 수행하는 코드는 회원 정보를 저장하는(2)의 saveMember()와 회원의 포인트 정보를 저장하는 savePoint()이다

이 외에 1)의 connection.setAutocommit(false)이나 3)의 connection.commit(),4)의 connection.rollback()은 saveMember()와 savePoint() 작업을 트랜잭션으로 묶어서 처리하기 위한 기능들이다.

문제는 이렇게 트랜잭션 처리를 하는 코드들이 애플리케이션의 다른 기능에도 중복되어 나타날 것이라는 거다.

중복된 코드를 공통화해서 재사용하도록 만드는 작업은 AOP를 통해 할 수 있다.

Spring에서는 이미 이런 트랜잭션 처리 기능을 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를 이용한 포인트 정보 저장
    }
}

코드 2. Spring AOP 기능이 적용된 JDBC 트랜잭션 예

코드 2는 Spring의 AOP기능을 사용하여 registerMember()에 트랜잭션을 적용한 예제 코드며, 트랜잭션 처리를 위한 코드들이 사라지고 순수하게 비즈니스 로직을 처리하기 위한 saveMember(member)와 savePoint(point)만 남은 것을 볼 수 있다.

트랜잭션 처리는 1)의 @Transactional 애노테이션 하나만 붙이면 Spring 내부에서 이 애노테이션 정보를 활용해서 AOP기능을 통해 트랜잭션을 적용한다.

 

이처럼 AOP를 활용하면 애플리케이션에 전반에 걸쳐 적용되는 공통 기능(트랜잭션, 로깅, 보안, 트레이싱, 모니터링)등을 비즈니스 로직에서 깔끔하게 분리하여 재사용 가능한 모듈로 사용할 수 있다.

 

Point

  • AOP는 관심 지향 프로그래밍이다
  • AOP에서 의미하는 Aspect는 애플리케이션의 공통 관심사를 의미한다
  • 애플리케이션의 공통 관심사는 비즈니스 로직을 제외한 애플리케이션 전반에 걸쳐서 사용되는 공통 기능들을 의미한다
  • 애플리케이션 전반에 걸쳐서 사용되는 공통 기능에는 로깅,보안,트랜잭션,모니터링,트레이싱 등의 기능이 있다
  • AOP를 애플리케이션에 적용하면 /코드의 간결성 유지, 객체 지향 설계 원칙에 맞는 코드 구현 / 코드의 재사용 과같은 이점을 누릴수있다. 

 

 

728x90

'TIL' 카테고리의 다른 글

[Spring][SpringMVC][Controller][패키지구조]  (0) 2022.10.21
[Spring MVC] [Spring API계층]  (0) 2022.10.20
[SpringFramework][IoC/DI기초]  (0) 2022.10.15
[SpringFramework][POJO]  (0) 2022.10.14
[Spring Framework][사용하는 이유]  (0) 2022.10.14