다음 포스팅에 스프링 AOP에 사용되는 프록시 패턴과 데코레이터 패턴을 배우기 전에 해당 패턴에 사용되는 프록시란 무엇인지 자세하게 알 필요가 있을 것 같아서 프록시에 대해서 먼저 포스팅을 하게 되었습니다.
프록시
프록시 그 자체적인 의미는 대리자라는 의미를 가지고 있습니다.
프록시를 이제 객체에 대해 적용하느냐, 서버에 대해 적용하느냐에 대해서 이제 대리자로서 다르게 동작할 뿐입니다.
참고로 프록시 서버의 정의는 다음과 같습니다.
클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램
출처 : 위키피디아
간접적이라는 말이 보이시죠? 클라이언트의 요청을 대리자로서 접속할 수 있게 해준다는 것입니다.
그럼 여기서 클라이언트라는 말이 나왔으니, 클라이언트와 서버에 대해서도 잠깐 알아봅시다.
클라이언트와 서버
대체로 클라이언트와 서버에 대해서 얘기하면 보통 클라이언트를 서버에게 어떠한 요청을 하는 사람 서버를 서버 컴퓨터로 생각하곤 합니다. 그러나 클라이언트와 서버는 생각보다 넓은 개념으로 사용이 되는데요.
클라이언트는 용어 그대로 의뢰인이라는 의미를 가지고 있고, 서버는 서비스나 상품을 제공하는 사람이나 물건을 뜻합니다.
따라서 위의 말도 틀린 말은 아니지만, 저희는 클라이언트와 서버에 대해서 설명할 때 다음과 같이 설명할 필요가 있습니다.
클라이언트는 서버에 필요한 것을 요청하고, 서버는 클라이언트의 요청을 처리한다.
위 처럼 이 개념을 네트워크에 도입하면, 클라이언트는 웹 브라우저 서버는 웹 서버가 되는 것입니다.
객체지향언어에서는 객체들간의 행동은 메시지를 통해서 해결됩니다. 이때, 메시지를 송신하는 객체를 송신자, 메시지를 수신하는 객체를 수신자 라고 하는데요.
이를 클라이언트와 서버의 개념으로 이해를 할 수가 있습니다. 즉 메시지를 송신하는 객체를 클라이언트, 메시지를 수신하는 객체를 서버라고 생각 할 수도 있는 것이지요.
그럼 객체의 입장에서는 프록시는 어떤 역할을 하는 것일까요?
객체와 프록시
대부분의 상황에서는 다음과 같이 객체가 메시지를 직접적으로 보내는 상황이 많을 것입니다. 이러한 경우를 직접 호출이라고 부르는데요.
그럼 프록시를 사용하면 어떠한 상황이 될까요?
다음과 같은 구조를 띄고 있습니다.
여기서 중요한 사실이 있는데 객체는 메시지를 통해 요청을 하게 되면 그 요청을 한 이후에 각 객체들이 어떻게 처리를 하는지에 대해서는 모릅니다. 각 객체는 그 요청에 따라 객체 자기 자신이 자율성에 따라 행동을 하기 때문이지요. 이것이 우리가 객체지향특징에서 많이 들어왔던 캡슐화입니다.
객체의 관점에서 프록시는 많은 일을 할 수 있습니다. 이번엔 프록시의 특징에 대해서 알아봅시다.
프록시의 특징
프록시는 다음과 같은 특징을 지니고 있습니다.
- 접근 제어
- 캐싱
- 부가기능 추가
- 프록시 체인
이전에 포스팅에서 템플릿과 관련된 디자인 패턴을 통해서 부가 기능을 수행하는 것을 볼 수 있었는데요. 프록시도 이와 같은 일을 수행 할 수 있습니다.
각 특징에 대한 설명으로 이에 대한 관점을 기억하고 보면 무슨 말인지 느낌이 오실 겁니다. 프록시는 클라이언트의 요청을 대신해서 서버에게 요청을 합니다. 이런 것이 가능하니,
클라이언트가 서버에게 요청했을 때 프록시가 해당 클라이언트가 보내는 메시지가 서버에 보낼 권한이 있는지 확인이 가능하고,
굳이 서버에 보내지 않고도 캐시에 담겨져 있는지도 확인이 가능하고,
클라이언트가 보내는 메시지에 부가 기능을 추가해서 서버에 보낼 수도 있고,
프록시가 보내는 메시지를 바로 서버에 보내지 않고 또 프록시를 거쳐서 서버에 보낼 수도 있는 것입니다.
하지만 프록시가 서버에 위와 같은 기능을 하기 위해서는 다음과 같은 조건이 반드시 필요합니다.
서버와 프록시는 같은 인터페이스를 구현해야 한다.
단순하게 생각해보면 클라이언트는 서버는 프록시에 요청을 하는 것이 아니라 서버에 요청 할 뿐인데, 그 일을 프록시가 대리자로서 일련의 처리를 하고 서버에게 요청하는 것 뿐입니다. 따라서 클라이언트의 입장에서는 프록시가 서버인지 프록시인지 알 수가 없어야 합니다.
그저 클라이언트는 서버에게 요청을 한 것이지요. 이를 이용 하는 방법이 객체지향언어에 특징 중에서 가장 중요한 특징이 있죠!
바로 다형성을 이용해서 위와 같은 일이 가능합니다.
객체가 다음과 같은 구조를 띄고 있을 때 Client는 ServerInterface에 보내지만 ServerInterface가 어떤 객체로 구현되어있는지에 따라 다르게 동작 할 것입니다. 개발에서 이를 활용하기 위해 DI(Dependency Injection) 을 이용해서 간단하게 사용이 가능하지요.
GOF 디자인 패턴에서의 프록시
GOF 디자인 패턴에서 프록시를 사용하는 디자인 패턴은 크게 2가지가 있습니다.
- 프록시 패턴 : 접근 제어가 목적
- 데코레이터 패턴 : 부가 기능 추가가 목적
이름에 프록시가 들어가 있어서, 프록시 패턴만 프록시를 사용하는 것으로 오해를 할 수 있습니다. 하지만 데코레이터 패턴 또한 프록시를 사용한다는 것을 잊지 말아야 합니다.
먼저 프록시 패턴의 정의는 다음과 같습니다.
대상 원본 객체를 대리하여 대신 처리하게 함으로써 로직의 흐름을 제어하는 행동 패턴
이어서 데코레이터 패턴의 정의는 다음과 같습니다.
객체에 추가 요소를 동적으로 더할 수 있다. 데코레이터를 사용하면 서브클래스를 만들때보다 훨씬 유연하게 기능확장이 가능하다.
다음에는 프록시 패턴이 실제로 어떻게 구현되는지 데코레이터 패턴이 실제로 어떻게 구현되는지에 대해서 포스팅 해보도록 하겠습니다!
'Backend > Spring' 카테고리의 다른 글
[Intellij] JUnit Test 시 No tests found for given includes: (0) | 2023.04.22 |
---|---|
자바 리플렉션과 이를 이용한 JDK 동적 프록시와 CGLIB (0) | 2023.04.20 |
템플릿 콜백 패턴 (1) | 2023.04.17 |
스프링의 싱글톤 패턴으로 인한 동시성 문제와 그 해결 (0) | 2023.04.14 |
1. SPRING (0) | 2022.06.13 |