Spring Core/03. AOP

01. AOP 기본 컨셉

  • -
반응형

AOP

스프링의 특징을 딱 두 가지만 들어보라면 앞서 배운 DI와 지금 소개할 AOP이다. 사실 AOP는 프로젝트 과정에서 적극적으로 사용하지 않을 수도 있지만 스프링 내부적으로 어마어마하게 많이 사용되고 있는 기술이다. 무언가 스프링이 처리하는 마법 같은 일들은 대부분 AOP의 결과인 것들이 많다.

과연 AOP란 무엇일까?

 

AOP(Aspect Oriented Programming: 관점 지향 프로그래밍)란?

AOP는 사실 용어조차 추측하기 힘들다. 어떤 "관점을 기반으로 프로그래밍 한다"는 이야기인데 찬찬히 살펴보자.

일상생활에서의 관점과 관점 지향적 삶

먼저 일상 생활에서 "관점"이라는 것을 생각해 보자. 

우리는 사무실, 식당, 헬스장 등 다양한 공간에서 다양한 일을 한다. 사무실에서는 업무를 처리하고, 식당에서 식사를 하며, 헬스장에서 운동을 한다. 각 공간에서 수행하는 일은 서로 다르다. 이런 공간을 사용할 때, 해야 할 또는 하고 싶은 일들만 하는 것은 아니다. 아마도 대부분 지저분한 곳에서는 활동하기 싫어서 청소를 먼저 하고 사용하게 된다.

이 "청소"라는 것에 집중해보자.

청소는 대부분의 공간에서 필요한 작업이다.  그러나 각 공간에서 해야 할 일들과 직접적인 연관은 없다. 사용자 입장에서는 매우 귀찮은 작업이며, 손이 많이 가는 전문적인 일이기도 하다. 만약 우리가 이 작업을 직접 한다면 업무 효율은 떨어질 수밖에 없을 것이다.

청소는 꼭 필요한일이지만 막상 하자니 쉽지 않다.

 

실제 우리 생활에서는 어떨까? 사실 많은 사람들이 이런 공간을 청소해본 적이 없을 것이다. 대부분 공간에는 청소의 관점에서만 이런 공간을 바라보는 "청소 전문가"가 있기 때문이다.  청소 전문가는 오로지 청소만 생각하므로 청소에 관해서는 완벽하다. 하지만 '거기서 어떤 일이 일어나는가?'는 관심 사항이 아니다 

 

청소가 필요한 분은 청소 전문가를 찾아주세요.

 

청소뿐 아니라 보안 등 다양한 분야에서 이런 전문가들이 활동한다면 우리는 좀 더 하고 싶은 일에 전념할 수 있게 될 것이다.

 

일반적인 프로그래밍 코드의 문제점

이제 프로그래밍으로 와보자. 다음은 JDBC를 이용한 코드의 부분으로 전달받은 Buddy 정보를 DB에 저장하기 위한 것이다. 지적질을 하고 싶은 코드이기 때문에 코드를 상세히 읽어볼 필요는 없다. 대략 주석을 통해서 흐름만 살펴보자.

@Slf4j
public class BuddyServiceImpl implements BuddyService {
    @Autowired
    private BuddyRepo repo;
    public void writeBuddy(Buddy buddy) {          
      log.trace("buddy : " +buddy);             // 메서드 로깅 
      long start = System. currentTimeMillis(); // 성능 측정 시작
      Connection con = null;
      try{                  
          con = DB Connection을 얻는 코드       // 리소스 관리 - DB 접속           
          con.setAutoCommit(false);             // 트랜젝션 처리 시작               
          repo.insert(con, buddy);              // 자료 저장 - 비즈니스 로직 
          con.commit();                         // 트랜잭션 처리 - 커밋
      }catch(Exception e){        
          con.rollback();                       // 트랜잭션 처리 - 롤백           
      }finally{          
        con.close();                            // 리소스 관리 - 접속 반환
      }
      long end = System.currentTimeMillis();    // 성능 측정 종료
      log.trace("소요시간: {}", end-start);     // 메서드 로깅     
    }
}

약 20여 줄의 코드 중 주요 목적(core concern) 즉 비즈니스 로직은 repo.insert(con, buddy) 부분이다. 나머지 connection 처리, transaction 처리, 로깅, 성능 측정 등은 비즈니스 로직과는 상관 없이 각자 필요한 관점에 의해 들어와 있는 부가 기능에 대한 코드들이다.  이런 코드들은 전체적인 동작을 위해서 다 필요하긴 한데 비즈니스 로직과는 상관 없는 경우가 많다. 또한 JDBC 프로그래밍을 조금 해본 경험이 있다면 알겠지만 모든 메서드에서 지루하게 반복적으로 등장한다. 

