로깅과 같이 로그는 남기는 기능은 비즈니스 로직에 꼭 포함되어야 한다. 그러나 그것이 연속적으로 똑같이 반복되면 소스코드가 지저분하고 복잡해진다.
그래서 등장한 개념이..! AOP 이다.
AOP의 정의 : 컴퓨팅에서 관점 지향 프로그래밍은 횡단 관심사의 분리를 허용함으로써 모듈성을 증가시키는 것이 목적인 프로그래밍 패러다임
위의 예시를 보면 세로줄의 카페 생성, 게시판 생성, 게시글 생성은 기능이다. 그런데 얘네들은 전부 가로 줄의 보안, 로깅, DB 가 필요하다.
어떠한 행동을 하고 싶은 특정한 관점을 Logging Aspect라고 하고 Logging Aspect 가 들어갈 수 있는 지점을 join point라고 한다.
Logging Aspect는 모든 join point에 들어가야할 수도 있고 아닐 수도 있다. 따라서 Logging Aspect가 적용될 join point를 정의하기 위해서 pointCut을 지정한다.
Logging Aspect에서 실제로 실행될 함수를 adivce라고 부른다.
따라서 우리는 코드를 통해 Logging Aspect, 그 안에 있는 advice, advice가 실제로 적용될 pointCut을 살펴본다.
계속 사용하고 있는 jpa 프로젝트에서 이어서 작성한다.
먼저 build.gradle의 dependencies에 추가해준다.(18번째 줄)
그리고 aspect라는 패키지를 만들고 그 안에 LogExecutionTime 이라는 이름의 Annotation 형식의 자바 파일을 만든다.
그리고 아래와 같이 코드를 작성한다.
@Retention() : 실제로 어느시점까지 컴퓨터상에 존재할 것인가를 정의한다.
- source : 컴파일러로 인해 제거되는 어노테이션. 즉 명시를 위한 용도.
- class : 컴파일러에서는 읽어들이지만 실행할 때는 상관없는 어노테이션.
- runtime : 프로젝트를 실행할 때 정상적으로 작동하는 어노테이션.
그 다음으로는 어노테이션에 따라서 작동하기 위한 Aspect를 만들어준다.
ProceedingJoinPoint: 일반적인 joinPoint와 다르다. ProceedingJoinPoint는 Around advice에서만 지원되는 JoinPoint이다. 기존 사용했던 joinPoint처럼 Target Object의 메소드 정보를 포함하고 있다. 특히 ProceedingJoinPoint.proceed()는 Target의 메소드를 실행을 제어할 수 있다.
joinPoint.proceed() 시점
- Around 에서 joinPoint.proceed() 에 대한 시점이 중요
- proceed()를 기준으로 이전 코드는 before, 이후 코드는 after로 구분된다.
- proceed() 의 리턴 값은 Object 이다. 이는 Aspect 로 연결된 Original Method 의 리턴 값을 받을 수 있다.
그리고 이제 이 어노테이션을 확인해보자! 컨트롤러에가서 예시로 readPostAll 메소드위에 어노테이션을 입력한다.
그리고 실행을 한 후 readPostAll 에 해당하는 url에 접속해보면
아래와 같이 콘솔창에 로그가 뜨는 것을 확인할 수 있다.
추가적으로 몇가지 더 알아보자.
LogExecutionTime를 만들었던 것과 같이 아래처럼 LogParameters를 만든다.
그리고 LoggingAspect.java 클래스로가서 아래와 같이 코드를 추가한다.
그리고 컨트롤러에서 createPost메소드에 위 어노테이션을 달아준 후 포스트맨으로 create에 해당하는 부분을 실행하면 아래와 같은 결과가 나온다!
마지막으로 @After에 대해 확인해보자. 어노테이션을 하나 만들고
Aspect.java에 아래 코드를 추가한다.
그리고 해당하는 부분인 컨트롤러에서 readPost 메소드 부분에 어노테이션을 입력하고 실행 시킨 후 작동하면
위와 같이 결과 나온다는 것을 확인할 수 있다.