본문으로 바로가기

19/01/02

category 수업내용 정리/정리안된 메모 2019. 6. 16. 21:01

19/01/02

진짜 완전 좋은 블로그 : https://victorydntmd.tistory.com/178

[AOP (Aspect Oriented Programming, 관점 지향 프로그래밍)] 객체지향프로그래밍 만으로 부족한 기능 분리를 위해서 사용하는 개발이론으로, 구현하고자 하는 기능을 핵심관심사항(핵심기능)과 공통관심사항(부가기능)으로 분리해서 작성하고 핵심기능이 실행될 때 부가기능을 같이 실행하는 개념

(예) "로그인 기능(핵심관심사항)이 실행되면 누가 로그인했는지 기록(공통관심사항)을 남겨라."

좋은 블로그 : http://isstory83.tistory.com/90

       ​http://www.incodom.kr/spring/AOP

Application을 두가지 관점에 따라 구현

• 핵심 관심 사항(core concern)

• 시스템의 핵심가치와 목적이 드러난 영역

• 공통 관심 사항 (cross-cutting concern)

• 부가적이지만 시스템의 완성도를 높여주는 기능 예) 로깅, 보안검사, 트랜잭션처리 등

AOP가 적용되지 않은 프로그램의 문제점

코드중복

• 중복되는 공통관심사항(CrossCutting concerns) 코드

지저분한 코드

• 핵심관심사항 (Core Concers)코드 사이 사이에 들어가는 공통관심사항 코드

재활용성 저하

생산성 저하

• 각 모듈에 공통으로 등장하는 공통관심사항에 대해서 같이 작업을 해야 하기 때 문에 모듈별 작업에 한계가 있다.

[Proxy 패턴]

실제 기능이 구현된 target 객체를 호출하면 target이 직접호출 되지 않고 target을 감싸고 있는 proxy에 의해 target이 호출된다. 이러한 구조로 advice가 적용되어 만들어진 객 체를 proxy 객체라 한다.

[Proxy 패턴 이해 예제]

boy : PC방에서 게임하기

girl : 백화점에서 쇼핑하기

이미지0) Person 이라는 Interface Class

이미지1) Person을 구현하는 구현 클래스 Boy, Girl

각각 핵심기능 (빨간색 체크박스)을 실행하기 위해서는, 부가적인 기능(체크박스 외의 sysout)​을 작성해야 하는데 이 때 같은 부가기능을 실행해야 하는 경우 코드 중복이 발생할 수 있는데, 이때 '프록시객체'를 이용하면 코드 중복을 없앨 수 있다.

이미지2) Proxy 클래스

Boy와 Girl이 가지고 있던 부가적인 기능 (중복코드)를 Proxy에서 작성해준다. Proxy 객체에 있는 doSomething에는 사용자가 실질적으로 원하는 기능 (Boy, Gril)을 대신 호출하게 된다.

이미지3) 테스트 해보기

테스트에 앞서, Boy와 Gril에 존재하던 부가기능 (이미지1에서 빨간체크 박스 외sysout)을 삭제하고, 핵심기능만 남겨놓은 상태이다.

위와 같은 상태에서 실행을 하게 되면 Proxy 생성자에 인자로 들어간 객체의 핵심기능이 출력과, Proxy 객체가 가지고 있는 부가기능이 함께 출력되는 것을 확인 할 수 있다.

위 예제처럼, 핵심기능이 실행 될 때 동작하는 부가기능을 정의 해놓은 객체가 Proxy 객체이다.

스프링에서는 위 처럼 사용자가 별도로 Proxy객체를 만들지 않고, 설정만을 통해서 위 예제와 같은 효과를 얻을 수 있다.

[SpringFramework에서 AOP 사용하기 위한 porm.xml 설정]

이미지0) pom.xml / 총5개의 라이브러리를 추가했다.

Spring : core, context, aop

aspectj(AOP구현을 위한 라이브러리) : aspectjrt, aspectjweaver

[AOP 용어(구성요소)]

