๐ŸŒฑ <groot/>
'์ด ๋ฒ„ํŠผ ๋Œ€์ฒด ์–ด๋А ํŒŒ์ผ์ด์•ผ?' โ€” ์šฐํด๋ฆญ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ์†Œ์Šค๋กœ ์ ํ”„ํ•˜๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค | Groot's Tech Blog
โš›๏ธReact

'์ด ๋ฒ„ํŠผ ๋Œ€์ฒด ์–ด๋А ํŒŒ์ผ์ด์•ผ?' โ€” ์šฐํด๋ฆญ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ์†Œ์Šค๋กœ ์ ํ”„ํ•˜๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค

2026.07.02ยท5๋ถ„ ์ฝ๊ธฐ

์‹œ์ž‘์€ ์‚ฌ์†Œํ•œ ๋ถˆํŽธ์ด์—ˆ๋‹ค

ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋ฒ„ํŠผ ํ•˜๋‚˜๋ฅผ ๊ณ ์น˜๋ ค๊ณ  ๊ทธ ๋ฒ„ํŠผ์ด ์–ด๋А ํŒŒ์ผ, ๋ช‡ ๋ฒˆ์งธ ์ค„์—์„œ ๊ทธ๋ ค์ง€๋Š”์ง€ ์ฐพ๋Š” ์ผ. ๋ณ„๊ฒƒ ์•„๋‹Œ ๊ฒƒ ๊ฐ™์ง€๋งŒ, ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ์ด๊ฒŒ ์€๊ทผํžˆ ์‹œ๊ฐ„์„ ์žก์•„๋จน๋Š”๋‹ค. ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์œผ๋กœ ๊ฒ€์ƒ‰ํ•ด๋„ ๊ฐ™์€ ์ด๋ฆ„์ด ์—ฌ๋Ÿฌ ๊ฐœ๊ณ , ์—ฌ๋Ÿฌ ๋ฒˆ ๊ฐ์‹ธ์ง„(HOC๋กœ ๋ž˜ํ•‘๋œ) ์ปดํฌ๋„ŒํŠธ๋Š” ์ •์˜ ์œ„์น˜์™€ ์‹ค์ œ ๋ Œ๋” ์œ„์น˜๊ฐ€ ๋‹ค๋ฅด๋‹ค.

React DevTools๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋А ์ •๋„ ํ’€์–ด์คฌ๋‹ค. ์˜ˆ์ „์—” Fiber์— _debugSource๊ฐ€ ์žˆ์–ด์„œ "์ด ์š”์†Œ๊ฐ€ ์–ด๋””์„œ ์™”๋Š”์ง€"๋ฅผ ์•Œ ์ˆ˜ ์žˆ์—ˆ์œผ๋‹ˆ๊นŒ. (์• ์ดˆ์— ๊ฐœ๋ฐœ ๋นŒ๋“œ + jsxDEV ๋ณ€ํ™˜์—์„œ๋งŒ ์ฑ„์›Œ์ง€๋˜ ๊ฐœ๋ฐœ์šฉ ์ •๋ณด์˜€๋‹ค.) ๊ทธ๋Ÿฐ๋ฐ React 19์—์„œ _debugSource๊ฐ€ ์ œ๊ฑฐ๋๋‹ค. ๋‚ด๊ฐ€ ๊ธฐ๋Œ€๋˜ ๋ฐฉ๋ฒ•์ด ์‚ฌ๋ผ์ง„ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ ์ง์ ‘ ๋งŒ๋“ค๊ธฐ๋กœ ํ–ˆ๋‹ค. ๋ชฉํ‘œ๋Š” ํ•˜๋‚˜์˜€๋‹ค.

ํ™”๋ฉด์—์„œ ์š”์†Œ๋ฅผ ์šฐํด๋ฆญํ•˜๋ฉด ๊ทธ ์†Œ์Šค ์ฝ”๋“œ ์œ„์น˜๋กœ ๋ฐ”๋กœ ์ ํ”„ํ•œ๋‹ค.

