"매 ReferenceError 의 root cause 매 hoisting, TDZ, circular import, async timing 의 4 가지로 collapse". 매 case study (combat system 의 reference error) 를 통해 매 systematic debug pipeline 정리.
매 핵심
매 ReferenceError 4 카테고리
Undeclared: variable 매 declare 안됨 (typo, missing import).
TDZ: let/const 매 init 전 access (temporal dead zone).
Circular import: A imports B, B imports A → 매 partially-loaded module.
Async timing: top-level await, dynamic import 의 race.
매 Combat case (post-mortem 요약)
Symptom: ReferenceError: CombatEngine is not defined 매 production only.
Root cause: Vite tree-shaking 의 side-effect import 의 elimination.
Fix: package.json 의 "sideEffects": ["./src/combat/registry.ts"].
매 Debug 절차
Reproduce: minimal repo.
Stack trace: 매 first frame 의 file:line.
Bisect: git bisect or feature flag.
Verify: regression test 추가.
💻 패턴
TDZ 의 detection
// BAD — TDZ
console.log(x);// ReferenceError
letx=1;// GOOD — declare 먼저
letx: number;x=1;console.log(x);
Circular import resolve
// a.ts
import{B}from'./b';exportclassA{b=newB();}// b.ts — circular
// import { A } from './a'; // 매 X
// 매 type-only import 로 break:
importtype{A}from'./a';exportclassB{parent?: A;}
functionparseRefError(err: Error):{name: string;file?: string;line?: number}{constm=err.message.match(/(\w+) is not defined/);constframe=err.stack?.split('\n')[1]?.match(/at .* \((.+):(\d+):\d+\)/);return{name: m?.[1]??'unknown',file: frame?.[1],line: frame?Number(frame[2]):undefined};}
Regression test
import{describe,it,expect}from'vitest';import{CombatEngine}from'@/combat';describe('combat module loading',()=>{it('exports CombatEngine after tree-shake',()=>{expect(CombatEngine).toBeDefined();expect(typeofCombatEngine).toBe('function');});it('registry has registered abilities',async()=>{const{abilityRegistry}=awaitimport('@/combat/registry');expect(abilityRegistry.size).toBeGreaterThan(0);});});