0Pricing
Lua Academy · 강의

모듈 패턴과 모범 사례

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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. require 함수
  2. 모듈 파일 작성
  3. package.path와 package.cpath
  4. 모듈 패턴과 모범 사례
← Lua Academy(으)로 돌아가기