프로젝트의 대부분 메서드는 위와 같이 비지니스 로직(핵심 관심: core concern) 부가 기능(횡단 관심: cross cutting concern)으로 구성된다. 그리고 이런 부가 기능은 여러 메서드를 가로질러 존재 한다.

횡단 관심사와 핵심 관심사

 

다양한 횡단 관심사와 AOP의 대책

프로젝트 설계 문서에 보면 다음과 같은 요구사항들을 흔히 볼 수 있게 된다.

  • 로깅 필요
  • 보안을 위한 인증 및 메서드 호출 권한 검사
  • 안정적인 데이터 처리를 위한 트랜잭션 처리
  • 성능을 위한 데이터 캐싱과 모니터링
  • 데이터 보호를 위한 암호화 처리 등

 비즈니스 로직과 무관한 이런 일들이 횡단 관심사들이다. 보안, 트랜젝션, 캐싱 등 이름만 들어도 구현하기에 상당히 어려운 기술 같다.

하지만 우리는 뭐든지 열심히 하는 사람이니까 며칠을 공부하고 야근하며 요청 사항을 만족시킬 수 있다. 그 결과..

  • 개발자가 알아야 할 고급 기술이 급격히 증가. 하지만 개발자의 등급에 따라 제대로 처리되었는지 확신하기 어려움
  • 코드의 양 증가로 유지 보수가 어려움
  • 알고 보면 모두 비슷한 코드들이라 메서드를 만들다 보면 C.P 방법론을 시전하고 있을 확률이 높다.

 

작업을 많이 한것 같지만 결국은 복붙신공!

 

AOP에서는 일반적으로 선행 개발자들이 횡단 관심사를 모듈 형태로 개발한다. 그리고 일반 개발자들은 횡단 관심 코드가 필요한 곳에 개발된 모듈을 "적용"시키기만 하면 된다.

이제 개발자들은 비즈니스 로직에 집중할 수 있게 되기 때문에 개발 속도가 빨라지고 불필요한 코드도 사라져서 코드의 유지보수성도 향상된다.

AOP를 통해서 횡단관심사를 분리하자!

 

AOP 기본 컨셉과 용어

AOP는 개념 자체가 낯설기 때문에 좀 더 쉬운 이해를 위해서는 먼저 사용되는 용어에 익숙해질 필요가 있다.

용어 설명
target 핵심 관심사 (Core Concern)을 가지고 있는 실제 빈
advice 횡단 관심사 (Cross Cutting Concern)처리 코드
스프링에서는 동작 시점에 따라 @Before, @After, @Around, @AfterThrowing, @AfterReturning 5가지 타입 지원

   
join point advice가 끼어드는 지점으로 target의 비지니스 로직 메서드, field등이 있으나 spring에서는 메서드만 지원
pointcut target의 어떤 메서드에서 advice를 적용할 것인지를 결정하는 표현식으로 필터 역할
aspect 횡단 관심 코드를 구현하는 객체로 모듈화된 관점에 대한 추상적인 명칭
하나 이상의 advice와 pointcut의 결합으로 구성
   
weaving aspect를 join point에 적용하는 행위 

예를 들어 다음의 간단한 클래스에서 위에서 사용한 용어들의 되집어보자. 우리는 setName이라는 메서드가 실행되기 전에 "설정 중"이라는 로그를 남기고 싶다.

public class TargetBean{
  private String name;

  public void setName(String name) {
      // 비지니스 로직
      this.name = name;
  }
  public String getName(){
      return this.name;
  }
}

여기서 this.name=name 코드가 핵심 로직이고 핵심로직을 가지는 이 빈 객체 target이라고 한다. 로그를 남기는 행위 횡단 관심사, 로그를 남기는 코드인 횡단 관심 코드 advice가 된다. 이 advice는 메서드가 실행되기 전에 처리되어야 하므로 타입은 @Before가 적절하다.

target에는 여러 가지 메서드가 있는데 이 메서드들이 join point 이다. setName, getName처럼 2개의 join point가 있는데 getName은 아니고 "setName 메서드만 대상으로" 하도록 처리하는 부분은 pointcut에 해당한다. 

필터인 pointcut과 횡단 관심 코드인 advice를 뭉쳐서 aspect를 생성할 수 있다. aspect에는 하나 이상의 pointcut + advice 들이 존재한다. 마지막으로 advice 또는 aspect를 join point에 적용시키는 것을 weaving 시킨다고 한다.

반응형

'Spring Core > 03. AOP' 카테고리의 다른 글

06. AOP 작성 주의 사항  (0) 2024.02.16
05. Spring 내부의 AOP들  (0) 2021.10.29
04. advice의 타입  (0) 2020.06.20
03. pointcut 작성  (0) 2020.06.20
02. Aspect 작성과 동작  (0) 2020.06.18
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.