๋งŒ๋“ค๊ณ  ๋ณด๋‹ˆ react-code-locator๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ npm์— ์˜ฌ๋ฆด ๋งŒํผ ์“ธ๋ชจ๊ฐ€ ์žˆ์—ˆ๊ณ , ๋งŒ๋“œ๋Š” ๊ณผ์ •์—์„œ ๋ฐฐ์šด ๊ฒŒ ํ›จ์”ฌ ๋งŽ์•˜๋‹ค. ๊ทธ ์ด์•ผ๊ธฐ๋ฅผ ์ •๋ฆฌํ•œ๋‹ค.

ํฐ ๊ทธ๋ฆผ: ๋นŒ๋“œ ํƒ€์ž„ + ๋Ÿฐํƒ€์ž„ ๋‘ ๋‹จ๊ณ„

ํ•ต์‹ฌ ์•„์ด๋””์–ด๋Š” ๋‘ ๋‹จ๊ณ„๋กœ ๋‚˜๋‰œ๋‹ค.

  1. ๋นŒ๋“œ ํƒ€์ž„ โ€” ๋ฒˆ๋“ค๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ›‘์œผ๋ฉด์„œ, ๊ฐ JSX ์š”์†Œ์™€ ์ปดํฌ๋„ŒํŠธ ์„ ์–ธ์— "์ด๊ฑด ํŒŒ์ผ:์ค„:์นธ์—์„œ ์™”๋‹ค"๋Š” ์œ„์น˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ์ž…ํ•œ๋‹ค.
  2. ๋Ÿฐํƒ€์ž„ โ€” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋ฉด, React Fiber ํŠธ๋ฆฌ๋ฅผ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋ฉฐ ์ฃผ์ž…ํ•ด๋‘” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„ ์†Œ์Šค ์œ„์น˜๋ฅผ ์•Œ์•„๋‚ด๊ณ , ํ•˜์ด๋ผ์ดํŠธํ•˜๊ฑฐ๋‚˜ ์—๋””ํ„ฐ๋ฅผ ์—ฐ๋‹ค.

_debugSource์ฒ˜๋Ÿผ React ๋‚ด๋ถ€ ๊ตฌํ˜„์— ๊ธฐ๋Œ€์ง€ ์•Š๊ณ  ๋‚ด๊ฐ€ ์ง์ ‘ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์‹ฌ๊ธฐ ๋•Œ๋ฌธ์—, React ๋ฒ„์ „์ด ๋ฐ”๋€Œ์–ด๋„ ๋™์ž‘ํ•œ๋‹ค. ์ด๊ฒŒ ์ด ์ ‘๊ทผ์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด๋‹ค.

1๋‹จ๊ณ„ โ€” ์†Œ์Šค ์œ„์น˜๋ฅผ ์ฝ”๋“œ์— ์‹ฌ๊ธฐ

๋นŒ๋“œ ํƒ€์ž„ ๋ณ€ํ™˜์˜ ์›์น™์€ ๋”ฑ ํ•˜๋‚˜์˜€๋‹ค.

์›๋ณธ ์ฝ”๋“œ๋ฅผ ์ ˆ๋Œ€ ์žฌ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค.

AST๋ฅผ ํŒŒ์‹ฑํ•ด์„œ ๋‹ค์‹œ ์ฝ”๋“œ๋กœ ๋ฝ‘์•„๋‚ด๋ฉด(์ฝ”๋“œ ์ œ๋„ˆ๋ ˆ์ด์…˜), ์›๋ณธ์˜ ํฌ๋งคํŒ…์ด๋‚˜ TypeScript/JSX ๋ฌธ๋ฒ•์ด ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ํ‹€์–ด์งˆ ์œ„ํ—˜์ด ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ํŒŒ์‹ฑ์€ ์œ„์น˜๋ฅผ ์ฐพ๋Š” ์šฉ๋„๋กœ๋งŒ ์“ฐ๊ณ , ์‹ค์ œ ์‚ฝ์ž…์€ ์›๋ณธ ๋ฌธ์ž์—ด์„ ๊ทธ๋Œ€๋กœ ๋‘” ์ฑ„ ํ•„์š”ํ•œ ์ง€์ ์— ๋ฌธ์ž์—ด๋งŒ ๋ผ์›Œ ๋„ฃ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐ”๋‹ค.

import * as acorn from "acorn";
import acornJsx from "acorn-jsx";
import acornTs from "acorn-typescript";
import MagicString from "magic-string";

