학습
Lua 루아의 메타 프로그래밍 심화
Lua 루아의 메타 프로그래밍 심화 — 고급
루아의 메타 프로그래밍 심화
1. 도입 (왜 배워야 하는가)
루아의 메타 프로그래밍은 매우 강력한 기능으로, 프로그램의 동작을 동적으로 변경할 수 있는 능력을 제공합니다. 실무에서 메타 프로그래밍을 활용하면 코드의 유연성과 재사용성을 극대화할 수 있습니다. 예를 들어, 게임 개발에서는 객체의 속성을 동적으로 변경하거나, 특정 상황에 맞춰 동작을 조정하는 데 유용합니다.
이러한 기능을 모르면 코드가 복잡해지고, 유지보수가 어려워질 수 있습니다. 또한, 코드의 재사용성을 낮추며, 반복적인 작업을 피하기 위해서라도 메타 프로그래밍을 이해하는 것이 필수적입니다.
2. 핵심 개념 설명
메타 테이블
메타 테이블은 루아의 테이블에 추가적인 동작을 정의할 수 있는 특별한 테이블입니다. 이를 통해 테이블의 동작을 오버라이드하거나, 새로운 동작을 추가할 수 있습니다.
예를 들어, 메타 테이블을 통해 두 테이블을 더하는 방법을 정의할 수 있습니다. 이는 마치 요리 레시피를 바꿔 새로운 요리를 만드는 것과 같습니다.
| 용어 | 정의 |
|---|---|
| 메타 프로그래밍 | 프로그램이 프로그램을 조작하는 기술 |
| 메타 테이블 | 루아 테이블에 추가적인 동작을 정의하는 테이블 |
3. 기본 코드 예제
메타 테이블을 사용하여 테이블의 더하기 연산을 오버라이드하는 간단한 예제를 살펴보겠습니다.
-- 메타 테이블 정의
local mt = {
__add = function(t1, t2)
local result = {}
for k, v in pairs(t1) do
result[k] = v + (t2[k] or 0)
end
for k, v in pairs(t2) do
result[k] = result[k] or v
end
return result
end
}
-- 두 개의 테이블 생성
local t1 = setmetatable({x = 1, y = 2}, mt)
local t2 = setmetatable({y = 3, z = 4}, mt)
-- 두 테이블 더하기
local result = t1 + t2
-- 결과 출력
for k, v in pairs(result) do
print(k, v)
end
실행 결과:
x 1
y 5
z 4
- 첫 번째 줄에서 메타 테이블을 정의합니다.
__add는 더하기 연산을 오버라이드하는 함수입니다. - 두 번째 줄과 세 번째 줄에서 두 개의 테이블
t1과t2를 생성하고 메타 테이블을 설정합니다. t1 + t2를 수행하면, 메타 테이블의__add함수가 호출되어 두 테이블의 값을 합칩니다.- 마지막으로 각 키와 값을 출력합니다.
4. 실전 활용 예제
예제 1: 객체지향 프로그래밍 구현
쇼핑몰에서 상품 객체를 구현할 때, 메타 테이블을 사용하여 상품의 가격을 자동으로 할인하는 기능을 추가할 수 있습니다.
local Product = {}
Product.__index = Product
function Product:new(name, price)
local obj = setmetatable({}, self)
obj.name = name
obj.price = price
return obj
end
function Product:apply_discount(discount)
self.price = self.price - (self.price * discount)
end
local item = Product:new("Laptop", 1000)
item:apply_discount(0.1) -- 10% 할인 적용
print(item.price) -- 900
예제 2: 속성 접근 제어
게임 캐릭터의 속성을 관리할 때, 메타 테이블을 사용하여 각 속성이 특정 조건을 만족할 때만 접근할 수 있도록 할 수 있습니다.
local Character = {}
Character.__index = Character
function Character:new(name)
local obj = setmetatable({}, self)
obj.name = name
obj.health = 100
return obj
end
setmetatable(Character, {
__index = function(t, k)
if k == "health" then
return "Health is private!"
end
end
})
local hero = Character:new("Warrior")
print(hero.health) -- "Health is private!"
5. 흔한 실수와 주의사항
실수 1: 메타 테이블을 설정하지 않음
local t = {}
-- setmetatable(t, mt) 를 놓쳤을 경우
print(t + {x = 1}) -- 에러 발생
해결: 반드시 메타 테이블을 설정해야 합니다.
실수 2: 잘못된 메타 메서드를 사용
local mt = {
__add = "This is not a function!" -- 메타 메서드가 함수여야 함
}
해결: 메타 메서드는 반드시 함수로 정의해야 합니다.