좋은 블로그 : http://closer27.github.io/backend/2017/08/03/spring-aop/

       ​https://hunit.tistory.com/188

       ​http://private.tistory.com/43

• Target : 핵심관심사항이 구현된 객체

• JoinPoint : ​공통관심사항 모듈이 삽입되어 동작할 수 있는 특정 위치

• Pointcut : ​공통관심사항의 모듈이 어느 JointPoint를 사용할 지 결정하는 선택 기능

• Advice : ​각 JointPoint에 삽입되어 동작할 수 있는 실제 구현 코드

• CrossCutting (Weaving) : ​핵심관심사항 모듈 사이 사이에 공통관심사항 코드가 엮어지게 만드는 기능 세 가지 시점(컴파일 시점, 로딩 시점, 런타임 시점) 방식이 있다.

• Aspect : ​어디(Pointcut)에서 무엇(Advice)을 할 것인지 합쳐 놓은 것

​​

[Advice 종류]

 before : target 메서드 호출 이전

• after : target 메서드 호출 이후 무조건 실행

• after returning : target 메서드 정상동작 후

• after thowing : target 메서드 에러 발생 후

• around : target 메서드 호출 이전, 이후 모

[실습] 앞서 Proxy 이해 실습에서 사용하였던 boy, girl, person(인터페이스) 그대로 사용 

​해야 할 일

1.기능구현 : 핵심관심사항, 공통관심사항 각각 기능을 가지는 객체를 bean으로 등록

2.핵심기능이 실행됐을 때, 공통기능이 같이 실행되도록 AOP 적용​

이미지0) MyAspect.java 코드

공통관심사항 코드를 지니고 있는 advice 클래스를 작성하였다.

이미지1-1) applicationContext.xml.xml 코드 

이미지1-2) applicationContext.xml코드

붉은색 체크박스 처럼, 각각 속성을 지정하면 속성에 맞는 화살표가 표기되어 진다. 이미지상에는 나와 있지 않지만, doSomething()을 포함한 bean에는 → 화살표가 추가되는데 이는 <aop:pointcut expression="execution(public void *.doSomething(..))"/> 코드에서 언급되어 있는 doSomething()를 1개 이상 포함하고 있다는 뜻이다.

표현식 블로그 참고 : http://blog.naver.com/PostView.nhn?blogId=chocolleto&logNo=30086024618&categoryNo=29&viewDate=¤tPage=1&listtype=0

이미지1-3) 패턴 표현식 예시

이미지2-1) 테스트

우리가 실질적으로 실행한 것은 단수하게 boy의 doSomething() 이지만, doSomething()에 적용된 AOP로 인해서 "PC방에서 게임을 한다" 외에 다른 메서드들이 (AOP에 적용시킨) 함께 동작하여, 콘솔창에 찍히는 것을 볼 수 있다.

이미지2-2) 콘솔창에 찍힌 순서에 대해서...

​결과창에서 '씻고 잠을 잔다'는 after이고, '계산을 한다'는 returning이다. 두 속성의 순서는 정의되어 있지 않기 때문에, 순서가 우리가 원하는 (탑승-게임-계산-잠)으로 출력되지 않는 것을 확인 할 수 있다 (이미지2-1)

코드를 작성할 떄 프로그램의 실행 순서를 염두하는 코드 작성을 할 수는 있으나 (단순히 코드의 순서를 수정하면 가능: xml에서 작성한 순서를 바꿈) 올바른 코드 작성은 아니다. *그렇게 작성하면 안됨. AOP 문서에도 하면 안된다고 나와있음.

*추가설명

after,(after-returning, after-throwing) 세 가지 advice 들 간의 순서는 정의 되지 않음

after : target 실행 후 항상실행

after-returning : target이 정상 종료 된 후 실행

after-throwing  : target이 비정상 종료 된 후 실행

​​

[임의로 예외 발생시켜서 다른 동작해보기]

이미지0) 

Random().nextBoolean()은 랜덤으로 true 혹은 false를 반환한다.

