이 글에서는 C++의 프록시(Proxy) 클래스가 무엇인지 살펴보겠습니다. 프록시 클래스는 기본적으로 '프록시 디자인 패턴'을 구현한 것으로, 한 객체가 다른 클래스를 대신하여 수정된 인터페이스를 제공하는 방식입니다. 간단한 예제를 통해 그 개념을 이해해 보겠습니다.
예를 들어, 0과 1 같은 이진 값만 저장할 수 있는 배열 클래스를 만들고 싶다고 가정해 봅시다. 다음은 첫 번째 시도입니다.
첫 번째 시도: 문제가 있는 코드
class BinArray {
int arr[10];
int & operator[](int i) {
// 여기에 코드 작성
}
};위 코드에는 값에 대한 조건 검사가 전혀 없습니다. 우리는 arr[1] = 98처럼 잘못된 값을 대입했을 때 operator[]가 오류를 내도록 만들고 싶지만, 이는 불가능합니다. operator[]는 인덱스만 검사할 뿐, 대입되는 값 자체는 검사할 수 없기 때문입니다. 이 문제를 프록시 패턴을 적용해 해결해 보겠습니다.
프록시 패턴을 적용한 해결책
#include <iostream>
using namespace std;
class ProxyPat {
private:
int * my_ptr;
public:
ProxyPat(int& r) : my_ptr(&r) {
}
void operator = (int n) {
if (n > 1) {
throw "This is not a binary digit";
}
*my_ptr = n;
}
};
class BinaryArray {
private:
int binArray[10];
public:
ProxyPat operator[](int i) {
return ProxyPat(binArray[i]);
}
int item_at_pos(int i) {
return binArray[i];
}
};
int main() {
BinaryArray a;
try {
a[0] = 1; // 예외 발생하지 않음
cout << a.item_at_pos(0) << endl;
}
catch (const char * e) {
cout << e << endl;
}
try {
a[1] = 98; // 예외 발생
cout << a.item_at_pos(1) << endl;
}
catch (const char * e) {
cout << e << endl;
}
}실행 결과
1 This is not a binary digit
동작 원리 설명
핵심은 BinaryArray의 operator[]가 실제 int 참조가 아니라 ProxyPat 객체를 반환한다는 점입니다. 따라서 a[1] = 98처럼 값을 대입하면, 실제로는 프록시 객체의 operator=가 호출됩니다. 이 연산자 내부에서 대입하려는 값이 1보다 큰지 검사하고, 이진수가 아니면 예외를 던집니다. 값이 유효하면 내부 포인터를 통해 실제 배열 요소에 값을 저장합니다.
이처럼 프록시 클래스는 대입 연산 과정에 개입하여 타입 안전성을 높이고, 잘못된 값의 저장을 사전에 차단하는 역할을 합니다. 참고로 C++ 표준 라이브러리의 std::vector<bool>도 비슷한 프록시 기법을 활용하는 대표적인 사례입니다.