// .js/.jsx/.tsx: TypeScript ํ”Œ๋Ÿฌ๊ทธ์ธ์ด JSX ํ”Œ๋Ÿฌ๊ทธ์ธ๋ณด๋‹ค ๋จผ์ € ์™€์•ผ ํ•œ๋‹ค
const ParserTSX = acorn.Parser.extend(acornTs(), acornJsx());
// .ts ์ „์šฉ: JSX ํ”Œ๋Ÿฌ๊ทธ์ธ ์—†์Œ
const ParserTS = acorn.Parser.extend(acornTs());

์ฐพ์€ ์œ„์น˜๋งˆ๋‹ค ์‚ฝ์ž…ํ•  ํ…์ŠคํŠธ๋ฅผ ๋ชจ์•„๋’€๋‹ค๊ฐ€, ๋งˆ์ง€๋ง‰์— MagicString์œผ๋กœ ํ•œ ๋ฒˆ์— ๊ฝ‚๋Š”๋‹ค.

const s = new MagicString(code);
for (const { at, text } of insertions) {
  s.appendLeft(at, text);
}
return { code: s.toString(), map: s.generateMap({ hires: true }) };

๋ฌด์—‡์„ ์‹ฌ๋А๋ƒ๋ฉด:

  • JSX ์š”์†Œ์—๋Š” ์†Œ์Šค ์œ„์น˜๋ฅผ ๋‹ด์€ prop์„ ๋ถ™์ธ๋‹ค. โ†’ <div ... >๊ฐ€ "์ด div๋Š” src/App.tsx:12:5์—์„œ ์™”๋‹ค"๋ฅผ ๋“ค๊ณ  ๋‹ค๋‹ˆ๊ฒŒ ๋œ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ ์„ ์–ธ(ํ•จ์ˆ˜/ํด๋ž˜์Šค/ํ™”์‚ดํ‘œ ํ•จ์ˆ˜)์—๋Š” ์„ ์–ธ ์งํ›„์— Comp.__componentSourceLoc = "src/App.tsx:8:1" ๊ฐ™์€ ํ• ๋‹น๋ฌธ์„ ๋ถ™์ธ๋‹ค.

์‚ฝ์งˆ 1: <T,> ์ œ๋„ค๋ฆญ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ ํ•จ์ •

.tsx์—์„œ JSX์™€ TypeScript ์ œ๋„ค๋ฆญ์€ ๋ฌธ๋ฒ•์ด ์ถฉ๋Œํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด const f = <T,>(x: T) => x ์˜ <T,>๋ฅผ JSX ํŒŒ์„œ๊ฐ€ JSX ํƒœ๊ทธ๋กœ ์˜คํ•ดํ•œ๋‹ค. ์ด๊ฑธ ๋ฌด๋ฆฌํ•˜๊ฒŒ ํŒŒ์‹ฑํ•˜๋ ค๋‹ค ํŒŒ์ผ ์ „์ฒด๊ฐ€ ๊นจ์ง€๋А๋‹ˆ, .ts ํŒŒ์ผ์€ ์•„์˜ˆ JSX ํŒŒ์„œ๋ฅผ ํƒœ์šฐ์ง€ ์•Š๋„๋ก ํŒŒ์„œ๋ฅผ ๋ถ„๋ฆฌํ–ˆ๋‹ค. (.ts์—” JSX๊ฐ€ ์˜ฌ ์ˆ˜ ์—†์œผ๋‹ˆ ์•ˆ์ „ํ•˜๋‹ค.)

์‚ฝ์งˆ 2: HOC๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๋Š” "์กฐ์‹ฌ์Šค๋Ÿฝ๊ฒŒ" ์‹ฌ์–ด์•ผ ํ•œ๋‹ค

export default memo(MyComp), styled.div\...`` ์ฒ˜๋Ÿผ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด๋‚˜ ํƒœ๊ทธ๋“œ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๊ฐ์‹ผ ๊ฒฝ์šฐ, ๋ฐ˜ํ™˜๊ฐ’์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ "wrapped" ์ผ€์ด์Šค๋Š” ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ์”Œ์›Œ์„œ, ๊ฐ’์ด ๊ฐ์ฒด/ํ•จ์ˆ˜์ผ ๋•Œ๋งŒ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ• ๋‹นํ•˜๋„๋ก ํ–ˆ๋‹ค.

