콘솔은 당신을 속이고 있습니다
브라우저 DevTools는 디버깅 중에 당신을 오도할 수 있습니다. 도구가 고장 난 것이 아닙니다. 완벽한 정확도가 아닌 속도에 최적화되어 있기 때문입니다.
왜 항상 console.log를 신뢰할 수 없는지 그 이유를 알려드립니다.
• 지연 평가 (Lazy Evaluation) 객체를 로그로 남길 때, 브라우저는 이를 즉시 복사하지 않습니다. 대신 실시간 참조(live reference)를 저장합니다. 브라우저는 화살표를 클릭하여 객체를 확장할 때만 속성을 읽습니다. 만약 클릭하기 전에 코드가 해당 객체를 변경한다면, 이전 값이 아닌 변경된 새로운 값을 보게 됩니다.
• 하이젠버그 효과 (The Heisenbug Effect)
console.log를 추가하는 것이 오히려 버그를 숨길 수도 있습니다. 로깅은 시간과 리소스를 소모합니다. 실행 속도가 빠른 코드에서 이 미세한 지연은 애플리케이션의 타이밍을 바꿀 수 있습니다. 이로 인해 관찰하는 동안에는 레이스 컨디션(race condition)이 발생하지 않게 되어, 버그가 사라진 것처럼 보일 수 있습니다.
• React 상태 트랩 (React State Traps)
setCount 호출 직후에 상태를 로깅하면 이전 값이 나타납니다. 이는 클로저(closure)와 React의 업데이트 스케줄링 방식 때문에 발생합니다. 로깅한 값은 다음 렌더링이 아닌 현재 렌더링에 속한 값입니다.
• 소스 맵 오류 (Source Map Errors) 프로덕션 환경에서는 코드가 압축(minified)되고 번들링됩니다. 만약 소스 맵이 오래되었거나 부정확하다면, 콘솔은 잘못된 코드 라인을 가리킬 것입니다. 에러 자체는 실제 상황이지만, 위치가 틀린 것입니다.
더 나은 디버깅 방법:
structuredClone을 사용하여 스냅샷 찍기 객체를 현재 상태 그대로 보고 싶다면 다음을 사용하세요:const snap = structuredClone(obj)console.log(snap)큰 객체 대신 원시 값(primitives) 로깅하기 ID, 타임스탬프 또는 상태 문자열을 로깅하세요. 이렇게 하면 지연 평가의 위험과 성능 저하를 줄일 수 있습니다.
디버거(debugger) 사용하기 중단점(breakpoint)을 사용하여 실행을 일시 중지하세요. 이를 통해 코드의 타이밍을 변경하지 않고도 실제 상태와 콜 스택(call stack)을 조사할 수 있습니다.
프레임워크 DevTools 사용하기 React나 Vue를 사용한다면 해당 프레임워크 전용 DevTools를 사용하세요. 로그보다 생명주기(lifecycle)와 렌더링 단계를 더 정확하게 보여줍니다.
콘솔은 빠른 탐색을 위한 훌륭한 도구입니다. 하지만 콘솔을 최종적인 신뢰할 수 있는 정보원(source of truth)으로 사용하지는 마세요.
