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
endpcall과 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- error() 함수
- pcall을 사용한 보호된 호출
- xpcall과 메시지 처리기
- 구조화된 오류 객체