// ์›์‹œ๊ฐ’์ด๋ฉด ์กฐ์šฉํžˆ ๊ฑด๋„ˆ๋›ด๋‹ค (throw ์—†์Œ)
Name && (typeof Name === "object" || typeof Name === "function")
  && (Name.__componentSourceLoc = "src/App.tsx:8:1");

๋ฐ˜๋Œ€๋กœ ํ™”์‚ดํ‘œ/ํ•จ์ˆ˜/ํด๋ž˜์Šค ํ‘œํ˜„์‹์ฒ˜๋Ÿผ ๊ฐ’์ด ํ™•์‹คํ•œ "direct" ์ผ€์ด์Šค๋Š” ๊ฐ€๋“œ ์—†์ด ๋ฐ”๋กœ ํ• ๋‹นํ•œ๋‹ค. ์ด๋Ÿฐ ์„ธ๋ฐ€ํ•œ ๋ถ„๊ธฐ๊ฐ€ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์˜ ์˜จ๊ฐ– ์ปดํฌ๋„ŒํŠธ ํŒจํ„ด์„ ๊ฒฌ๋””๊ฒŒ ํ•ด์คฌ๋‹ค.

2๋‹จ๊ณ„ โ€” ๋Ÿฐํƒ€์ž„์—์„œ Fiber๋ฅผ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๊ธฐ

๋ธŒ๋ผ์šฐ์ €์—์„œ ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋ฉด, ๊ทธ DOM์— ๋ถ™์€ React Fiber๋ฅผ ์ฐพ๋Š”๋‹ค. React๋Š” DOM ๋…ธ๋“œ์— __reactFiber$... ๊ฐ™์€ ํ‚ค๋กœ Fiber๋ฅผ ๋งค๋‹ฌ์•„ ๋‘”๋‹ค.

function getReactFiberKey(element: Element) {
  return Object.keys(element).find(
    (k) => k.startsWith("__reactFiber$") ||
           k.startsWith("__reactInternalInstance$"),
  );
}

์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ Fiber์˜ return(๋ถ€๋ชจ)์„ ํƒ€๊ณ  ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€๋ฉฐ, ๋นŒ๋“œ ํƒ€์ž„์— ์‹ฌ์–ด๋‘” ์†Œ์Šค ์ •๋ณด๋ฅผ ๋ชจ์€๋‹ค. ์žฌ๋ฏธ์žˆ๋Š” ๊ฑด "ํ™”๋ฉด์—์„œ ๋ณด์ด๋Š” ์œ„์น˜"์™€ "์‹ค์ œ ๊ตฌํ˜„ ์œ„์น˜"๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋‘ ๊ฐ€์ง€ ๋ชจ๋“œ๋ฅผ ๋’€๋‹ค.

  • Screen ๋ชจ๋“œ(Alt+1) โ€” ๋‚ด ํ”„๋กœ์ ํŠธ์—์„œ ์ด ์š”์†Œ๋ฅผ ์‹ค์ œ๋กœ ์“ด ์œ„์น˜. ๋””์ž์ธ ๊ณ ์น  ๋•Œ ์›ํ•˜๋Š” ๊ทธ ์œ„์น˜.
  • Implementation ๋ชจ๋“œ(Alt+2) โ€” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ •์˜๋œ ๊ตฌํ˜„ ์œ„์น˜. (๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€๊นŒ์ง€)

์ •๋ณด๋ฅผ ์ฐพ์œผ๋ฉด DevTools ์ธ์ŠคํŽ™ํ„ฐ์ฒ˜๋Ÿผ ํŒŒ๋ž€ ์˜ค๋ฒ„๋ ˆ์ด๋กœ ์š”์†Œ๋ฅผ ํ•˜์ด๋ผ์ดํŠธํ•˜๊ณ , ํŒŒ์ผ๋ช…๊ณผ ์ค„ ๋ฒˆํ˜ธ๋ฅผ ๋ผ๋ฒจ๋กœ ๋„์šด๋‹ค. ์šฐํด๋ฆญํ•˜๋ฉด ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๊ฐ€ ๋– ์„œ ๊ธฐ๋ณธ์œผ๋กœ๋Š” ๊ฒฝ๋กœ ๋ณต์‚ฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ณ , openInEditor ์˜ต์…˜(๊ธฐ๋ณธ๊ฐ’ false)์„ ์ผœ๋ฉด ์—๋””ํ„ฐ์—์„œ ์—ด๊ธฐ ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋œ๋‹ค.

