메타프로그래밍
메타프로그래밍은 간단하게 로봇이 다른 로봇을 만드는것과 같음
일반적인 프로그래밍은 사람이 로봇에게 로봇을 만들라고 지시하게됨
하지만 메타프로그래밍에선 로봇이 새로운 명령을 만들거나 다른 로봇을 만들어내게됨
결국 메타프로그래밍은 코드가 코드를 만드는걸 의미함
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;