0Pricing
Lua Academy · 강의

xpcall과 메시지 처리기

사용자 지정 처리기와 함께 xpcall을 사용해 자세한 오류 추적 정보를 얻습니다.

xpcall과 메시지 처리기은(는) CoddyKit의 무료 Lua Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Lua Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Lua Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

xpcall 구문

xpcall(f, handler, ...)는 보호 모드에서 인수 ...와 함께 f를 호출하고, 오류가 발생하면 handler(errorObject)를 호출합니다. 처리기의 반환 값은 xpcall의 두 번째 반환 값이 됩니다. pcall과 달리 xpcall은 호출 스택이 유지된 상태에서 처리기를 실행합니다.

local function handler(err)
  return "HANDLED: " .. tostring(err)
end

local ok, msg = xpcall(
  function() error("something bad") end,
  handler
)

print(ok)   -- false
print(msg)  -- HANDLED: ...: something bad

처리기로 사용하는 debug.traceback

가장 일반적인 xpcall 처리기는 debug.traceback입니다. 이를 처리기로 직접 전달하십시오. 전체 호출 스택 추적과 함께 오류 형식을 지정하므로 운영 환경의 오류를 디버깅할 때 매우 유용합니다.

local function level3() error("deep error") end
local function level2() level3() end
local function level1() level2() end

local ok, err = xpcall(level1, debug.traceback)

if not ok then
  -- err contains the full stack trace
  print(err)
end

문맥이 있는 사용자 지정 처리기

사용자 지정 처리기는 문맥을 추가할 수 있습니다. 타임스탬프를 기록하고, 파일에 기록하며, 모니터링 시스템에 알린 다음 형식이 지정된 오류를 반환할 수 있습니다. 이는 Lua 애플리케이션에서 운영 환경의 오류를 처리하는 표준 패턴입니다.

local function errorHandler(err)
  local trace = debug.traceback(err, 2)
  local ts = os.date("%H:%M:%S")
  local report = string.format("[%s] ERROR\n%s", ts, trace)
  -- Could log to file here
  io.stderr:write(report .. "\n")
  return report
end

local ok, msg = xpcall(
  function()
    local t = nil
    return t.field   -- error!
  end,
  errorHandler
)
print("ok:", ok)

처리기에서는 오류를 발생시키면 안 됩니다

메시지 처리기 자체에서 오류를 발생시키면 Lua는 처리기를 다시 호출하지 않고 오류 표시자를 반환합니다. 처리기는 항상 어떤 상황에서도 안전하게 동작하도록 작성하십시오. 실패할 수 있는 IO나 nil 인덱싱을 사용하지 마십시오.

local function safeHandler(err)
  -- Keep handler simple and safe
  local ok, trace = pcall(debug.traceback, err, 2)
  if ok then return trace
  else return tostring(err) .. " (traceback failed)"
  end
end

local ok, msg = xpcall(
  function() error({complex="error table"}) end,
  safeHandler
)
print(ok, type(msg))

주 반복문을 위한 xpcall

장시간 실행되는 프로그램(서버, 게임 반복문)에서는 처리되지 않은 오류를 잡아 기록하고 프로그램이 중단되지 않도록 주 함수를 xpcall로 감싸십시오. 그러면 주 반복문에서 다시 시작할지 종료할지 결정할 수 있습니다.

local function mainApp()
  -- simulate work
  for i = 1, 3 do
    print("Tick", i)
    if i == 2 then error("transient error") end
  end
end

local function handler(e)
  return debug.traceback("App error: "..tostring(e), 2)
end

local ok, err = xpcall(mainApp, handler)
if not ok then
  print("Application crashed:\n" .. err)
end

구조화된 오류 보고

xpcall을 구조화된 오류 객체 및 풍부한 처리기와 결합하여 디버깅이나 모니터링 대시보드에 사용할 수 있는 상세하고 실행 가능한 오류 보고서를 생성하십시오.

local function handler(err)
  local info = {
    error   = tostring(err),
    time    = os.date("!%Y-%m-%dT%H:%M:%SZ"),
    trace   = debug.traceback(nil, 2),
  }
  return info
end

local ok, report = xpcall(
  function() error({code=500, msg="internal error"}) end,
  handler
)