"์—๋””ํ„ฐ์—์„œ ์—ด๊ธฐ"๋Š” ๊ฐœ๋ฐœ ์„œ๋ฒ„์— /__open-in-editor ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ•˜๋‚˜ ๋‘๊ณ , ํด๋ฆญ ์‹œ ๊ทธ ์ฃผ์†Œ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด ๋กœ์ปฌ ์—๋””ํ„ฐ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

const onOpen = () =>
  fetch(`/__open-in-editor?file=${encodeURIComponent(result.source)}`);

VS Code, Cursor, WebStorm, Vim ๋“ฑ ์›ฌ๋งŒํ•œ ์—๋””ํ„ฐ์˜ CLI ๋ช…๋ น์„ ๋งคํ•‘ํ•ด๋’€๋‹ค.

ํ•œ ๋ฒˆ ๋งŒ๋“ค๊ณ  ๋‹ค์„ฏ ๊ฐœ ๋ฒˆ๋“ค๋Ÿฌ ์ง€์›ํ•˜๊ธฐ

์ฒ˜์Œ์—” Vite๋งŒ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, Webpack(Next.js), Rollup, esbuild, Rspack๊นŒ์ง€ ์“ฐ๊ณ  ์‹ถ์–ด์กŒ๋‹ค. ์ด๊ฑธ ๊ฐ๊ฐ ๊ตฌํ˜„ํ•˜๋ฉด ์ง€์˜ฅ์ด๋‹ค. ๊ทธ๋ž˜์„œ unplugin ์œผ๋กœ ํ†ตํ•ฉํ–ˆ๋‹ค. ๋ณ€ํ™˜ ๋กœ์ง ํ•˜๋‚˜๋งŒ ์ž˜ ๋งŒ๋“ค์–ด๋‘๋ฉด ์—ฌ๋Ÿฌ ๋ฒˆ๋“ค๋Ÿฌ์šฉ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํ•œ ๋ฒˆ์— ๋‚˜์˜จ๋‹ค. ๋‹ค๋งŒ Vite๋งŒํผ์€ ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹คํ–‰ ์ˆœ์„œ ๋ฌธ์ œ ๋•Œ๋ฌธ์— unplugin ์–ด๋Œ‘ํ„ฐ ๋Œ€์‹  ๋„ค์ดํ‹ฐ๋ธŒ Vite ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ๋”ฐ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

export { vitePlugin, webpackPlugin, rollupPlugin, esbuildPlugin, rspackPlugin }
  from "./unplugin";

๋˜๋Œ์•„๋ณด๋ฉฐ โ€” ๋งŒ๋“ค๋ฉด์„œ ๋ฐฐ์šด ๊ฒƒ๋“ค

