조아마시

쓸모 있는 상세페이지 만들기

웹개발/javascript

[자바스크립트] 프록시(Proxy) 패턴

joamashi 2025. 3. 17. 16:42
반응형

프록시 패턴(Proxy Pattern)이란?

프록시 패턴은 다른 객체에 대한 접근을 제어하는 대리 객체(Proxy)를 사용하는 디자인 패턴입니다.
쉽게 말해, 어떤 객체에 직접 접근하는 것이 아니라, **중간에서 대신 처리해주는 객체(프록시)**를 두는 방식입니다.


왜 프록시 패턴을 사용할까?

  1. 보안(Security) → 민감한 데이터에 대한 직접 접근을 막고, 프록시를 통해 제한을 걸 수 있음.
  2. 로깅(Logging) → 객체의 메서드 호출이나 속성 접근을 추적하고 기록할 수 있음.
  3. 성능 향상(Caching) → 한 번 가져온 데이터를 캐시에 저장해서 같은 요청이 들어오면 빠르게 응답할 수 있음.
  4. 객체 생성 비용 절감(Lazy Initialization) → 무거운 객체를 미리 만들지 않고, 필요할 때 생성할 수 있음.

쉽게 이해하는 예제

🍔 햄버거 가게 예제

  1. 직접 주방에서 요리를 만드는 것보다 **점원(프록시)**을 통해 주문하는 것이 편함.
  2. 점원이 고객의 요청을 확인하고, 주방이 요리를 만들 수 있도록 함.
  3. 손님은 주방에 직접 접근할 필요 없이, 점원을 통해 햄버거를 받을 수 있음.

여기서 점원이 바로 프록시(Proxy) 역할을 하는 것입니다.


프록시 패턴 자바스크립트 코드 예제

📌 기본적인 프록시

const realBurger = {
  cook: () => "🍔 햄버거 완성!"
};

const burgerProxy = new Proxy(realBurger, {
  get(target, prop) {
    console.log(`'${prop}' 요청을 처리 중...`);
    return target[prop];
  }
});

console.log(burgerProxy.cook()); 
// 'cook' 요청을 처리 중...
// 🍔 햄버거 완성!

👉 프록시가 요청을 가로채서 로그를 출력하고, 실제 객체(realBurger)로 요청을 전달함.


프록시 패턴의 다양한 활용

🔒 1. 보안 역할 (접근 제한)

const userData = {
  name: "Alice",
  password: "1234"
};

const secureProxy = new Proxy(userData, {
  get(target, prop) {
    if (prop === "password") {
      throw new Error("비밀번호는 접근 불가!");
    }
    return target[prop];
  }
});

console.log(secureProxy.name); // Alice
// console.log(secureProxy.password); // Error 발생!

👉 비밀번호 같은 민감한 정보를 보호할 수 있음.


📝 2. 로깅 (데이터 변경 추적)

const user = { name: "Bob" };

const logProxy = new Proxy(user, {
  set(target, prop, value) {
    console.log(`'${prop}' 값이 '${target[prop]}' → '${value}'로 변경됨`);
    target[prop] = value;
    return true;
  }
});

logProxy.name = "Charlie"; // 'name' 값이 'Bob' → 'Charlie'로 변경됨

👉 속성이 변경될 때마다 로그를 남길 수 있음.


🚀 3. 네트워크 요청 프록시 (가짜 API)

const apiProxy = new Proxy({}, {
  get(_, endpoint) {
    return () => Promise.resolve(`📡 '${endpoint}' 데이터를 가져옴`);
  }
});

apiProxy.getUser().then(console.log); // 📡 'getUser' 데이터를 가져옴
apiProxy.getPosts().then(console.log); // 📡 'getPosts' 데이터를 가져옴

👉 실제 서버를 호출하지 않고, 가짜 데이터를 반환하는 API를 만들 수 있음.


정리

프록시 패턴은 객체에 직접 접근하지 않고, 중간에서 대신 처리하는 역할을 한다!
보안, 로깅, 캐싱, 성능 최적화 등 다양한 용도로 사용 가능!
JavaScript의 Proxy 객체를 활용하면 쉽게 구현할 수 있음! 🚀


1. 기본 프록시 (객체 속성 감시)

const target = { message: "Hello" };
const proxy = new Proxy(target, {
  get(obj, prop) {
    console.log(`${prop} 속성에 접근`);
    return obj[prop];
  }
});

console.log(proxy.message); // "message 속성에 접근" -> "Hello"

2. 읽기 전용 프록시

const readOnly = new Proxy({ data: "변경 불가" }, {
  set() {
    throw new Error("데이터 수정 불가!");
  }
});

console.log(readOnly.data); // "변경 불가"
// readOnly.data = "변경";  // Error 발생

3. 속성 유효성 검사

const validator = new Proxy({}, {
  set(obj, prop, value) {
    if (prop === "age" && value < 0) {
      throw new Error("나이는 0 이상이어야 합니다.");
    }
    obj[prop] = value;
    return true;
  }
});

validator.age = 25; // 정상
// validator.age = -5;  // Error 발생

4. 자동 속성 로깅

const logger = new Proxy({}, {
  set(obj, prop, value) {
    console.log(`${prop} 속성이 ${value}로 변경됨`);
    obj[prop] = value;
    return true;
  }
});

logger.name = "Alice"; // "name 속성이 Alice로 변경됨"

5. 동적 기본값 할당

const defaultValue = new Proxy({}, {
  get(obj, prop) {
    return prop in obj ? obj[prop] : "기본값";
  }
});

console.log(defaultValue.someProp); // "기본값"

6. 메서드 접근 제한

const api = {
  secretMethod: () => "비밀 데이터",
  publicMethod: () => "공개 데이터"
};

const secureApi = new Proxy(api, {
  get(obj, prop) {
    if (prop === "secretMethod") {
      throw new Error("비밀 메서드는 접근 불가");
    }
    return obj[prop];
  }
});

console.log(secureApi.publicMethod()); // "공개 데이터"
// console.log(secureApi.secretMethod()); // Error 발생

7. 배열 프록시 - 특정 조건 추가

const arrayProxy = new Proxy([], {
  set(target, prop, value) {
    if (typeof value !== "number") {
      throw new Error("숫자만 추가 가능");
    }
    target[prop] = value;
    return true;
  }
});

arrayProxy.push(10); // 정상
// arrayProxy.push("hello"); // Error 발생

8. 함수 호출 감시

const logFunctionCalls = new Proxy(function (x) { return x * 2; }, {
  apply(target, thisArg, args) {
    console.log(`함수 호출: ${args}`);
    return target.apply(thisArg, args);
  }
});

console.log(logFunctionCalls(5)); // "함수 호출: 5" -> 10

9. 객체 확장 제한

const frozenObject = new Proxy({}, {
  set(obj, prop, value) {
    if (!(prop in obj)) {
      throw new Error("새로운 속성 추가 불가");
    }
    obj[prop] = value;
    return true;
  }
});

frozenObject.name = "고정 데이터"; // Error 발생

10. 네트워크 요청 프록시 (가짜 API)

const fakeApi = new Proxy({}, {
  get(_, endpoint) {
    return () => Promise.resolve(`'${endpoint}' 데이터 가져오기`);
  }
});

fakeApi.getUser().then(console.log); // "'getUser' 데이터 가져오기"
fakeApi.getPosts().then(console.log); // "'getPosts' 데이터 가져오기"

이렇게 프록시 패턴은 데이터 검증, 접근 제어, 로깅, 속성 감시 등의 다양한 상황에서 사용할 수 있습니다.

 

728x90
반응형