루아 프로그래밍 기법

루아 프로그래밍 기법 (Lua Programming Techniques)

이 절은 루아 5.4 Reference Manual의 특정 항목이라기보다, 루아에서 널리 쓰이는 관용구(idiom)와 기법을 정리한 종합 안내예요. 스크립트와 모듈을 작성할 때 실제로 유용한 패턴을 소개해요. 원문 매뉴얼의 관련 절(테이블, 함수, 메타테이블, 모듈, 코루틴)들을 종합했어요.

테이블을 데이터 구조처럼 (Tables as Data Structures)

루아의 테이블은 배열이자 레코드, 사전이에요. 정수 키로 배열처럼, 문자열 키로 레코드처럼, 임의 키로 사전처럼 사용할 수 있어요.

-- 배열
local fruits = { "사과", "바나나", "체리" }
print(fruits[1])      --> 사과

-- 레코드
local person = { name = "김루아", age = 30 }
print(person.name)    --> 김루아

-- 사전/세트
local seen = {}
seen[obj] = true

배열 인덱스는 1부터 시작해요. #fruits는 배열 길이(여기서 3)를 반환해요.

객체 지향 흉내내기 (Simulating Object Orientation)

__index 메타메서드를 활용하면 루아에서 클래스 기반 객체 지향을 흉내낼 수 있어요. 메서드는 :(콜론) 표기로 호출하고, 첫 인자로 self가 전달돼요.

local Animal = {}
Animal.__index = Animal

function Animal.new(name)
  local self = setmetatable({}, Animal)
  self.name = name
  return self
end

function Animal:speak()
  print(self.name .. "이(가) 울음소리를 냅니다")
end

local dog = Animal.new("멍멍이")
dog:speak()   --> 멍멍이이(가) 울음소리를 냅니다
  • Animal.__index = Animal로 인스턴스가 없는 메서드를 프로토타입에서 조회해요.
  • 상속은 Child.__index = Child + setmetatable(Child, Parent)로 구현해요.

즉시 실행 함수와 클로저 (Immediately-Invoked Functions and Closures)

클로저는 상태를 캡슐화하고, 반복자·콜백·상태 머신을 만들 때 유용해요. 즉시 실행된 함수(IIFE)는 스코프를 격리해 임시 변수의 오염을 막아요.

local timer = (function()
  local last = os.clock()
  return function()
    local now = os.clock()
    local dt = now - last
    last = now
    return dt
  end
end)()

반복자 (Iterators)

반복자는 일반 for에서 쓰는 함수·상태·초기값 조합이에요. pairs, ipairs, string.gmatch가 내장 반복자를 주고, 직접 만들 수도 있어요.

-- 클로저 기반 반복자
local function range(a, b)
  local i = a - 1
  return function()
    i = i + 1
    if i <= b then return i end
  end
end

for n in range(1, 5) do print(n) end   --> 1 2 3 4 5

coroutine.wrap으로 생성기(generator) 반복자를 만들 수도 있어요.

모듈 패턴 (Module Patterns)

모듈은 보통 테이블을 만들어 함수를 담고 반환해요. require로 로드해요.

-- mymath.lua
local M = {}
function M.double(x) return x * 2 end
return M

-- 사용
local mymath = require("mymath")
print(mymath.double(5))   --> 10

첫 글자 대문자 모듈 테이블은 "클래스"로, 소문자는 "함수/라이브러리"로 관례상 구분하기도 해요.

메모이제이션과 약한 테이블 (Memoization and Weak Tables)

비용이 큰 계산 결과를 캐시할 때, 키가 약한 테이블을 쓰면 객체가 사라질 때 캐시도 자동 정리돼요.

local cache = setmetatable({}, { __mode = "k" })

function expensive(obj)
  local cached = cache[obj]
  if cached then return cached end
  local result = heavy_computation(obj)
  cache[obj] = result
  return result
end

자원 정리 — to-be-closed 변수

<close> 속성의 지역 변수는 블록을 벗어날 때 자동으로 __close 메타메서드를 호출해요. 파일·소켓 같은 자원 정리에 결정적이고 깔끔해요.

do
  local f <close> = assert(io.open("data.txt", "r"))
  local content = f:read("a")
  -- 블록 끝에서 f가 자동으로 닫힘
end

코루틴으로 비동기/생성기 흐름 (Coroutines for Async/Generator Flows)

코루틴은 중단·재개 가능한 실행 흐름이에요. 생성기, 소비자-생산자, 상태 머신 등에 쓰여요.

local function producer()
  return coroutine.wrap(function()
    for i = 1, 3 do
      coroutine.yield(i * i)
    end
  end)
end

for v in producer() do print(v) end   --> 1 4 9

오류 처리 관용구 (Error-Handling Idioms)

  • pcall/xpcall: 보호된 호출로 오류를 잡아요.
  • assert: 전제조건을 검사하고 실패 시 오류를 내요.
  • error: 명시적으로 오류를 만들어요.
  • debug.traceback: 오류 메시지에 스택 추적을 덧붙여요.
local ok, res = pcall(risky_fn, arg)
if not ok then
  print("실패:", res)
end

문자열 처리 (String Handling)

string 라이브러리와 .. 연결, 패턴 매칭을 조합해 문자열을 다뤄요.

local name = "루아"
local msg = "안녕, " .. name .. "!"
print(msg)                    --> 안녕, 루아!
local year = string.match("year=2026", "(%d+)")
print(year)                   --> 2026

우아한 디버깅 (Better Debugging)

debug.traceback, print, table.concat을 조합해 상태를 살펴봐요. 테이블을 보기 좋게 출력하는 헬퍼:

local function dump(t, indent)
  indent = indent or ""
  for k, v in pairs(t) do
    if type(v) == "table" then
      print(indent .. k .. " = {")
      dump(v, indent .. "  ")
      print(indent .. "}")
    else
      print(indent .. k .. " = " .. tostring(v))
    end
  end
end

성능 고려

  • 지역 변수를 사용하고 local로 전역 함수를 캐시하면 접근이 빨라요.
  • 반복 문자열 연결 대신 table.concat을 사용해요.
  • 핫 경로의 함수 호출은 가상 머신 오버헤드가 있으니, 루프 안에서 과도한 호출을 피해요.
  • 가비지 컬렉션 부담을 줄이려면 객체 재사용과 약한 테이블을 고려해요.

출처: 루아 프로그래밍 기법 (Lua Programming Techniques)

본문

루아 철학

루아는 "작은 언어"로, 메커니즘은 적지만 조합이 풍부해요. 테이블 하나로 배열·레코드·사전·객체를 모두 표현하고, 메타테이블로 확장하고, 클로저·코루틴으로 흐름을 조합하는 것이 루아 방식이에요.

더 읽을거리

매뉴얼의 각 절(값과 타입, 메타테이블, 문장, 표현식, 코루틴, 표준 라이브러리)과 함께, 루아 공식 웹사이트의 "Programming in Lua" 서적이 실전 기법의 훌륭한 참고자료예요.

더 알아보기