이미지1) 예외발생

 

 

[annotation으로 aop 설정하기]

이미지0) : 1. 타켓, advice 구현 클래스 bean으로 등록
각각 사용 될 클래스 (Boy, Girl : 타켓메서드 / MyAspect : Aspect)를 @를 이용하여 bean으로 등록하였다. 그 이후 applicationContext.xml.xml에서 context:component-scan을 통해서 aop3 패키지에 annotation으로 등록된 클래스를 스캔할 수 있게 코드를 작성.

이미지1-1) pointcut 지정하기

이미지1-2) advice() 지정하기

이미지2) 스프링 설정파일 작성

[번외]

(1)

붉은색 체크 박스에 들어갈 클래스는 항상 interface 이어야 할 까 ? : 그렇다.

스프링 내부적으로 aop가 적용이 되면, Proxy 객체가 생성되는데, 이때 생성되는 Proxy 객체는 타켓(이미지상 Boy)의 부모 인터페이스(Person)을 구현하는 구현클래스(Proxy​객체) 이다.

AOP가 적용된 bean에 참조할 때 target의 타입으로 참조하는게 아니라, 부모인터페이스의 타입으로 참조해야 한다.

(2) after-returning과 after-thowing에서 target()가 반환하는 값 혹은 예외 얻어오기

글 작성은 반환 값으로 작성하였지만, 예외 역시 같은 방식으로 얻어 올 수 있음.

Boy 라는 target()은 "Boy:정상종료" 라는 String 값을 반환하도록 작성하고 

Aspect클래스의 advice() 중에서 after-returning에 해당하는 payment()에 파라미터를 통해서 msg를 받아오도록 작성하였다. 

그리고 sysout을 통해 파라미터로 받아온 msg를 기존 메시지와 함께 출력하도록 셋팅한 상태.

applicationContext.xml.xml에서 payment()를 설정한 부분에서 returning 이라는 속성을 추가하여, target 메서드(Boy)의 반환값을 payment()가 실행되면 msg라는 이름으로 전달하도록 설정했다.

(설명을 못하겠음)

AopTest를 통해서 실행하게 될 경우 위와 같은 결과창을 볼 수 있다.

지금 예제의 경우 간단하게 target()가 반환하는 값을 불러올 수 있다라는 것을 확인하기 위해서 간단하게 작성하였지만, 응용을 통해 여러 작업이 가능하다.

Ex)

A라는 사람이 돈을 입금할 경우 true 아닐 경우 false를 반환하게 A라는 Target()를 작성한 뒤에, A가 반환하는 값을 통해서 추가적인 작업이 이루어지게 코드를 작성 할 수 있다.

before : "A가 은행에 들어왔다"

after-returning : 반환값이 참이라면 "돈을 입금했다", false라면 "돈을 입금하지 않았다" 라는 문구가 출력되게끔...

(3)JoinPoint 활용해보기

JoinPoint : 공통관심사항 모듈이 삽입되어 동작할 수 있는 특정 위치

앞선 예제에서 JoinPoint(이하 jp)를 통해서 어떤 target이 작동했는지 알 수 있다.

jp의 getTarget()을 활용하면 어떤 target 인지 알 수 있다.

Ex, 활용한다면?)

은행업무 관련 코드를 작성 했을 때 A가 업무를 보는지 B가 업무를 보는지 등.

Gril 객체를 실행하면, Target인 Gril에 대한 정보가 나오게 된다.

[around] : 타켓메서드 실행 전후를 개발자가 직접관리

좋은 블로그 (예제) : http://whiteship.tistory.com/664

이미지0) around에 사용 할 메서드들















'수업내용 정리 > 정리안된 메모' 카테고리의 다른 글

19/01/04​  (0) 2019.06.16
19/01/03​  (0) 2019.06.16
[MyBatis와 Spreing 연동하기]  (0) 2019.06.16
18/12/31​  (0) 2019.06.16
18/12/28  (0) 2019.06.16