quad/.claude/audit/fallback-xpcall-verification.md
qwreey 2d9cc7b5f7
docs(base): Fallback/Traceback 승격 — research/에서 base/fallback-plan.md로
pcall 기반 Fallback과 xpcall+debug.traceback 기반 Traceback으로 분리,
정확한 제네릭 시그니처(OkComp/ErrComp/Args... 독립 제네릭)와 err: any를
확정. 패키지(quad-base)·이름(Fallback/Traceback) 확정으로 남은 열린
질문이 없어져 base/로 승격. 스파이크를 audit/fallback-xpcall-spike.luau로
옮기고 base/fallback-plan.md와 이름을 맞춰 내부 함수를 Traceback으로
정정, audit/fallback-xpcall-verification.md에 실측 결과 기록. README/
question.md/archive/question-resolved.md/lifecycle-hooks-plan.md의 상호
참조 동기화.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 04:32:29 +09:00

3.1 KiB

Fallback/Tracebackxpcall+debug.traceback 배선 실측 결과

상태: 전부 확인(2026-08-14). base/fallback-plan.mdTraceback 메커니즘 스케치가 실제 Luau에서 그대로 동작하는지 luau 스파이크 (fallback-xpcall-spike.luau, 같은 폴더)로 검증 — 10개 검증 전부 통과, luau-analyze도 클린(타입 에러 0).

배경

base/fallback-plan.md(당시엔 research/ 초안) 단계에서 열어뒀던 질문: xpcall의 에러 핸들러 안에서 클로저 업밸류에 쓴 값(trace)이 xpcall 리턴 이후에도 바깥에서 정상적으로 보이는지, debug.traceback이 에러 시점 스택을 정확히 담는지 — 의사코드 수준이라 Luau로 직접 부딪혀본 적 없었음.

확인된 것

  1. 성공 경로onError가 아예 안 불리고 base의 원래 반환값이 그대로 통과함.
  2. 실패 경로onError의 반환값이 최종 결과, 에러 메시지가 onError에 정상 전달됨.
  3. 클로저 업밸류 배선(가장 핵심)xpcall의 에러 핸들러 안에서 업밸류 trace에 쓴 값이 xpcall 리턴 후 onError 호출 시점에 정상적으로 채워져 있음.
  4. 중첩 호출에서의 debug.traceback — 3단 중첩(level1→level2→level3) 호출에서도 debug.traceback(nil, 2)가 실패 지점(level3)까지 정확히 담음. level=2가 익명 에러 핸들러 프레임 자체를 올바르게 스킵.
  5. err: any — 비-문자열 에러 값(error({code=42})류 table)도 손실 없이 onError에 그대로 전달됨. 사용자가 별도로 Luau REPL에서 error({aa=true})pcall로 잡은 뒤 b.aa == true를 직접 재확인, 스파이크 결과와 일치.
  6. 커링 관용구onError 자체를 클로저로 만들어 추가 컨텍스트를 캡처하는 관용구가 Fallback/Traceback 쪽 손댈 것 없이 그대로 동작.
  7. error(msg)의 기본 위치 접두(신규 발견) — 레벨 지정 없이 (Luau 기본 level=1) error("메시지")를 호출하면 onError가 받는 err"파일:줄: 메시지"처럼 위치 접두가 자동으로 붙음. error(msg, 0)으로 호출해야 접두 없는 순수 메시지가 옴 — quad가 붙이는 게 아니라 Luau error() 자체의 기본 동작.
  8. vararg 컴포넌트 시그니처(Args...) -> Comp 모양(여러 인자를 받는 컴포넌트 함수)도 성공/실패 경로 둘 다 정상 동작.

실측 방법

fallback-xpcall-spike.luau(같은 폴더) — base/fallback-plan.mdTraceback 의사코드를 그대로 옮겨 10개 assert로 검증. luau fallback-xpcall-spike.luau로 실행, luau-analyze fallback-xpcall-spike.luau로 타입 체크(무출력 = 클린).

참고

Fallback(순수 pcall, trace 없음) 쪽은 Traceback보다 메커니즘이 단순(에러 핸들러/업밸류 배선이 아예 없음)해서 별도 스파이크 없이도 pcall 자체의 기본 동작(성공/실패 경로, err: any 통과)으로 충분히 갈음됨 — 위 5번 확인이 그대로 적용됨.