์ด ํ”„๋กœ์ ํŠธ์—์„œ ํฌ๊ฒŒ ์„ธ ๋ฒˆ ๊ฐˆ์•„์—Ž์—ˆ๋‹ค.

  • ํŒŒ์„œ ๊ต์ฒด (oxc-parser โ†’ acorn): ์ฒ˜์Œ์—” ๋น ๋ฅธ oxc-parser๋ฅผ ์ผ๋Š”๋ฐ, ๋„ค์ดํ‹ฐ๋ธŒ ๋ฐ”์ธ๋”ฉ ๋•Œ๋ฌธ์— ๋ฒˆ๋“ค๋งยท๋ฐฐํฌ๊ฐ€ ๊นŒ๋‹ค๋กœ์› ๋‹ค. acorn ๊ณ„์—ด(+ TS/JSX ํ”Œ๋Ÿฌ๊ทธ์ธ)๋กœ ๋ฐ”๊พธ๋‹ˆ ์ˆœ์ˆ˜ JS๋กœ ์™„์ „ํžˆ ๋ฒˆ๋“ค ๊ฐ€๋Šฅํ•ด์กŒ๊ณ , ์„ค์น˜๊ฐ€ ํ›จ์”ฌ ๊ฐ€๋ฒผ์›Œ์กŒ๋‹ค.
  • Babel ์˜์กด์„ฑ ์ œ๊ฑฐ: ์ดˆ๊ธฐ์—” Babel์— ๊ธฐ๋Œ”์ง€๋งŒ, ๊ฒฐ๊ตญ "๋นŒ๋“œ ํ”Œ๋Ÿฌ๊ทธ์ธ ํ•˜๋‚˜" ๋กœ ๋๋‚˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒŒ ๋ชฉํ‘œ์˜€๋‹ค. Babel๋„ React DevTools๋„ ๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ๋„ ํ•„์š” ์—†์ด, ํ”Œ๋Ÿฌ๊ทธ์ธ ํ•œ ์ค„์ด๋ฉด ๋˜๋„๋ก ์ •๋ฆฌํ–ˆ๋‹ค.
  • ๋ฌธ์ž์—ด ์กฐ์ž‘ ์ตœ์ ํ™” (slice โ†’ MagicString): ๋งค ์‚ฝ์ž…๋งˆ๋‹ค slice + ์—ฐ๊ฒฐ์„ ํ•˜๋‹ˆ ํŒŒ์ผ์ด ํฌ๊ณ  ์‚ฝ์ž…์ด ๋งŽ์„์ˆ˜๋ก O(nยทm)๋กœ ๋А๋ ค์กŒ๋‹ค. MagicString์œผ๋กœ ๋ฐ”๊ฟ” ์‚ฝ์ž…์€ ์ •๋ ฌ๋œ ์œ„์น˜์— ๊ธฐ๋ก๋งŒ ํ•ด๋‘๋Š” ์‚ฌ์‹ค์ƒ ์ƒ์ˆ˜ ๋น„์šฉ์ด ๋๊ณ (์ตœ์ข… ๋ฌธ์ž์—ด ์ƒ์„ฑ์€ ๋งˆ์ง€๋ง‰ 1ํšŒ), ์†Œ์Šค๋งต ์ƒ์„ฑ๊นŒ์ง€ ๋ค์œผ๋กœ ์–ป์—ˆ๋‹ค.

๊ฐ€์žฅ ํฌ๊ฒŒ ๋‚จ์€ ๊ตํ›ˆ์€, "React ๋‚ด๋ถ€ ๊ตฌํ˜„์— ๊ธฐ๋Œ€์ง€ ๋ง๊ณ  ๋‚ด๊ฐ€ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์ž" ์˜€๋‹ค. _debugSource๊ฐ€ ์‚ฌ๋ผ์กŒ์„ ๋•Œ ๋ง‰๋ง‰ํ–ˆ์ง€๋งŒ, ์˜คํžˆ๋ ค ๋ฒ„์ „์— ๋…๋ฆฝ์ ์ธ ๋” ํŠผํŠผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ด์–ด์กŒ๋‹ค.

์จ๋ณด๊ธฐ

npm i -D react-code-locator
// vite.config.ts
import react from "@vitejs/plugin-react";
import { vitePlugin } from "react-code-locator";

export default defineConfig({
  plugins: [react(), vitePlugin()],
});

์ด์ œ ๊ฐœ๋ฐœ ์ค‘์— Shift๋ฅผ ๋ˆ„๋ฅธ ์ฑ„ ์š”์†Œ์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ํ•˜์ด๋ผ์ดํŠธ๋˜๊ณ , ์šฐํด๋ฆญํ•˜๋ฉด ๊ฒฝ๋กœ๋ฅผ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค(openInEditor ์˜ต์…˜์„ ์ผœ๋ฉด ์—๋””ํ„ฐ๋กœ ๋ฐ”๋กœ ์ ํ”„). ์‚ฌ์†Œํ•œ ๋ถˆํŽธ ํ•˜๋‚˜๊ฐ€, ๋งค์ผ ์“ฐ๋Š” ๋„๊ตฌ๊ฐ€ ๋๋‹ค.

โ† ๋ชฉ๋ก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ
ยฉ 2026 ยท Groot's Tech Blog. Built with Gatsby ๐ŸŒฑ