Java Adv 18 - 동시성 컬렉션이 필요한 이유 - 3
in Programming Language on Java
프록시(Proxy)
우리말로 대리자, 대신 처리해주는 자라는 뜻이다. 프록시를 쉽게 풀어서 설명하자면 친구에게 대신 음식을 주문해달라고 부탁하는 상황을 생각해 볼 수 있다. 예를 들어,당신이 피자를 먹고 싶은데, 직접 전화하는 게 부담스러워서 친구에게 대신 전화해서 피자를 주문해달라고 부탁한다고 해보자. 친구가 피자 가게에 전화를 걸어 주문하고, 피자가 도착하면 당신에게 가져다주는 것이다. 여기서 친구가 프록시 역할을 하는 것이다. 나(클라이언트) 피자 가게(서버), 나(클라이언트) 친구(프록시) 피자 가게(서버) 객체 세상에도 이런 프록시를 만들 수 있다. 여기서는 프록시가 대신 동기화(synchronized ) 기능을 처리해주는 것이다. 코드를 만들면서 확인해보자.
SyncProxyList 는 BasicList 와 같은 SimpleList 인터페이스를 구현한다. 이 클래스는 생성자를 통해 SimpleList target 을 주입 받는다. 여기에 실제 호출되는 대상이 들어간다. 이 클래스는 마치 빈껍데기 처럼 보인다. 이 클래스의 역할은 모든 메서드에 synchronized 를 걸어주는 일 뿐 이다. 그리고나서 target 에 있는 같은 기능을 호출한다. 이 프록시 클래스는 synchronized 만 걸고, 그 다음에 바로 실제 호출해야 하는 원본 대상(target )을 호출한다. 기존에 BasicList 를 직접 사용하고 있었다면, 이제 중간에 프록시를 사용하므로 다음과 같은 구조로 변경된다.
- 기존 구조: 클라이언트
BasicList(서버) - 변경 구조: 클라이언트
SyncProxyList(프록시)BasicList(서버)
그림과 같이 정적인 클래스의 의존 관계를 정적 의존 관계라 한다. test() 메서드를 클라이언트라고 가정하자. test() 메서드는 SimpleList 라는 인터페이스에만 의존한 다. 이것을 추상화에 의존한다고 표현한다. 덕분에 SimpleList 인터페이스의 구현체인 BasicList , SyncList , SyncProxyList 중에 어떤 것을 사용하든, 클라이언트인 test() 의 코드는 전혀 변경하지 않아도 된다. 클라이언트인 test() 입장에서 생각해보면 BasicList 가 넘어올지, SyncProxyList 가 넘어올지 알 수없다. 단순히 SimpleList 의 구현체 중의 하나가 넘어와서 실행된다는 정도만 알 수 있다. 그래서 클라이언트인 test() 는 매우 유연하다. BasicList 의 어떤 구현체든지 다 받아들일 수 있다.
런타임 의존관계
먼저 BasicList 를 사용하는 예를 보자.
실제 런타임에 발생하는 인스턴스의 의존 관계를 런타임 의존 관계라 한다. 먼저 간단한 BasicList 를 직접 사용하는 경우부터 알아보자. test(new BasicList()) 를 실행하면 BasicList(x001) 의 인스턴스가 만들어지면서 test() 메서드에 전달된다. test() 메서드는 BasicList(x001) 인스턴스의 참조를 알고 사용하게된다.
다음 두 코드는 같은 코드이므로 쉽게 풀어서 설명하겠다.
test(new SyncProxyList(new BasicList()))
SimpleList basicList = new BasicList();
SimpleList list = new SyncProxyList(basicList);
test(list)
- SimpleList basicList = new BasicList();
BasicList의 인스턴스가 생성되며, 이 인스턴스는x001이라는 고유 참조를 가진다.- 이 인스턴스를
basicList라는 이름의 변수에 저장한다.
- SimpleList list = new SyncProxyList(basicList);
SyncProxyList의 인스턴스가 생성된다.- 생성 시에
basicList의 참조인BasicList(x001)을 인수로 전달받는다. - 이렇게 만들어진
SyncProxyList(x002)는 내부에target이라는 변수로BasicList(x001)의 참조를 저장하고 있다.
- test(list);
test메서드에SyncProxyList(x002)가 전달된다.- 이때
SyncProxyList를 통해BasicList의 기능에 접근하게 된다. SyncProxyList는BasicList의 기능을 호출하기 전에 동기화 처리나 추가 기능을 적용한다.
Reference
김영한님의 자바 강의