모듈 패턴과 모범 사례
local M = {} 패턴을 사용하고 공개 API를 깔끔하게 노출합니다.
모듈 패턴과 모범 사례은(는) CoddyKit의 무료 Lua Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Lua Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Lua Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
M = {} 패턴
Lua의 보편적인 모듈 패턴은 로컬 테이블을 선언하고, 내용을 채운 다음 반환하는 방식입니다. 모든 공개 기호는 M에 넣고, 모든 비공개 도우미는 일반 로컬 항목으로 둡니다. 명확하고 간결하며 어디서나 사용할 수 있습니다.
-- The canonical module pattern
local M = {}
-- Private helper (not exported)
local function validate(x)
return type(x) == "number" and x >= 0
end
-- Public API
function M.sqrt(x)
assert(validate(x), "expected non-negative number")
return math.sqrt(x)
end
M.PI = math.pi
return M자기 참조 모듈
모듈 내부에서 함수는 이름(M.foo())으로 또는 로컬 항목으로 다른 모듈 함수를 호출할 수 있습니다. 로컬 항목을 사용하면 약간 더 빠르고, M.foo()를 사용하면 사용자가 M.foo를 재정의할 수 있어 내부 호출에서도 재정의된 함수를 사용하게 됩니다(몽키 패치).
local M = {}
-- Option A: use M.foo inside (allows override)
function M.double(n) return M.multiply(n, 2) end
function M.multiply(a, b) return a * b end
-- Option B: use local function (faster, no override)
local function mul(a, b) return a * b end
function M.triple(n) return mul(n, 3) end
return M싱글턴 패턴
모듈은 싱글턴처럼 동작할 수 있습니다. 즉, 모든 호출자가 공유하는 변경 가능한 내부 상태를 가집니다. require가 모듈을 캐시하므로 모든 require("mod") 호출은 동일한 상태를 가진 같은 객체를 받습니다.
-- config.lua (singleton)
local M = {}
local _config = {env="dev", logLevel="info"}
function M.set(key, val)
_config[key] = val
end
function M.get(key)
return _config[key]
end
function M.load(t)
for k,v in pairs(t) do _config[k]=v end
end
return M
-- All callers share the same config:네임스페이스로서의 모듈
전역 테이블을 오염시키지 않도록 모듈을 순수한 네임스페이스로 사용하십시오. 다른 언어의 패키지처럼 관련 상수와 유틸리티를 하나의 이름 아래에 그룹화할 수 있습니다.
-- constants.lua
local M = {
HTTP = {
OK=200, CREATED=201, NO_CONTENT=204,
BAD_REQUEST=400, UNAUTHORIZED=401,
NOT_FOUND=404, SERVER_ERROR=500,
},
COLORS = {RED="#FF0000", GREEN="#00FF00", BLUE="#0000FF"},
MAX_RETRIES = 3,
TIMEOUT_SEC = 30,
}
return M
-- local C = require("constants")
-- if status == C.HTTP.NOT_FOUND then ...팩토리 모듈
일반 테이블 대신 팩토리 함수를 내보내는 모듈입니다. 팩토리는 각자 고유한 비공개 상태를 가진 새 인스턴스를 만들고 반환합니다. 이는 모듈 수준에서 구현하는 클래스 패턴입니다.
-- logger.lua
local M = {}
function M.new(name, level)
level = level or "info"
local levels = {debug=1,info=2,warn=3,error=4}
local self = {}
function self.log(msgLevel, msg)
if levels[msgLevel] >= levels[level] then
print(string.format("[%s][%s] %s", name, msgLevel:upper(), msg))
end
end
function self.info(msg) self.log("info", msg) end
function self.warn(msg) self.log("warn", msg) end
function self.error(msg) self.log("error", msg) end
return self
end
return M모듈 초기화 함수
일부 모듈은 사용하기 전에 구성이 필요합니다. M.init(config) 함수를 제공하여 구성을 모듈의 비공개 상태에 저장하십시오. 이렇게 하면 의존성 주입과 테스트가 가능해집니다.
-- db.lua
local M = {}
local pool = nil
function M.init(config)
pool = {
host = config.host or "localhost",
port = config.port or 5432,
connections = {},
}
print("DB initialized:", pool.host, pool.port)
end
function M.query(sql)
assert(pool, "call db.init() first")
-- ... execute query
return {}
end
return M불변 모듈
__newindex를 사용해 모든 쓰기를 차단하면 사용자가 실수로 모듈 API를 수정하지 못하게 할 수 있습니다. 실수로 몽키 패치를 적용하면 문제가 발생할 수 있는 라이브러리 모듈에 특히 유용합니다.
local function freeze(t)
return setmetatable({}, {
__index = t,
__newindex = function(_, k, _)
error("module is read-only, cannot set: " .. tostring(k), 2)
end
})
end
local M = {}
function M.add(a, b) return a + b end
function M.sub(a, b) return a - b end
return freeze(M)LDoc를 사용한 문서화
Lua 모듈을 문서화하는 일반적인 규칙은 --- 접두사를 사용하는 LDoc 스타일 주석입니다. 언어에서 강제하지는 않지만, 이러한 주석을 사용하면 문서 생성 도구가 API 문서를 자동으로 만들 수 있습니다.
--- A utility module for string operations.
-- @module stringutils
local M = {}
--- Trim leading and trailing whitespace.
-- @param s string The input string.
-- @return string The trimmed string.
function M.trim(s)
return s:match("^%s*(.-)%s*$")
end
--- Count occurrences of a substring.
-- @param str string The string to search.
-- @param sub string The substring to count.
-- @return number Count of occurrences.
function M.count(str, sub)
local _, n = str:gsub(sub, "")
return n
end
return M모듈 테스트
모듈을 require한 다음 각 함수를 실행하여 테스트하십시오. 간단한 테스트 실행기나 busted(Lua 테스트 프레임워크)를 사용하십시오. 테스트는 모듈 경로를 그대로 반영하는 별도의 파일에 두십시오.
-- test/test_stringutils.lua
local su = require("stringutils")
local function test(name, fn)
local ok, err = pcall(fn)
if ok then print("[PASS] " .. name)
else print("[FAIL] " .. name .. ": " .. err)
end
end
test("trim removes spaces", function()
assert(su.trim(" hello ") == "hello")
end)
test("trim empty string", function()
assert(su.trim("") == "")
end)
test("count occurrences", function()
assert(su.count("banana", "a") == 3)
end)모듈 조합
복잡한 시스템은 여러 모듈을 조합하여 구성합니다. 주 진입점이 하위 모듈을 require하고 서로 연결합니다. 이러한 관심사 분리는 각 모듈이 특정 역할에 집중하고 독립적으로 테스트될 수 있게 합니다.
-- app.lua (main entry point)
local config = require("config")
local db = require("db")
local server = require("server")
-- Configure from environment
config.load({
dbHost = os.getenv("DB_HOST") or "localhost",
port = tonumber(os.getenv("PORT")) or 8080,
})
-- Wire modules together
db.init({host=config.get("dbHost"), port=5432})
server.init({port=config.get("port"), db=db})
server.start()빠른 확인
local M = {} ... return M 모듈 패턴의 주된 목적은 무엇입니까?
복습: 모듈 모범 사례
요약:
- 항상
local M = {} ... return M을 사용합니다 - 비공개 = 파일 수준 로컬 항목, 공개 = M 필드
- 싱글턴: require가 모듈 인스턴스를 캐시합니다
- 인스턴스별 상태에는 팩토리 함수를 사용합니다
- __newindex로 모듈을 고정하여 수정을 방지합니다
- 별도의 파일에서 테스트하고 --- 주석으로 문서화합니다
자주 묻는 질문
“모듈 패턴과 모범 사례” 강의는 무료인가요?
네 — “모듈 패턴과 모범 사례” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Lua Academy 강의 전체를 잠금 해제할 수 있습니다. Lua Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“모듈 패턴과 모범 사례”에서 뭘 배우나요?
local M = {} 패턴을 사용하고 공개 API를 깔끔하게 노출합니다. 브라우저에서 직접 실행하는 실습 코드로 Lua Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Lua Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Lua Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“모듈 패턴과 모범 사례” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Lua Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Lua Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- require 함수
- 모듈 파일 작성
- package.path와 package.cpath
- 모듈 패턴과 모범 사례