초보 웹 개발자를 위한 스프링 5 프로그래밍 입문을 더 잘 이해하기 위해 정리하기 위한 포스팅입니다.
목차
0. 프록시를 알아야 하는 이유
1. 프록시는 왜 등장하게 되었을까? 문제를 만들어보자.
2. 프록시 객체
0. 프록시를 알아야 하는 이유
1. 스프링 AOP가 프록시 객체를 생성해서 구현되어 있기 때문이다. @Transcational 우리가 사용하는 대표적인 스프링 AOP 기능일 것이다. 제대로 사용하려면 이에 대해 잘 알고 있어야 한다.
2. 일단 프록시랑 친해지면 여러모로 좋다. 아래 예제에서 delegate 라는 변수 명을 사용한다. 대리자라는 의미이다. 처음 프록시를 접했을 때는 "왜 대리자가 필요하지? 일만 복잡해지게 말이야." 의문이 들었을 때가 있다.
여러모로 좋다고 생각한 점은 프록시라는 개념은 생각보다 프로그래밍의 각지에서 등장한다. AOP 뿐만 아니라 JPA를 사용해본 사람이라면 could not initialize proxy 이런 에러를 한 번 쯤은 만나봤을 것이다. 또 웹 서버를 도입해본 사람이라면 리버스 프록시, 포워드 프록시에 대해 한 번 쯤은 들어봤을 수도 있다. 용어는 해당 개념을 학습하기 위한 시작이다. 스프링 AOP의 프록시를 이해하게 된다면 추후 다른 영역에서 프록시를 만나더라도 훨씬 이해가 쉬울 것이다.
1. 프록시는 왜 등장하게 되었을까? 문제를 만들어보자.
AOP의 가치를 느끼기 위한 간단한 예제를 만들어보자. 아래와 같은 인터페이스 규약이 있다. factorial은 n!을 계산하는 기능이다.
구현체 클래스 2개를 만들어주자.
이제 AOP를 배울 준비를 마쳤다.
앞서 구현한 두 클래스에 실행 시간을 출력하려면 어떻게 해야 할까? 가장 먼저 드는 생각은 메서드의 시작과 끝에 시간을 구하고 이 두 시간의 차이를 출력하는 것이다.
우선 ImpeCalculator에 실행 시간을 구하는 로직을 추가해보자.
다음은 RecCalculator 클래스 차례이다. 그런데 생각보다 복잡하다. 해당 클래스의 경우 factorial() 메서드를 재귀 호출한다.
그래서 앞서 ImpeCalculator 방식으로 실행 시간 로직을 구현하면 메시지가 여러 번, 의도하지 않은 대로 출력되는 문제가 있다.
그래서 메서드 내부에 로직을 추가하는 것보다 차라리 메서드 실행 전후에 값을 구하는 선택을 할 수도 있다.
그런데 위 방식도 문제가 있다. 만약 실행 시간을 밀리초 단위가 아니라 나노초 단위로 구해야한다면 어떻게 될까? 이 로직을 구현한 모든 곳을 일일히 수정해야 한다.
문제를 정리하면 다음과 같다.
1. 메서드 로직에 따라 메서드 내부에서 실행 시간을 구하기 어려울 수 있다.
2. 외부에서 구현 시 수정에 취약하고 코드 중복이 많이 발생한다.
1,2번 문제를 해결할 수 있는 방법은 없을까? 이 때 출현하는 것이 바로 프록시 객체이다.
2.프록시 객체
프록시 객체가 무엇인지는 뒤이어 알아보고 일단은 앞서 말한 문제를 프록시 객체를 통해 해결해보자.
이제는 아래와 같이 작성하면 factorial 과 실행 시간을 함께 구할 수 있다.
이를 통해 다음을 알 수 있다.
1. 기존 코드를 변경하지 않고 실행 시간을 출력할 수 있다. ImpeCalculator, RecCalculator 클래스는 코드 변경이 없다.
2. 실행 시간을 구하는 코드의 중복을 제거했다. 이제 밀리초, 나노초 시간 단위를 변경하고 싶다면 ExeTimeCalculator 클래스만 변경하면 된다.
이것이 가능한 이유는 ExeTimeCalculator 클래스를 다음과 같이 구현했기 때문이다.
1. factorila() 기능 자체를 구현한 것이 아니라 다른 객체에 factorial() 실행을 위임한다.
2. 계산 기능 외이에 다른 부가적인 기능을 실행한다. 여기서 부가 기능은 실행 시간 측정이다.
이렇게 핵심 기능의 실행은 다른 객체에 위임하고 부가적인 기능을 제공하는 객체를 프록시라고 부른다. 실제 핵심 기능을 실행하는 객체는 대상 객체라고 부른다. ExeTimeCalculator가 프록시고 ImpeCalculator 객체가 프록시의 대상 객체가 된다. 프록시의 특징은 핵심 기능은 구현하지 않는다는 점이다.
이 책의 저자는 다음과 같이 말한다. 지금 ㅈ가성한 코드는 프록시라기 보다는 데코레이터 객체에 가깝다. 프록시는 접근 제어 관점에 초점이 맞춰져 있다면, 데코레이터는 기능 추가와 확장에 초점이 맞춰져 있기 때문이다. 예제에서는 기존 기능에 시간 측정 긴으을 추가하고 있기 떄문에 데코레이터에 가깝지만 스프링의 레퍼런스 문서에서 AOP를 설명할 때 프록시란 용어를 사용하고 있어 이 책에서도 프록시를 사용했다.
'Spring > core' 카테고리의 다른 글
스프링 빈 순환 참조 예외 BeanCurrentlyInCreationException (0) | 2023.03.26 |
---|---|
스프링5 프로그래밍 입문 - ch7. AOP 프로그래밍 - (2) AOP (0) | 2023.03.25 |
스프링5 프로그래밍 입문 - ch6.빈 라이프사이클 (0) | 2023.03.24 |
스프링5 프로그래밍 입문 - ch5.컴포넌트 스캔 (0) | 2023.03.24 |
스프링5 프로그래밍 입문 - ch4.의존 자동 주입 (2) @Qualifier (0) | 2023.03.23 |