if not ok then
  print("Time:", report.time)
  print("Error:", report.error)
  -- print("Trace:", report.trace)
end

코루틴을 위한 xpcall

코루틴 내부에서는 pcall이 정상적으로 작동합니다. 코루틴 내부 오류의 호출 스택 추적을 얻으려면 코루틴 본문을 xpcall로 감싸십시오. 처리기는 코루틴의 호출 스택 문맥 안에서 실행됩니다.

local function co_body()
  error("error inside coroutine")
end

local co = coroutine.create(function()
  local ok, err = xpcall(co_body, debug.traceback)
  if not ok then
    print("Caught in coroutine:", err:match("([^\n]+)"))
  end
end)

coroutine.resume(co)

오류 객체 보강

처리기는 단순한 문자열 오류를 풍부한 객체로 보강하거나, 이미 풍부한 객체에 정보를 더 추가할 수 있습니다. 이를 통해 하위 수준 코드는 단순한 오류를 발생시키고 처리기는 문맥(요청 ID, 사용자 세션, 환경 정보)을 추가할 수 있습니다.

local requestID = "req-123"

local function handler(err)
  if type(err) == "string" then
    return {message=err, requestID=requestID, level="error"}
  end
  err.requestID = requestID
  return err
end

local ok, result = xpcall(
  function() error("database timeout") end,
  handler
)

if not ok then
  print(result.message, result.requestID)
  -- database timeout  req-123
end

pcall과 xpcall 비교

pcall을 사용할 때: 오류 값만 필요할 때, 오류가 예상되며 해당 위치에서 처리할 때, 단순성이 중요할 때입니다. xpcall을 사용할 때: 호출 스택 추적이 필요할 때, 최상위 경계에 있을 때, 모든 오류에 문맥을 추가하려 할 때입니다.

-- pcall: simple, no overhead
local ok, err = pcall(function()
  return 1/0   -- no error in Lua! returns inf
end)
print(ok, err)   -- true  inf

-- xpcall: adds traceback
local ok2, err2 = xpcall(
  function() error("real error") end,
  debug.traceback
)
print(ok2)       -- false
print(err2:sub(1,40))  -- first line of traceback

처리기의 반환 값

처리기가 무엇을 반환하든 xpcall의 두 번째 값이 됩니다. 처리기가 nil을 반환하면 xpcall의 두 번째 반환 값도 nil입니다. 원래 오류 객체에 추가 정보를 더해 반환하는 처리기가 가장 유연한 방식입니다.

local function enrichedHandler(err)
  return {
    original = err,
    traceback = debug.traceback(nil, 2),
    timestamp = os.time(),
  }
end

local ok, report = xpcall(
  function() error("oops") end,
  enrichedHandler
)

if not ok then
  print(type(report))          -- table
  print(report.original)       -- ...: oops
  print(report.timestamp > 0)  -- true
end

빠른 확인

pcall에 비해 xpcall이 갖는 핵심적인 장점은 무엇입니까?

복습: xpcall

요약:

  • xpcall(f, handler, ...) — 호출 스택이 유지된 상태에서 처리기가 실행됩니다.
  • 전체 호출 스택 추적을 얻으려면 debug.traceback을 처리기로 사용합니다.
  • 처리기에서 오류를 발생시키면 안 되므로 단순하게 유지해야 합니다.
  • 처리기에서 문맥을 추가하여 오류를 보강합니다.
  • 주 반복문이나 서버 처리기를 xpcall로 감쌉니다.
  • 처리기의 반환 값은 xpcall의 두 번째 반환 값이 됩니다.

자주 묻는 질문

“xpcall과 메시지 처리기” 강의는 무료인가요?

네 — “xpcall과 메시지 처리기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Lua Academy 강의 전체를 잠금 해제할 수 있습니다. Lua Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“xpcall과 메시지 처리기”에서 뭘 배우나요?

사용자 지정 처리기와 함께 xpcall을 사용해 자세한 오류 추적 정보를 얻습니다. 브라우저에서 직접 실행하는 실습 코드로 Lua Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Lua Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Lua Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“xpcall과 메시지 처리기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Lua Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Lua Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. error() 함수
  2. pcall을 사용한 보호된 호출
  3. xpcall과 메시지 처리기
  4. 구조화된 오류 객체
← Lua Academy(으)로 돌아가기