자바스크립트와 메타프로그래밍

메타프로그래밍과 자바스크립트

2025년 12월 2일4분0
javascript
proxy

메타프로그래밍

  • 메타프로그래밍은 간단하게 로봇이 다른 로봇을 만드는것과 같음

  • 일반적인 프로그래밍은 사람이 로봇에게 로봇을 만들라고 지시하게됨

  • 하지만 메타프로그래밍에선 로봇이 새로운 명령을 만들거나 다른 로봇을 만들어내게됨

  • 결국 메타프로그래밍은 코드가 코드를 만드는걸 의미함

code
/**
 * 일반적인 프로그래밍
 */
const numbers = [1, 2, 3];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6]

/**
 * 메타프로그래밍
 */
const user: { name: string; age: number } = { name: "동우", age: 27 };
for (const key in user) {
  console.log(`${key}의 타입은 ${typeof user[key as keyof typeof user]}입니다.`);
}

// name의 타입은 string입니다.
// age의 타입은 number입니다.

런타임에 구조에 접근하기 - Type Introspection

  • 프로그램이 실행 중에 이 데이터가 뭐지? 무슨 타입이지? 처럼 스스로 알아내는 것을 뜻함

  • 마치 사람이 거울을 보는것과 유사한데 동일하게 코드가 자기 자신의 구조를 들여다볼 수 있음

code
/**
 * 타입 확인하기
 */
console.log(typeof "IMKDW-DEV-BLOG"); // string
console.log(typeof 123); // number
console.log(typeof true);

/**
 * 어떤 클래스인지 확인
 */
class User {}
class Admin {}
const user = new User();
console.log(user instanceof User); // true
console.log(user instanceof Admin); // false

구조를 스스로 변경하기 - Self Modification

  • 프로그램이 런타임에 자기 자신의 구조나 동작을 바꾸는걸 의미함

  • 마치 레고를 조립하면서 동시에 블록을 바꿔 끼우는 것 처럼 완성된 후에 바꾸는게 아닌 도중에 스스로 변형함

code
/**
 * 객체 내용 수정하기
 */
const user: { name: string; age?: number } = { name: "동우", age: 27 };
console.log(user); // { name: '동우', age: 27 }

user.name = "우동";
console.log(user); // { name: '우동', age: 27 }

delete user.age;
console.log(user); // { name: '우동' }

/**
 * 클래스의 동작 수정하기
 */
class Animal {
  speak() {
    return "...";
  }
}

const dog = new Animal();
console.log(dog.speak()); // ...

Animal.prototype.speak = () => {
  return "왈왈";
};

console.log(dog.speak()); // 왈왈

언어의 의미 재정의 하기 - Intercession

  • 언어의 기본 동작을 가로채서 내가 원하는대로 변경이 가능함

  • 택배를 보내면 보내는 사람 -> 받는 사람으로 가는 택배를 내가 열어보고 안에 내용물을 바꾸거나 등 행동이 가능함

  • 자바스크립트의 경우 이런 로직을 Proxy를 통해서 구현하게됨

code
type User = { name: string; age: number };

const user: User = { name: "동우", age: 27 };

const proxyUser = new Proxy(user, {
  get(target: User, prop: keyof User) {
    console.log(`${prop}에 접근을 시도중임`);
    return target[prop];
  },
  set(target: User, prop: keyof User, value: User[keyof User]) {
    if (prop === "age" && typeof value === "number" && value < 0) {
      throw new Error("나이는 0보다 작을 수 없습니다.");
    }

    (target[prop] as User[keyof User]) = value;

    return true;
  },
});

// name에 접근을 시도중임
// 동우
console.log(proxyUser.name);

proxyUser.age = 30;
console.log(proxyUser.age); // 30

// Error: 나이는 0보다 작을 수 없습니다.
proxyUser.age = -1;

댓글 0

ME

댓글을 작성하려면 로그인이 필요합니다

아직 댓글이 없습니다.

첫 번째 댓글을 작성해보세요!