[TECH-QA] ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ˜ธ์ด์ŠคํŒ…๊ณผ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ˜ธ์ด์ŠคํŒ…(hoisting)์€ ์ฝ”๋“œ๋ฅผ ํ•œ ์ค„ ํ•œ ์ค„ ์‹คํ–‰ํ•˜๊ธฐ์— ์•ž์„œ, ์„ ์–ธ๋œ ๋ณ€์ˆ˜, ํ•จ์ˆ˜, ํด๋ž˜์Šค ๋“ฑ์˜ ์„ ์–ธ๋ฌธ์„ ์ฝ”๋“œ์˜ ์ตœ์ƒ๋‹จ์œผ๋กœ ๋Œ์–ด์˜ฌ๋ ค ๋Ÿฐํƒ€์ž„ ์ด์ „์— ํ•œ ๋ฒˆ ์‹คํ–‰ํ•ด ๋ฉ”๋ชจ๋ฆฌ์— ๋ฏธ๋ฆฌ ์˜ฌ๋ ค๋†“๋Š” ๊ณผ์ •์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution Context)๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜ ์„ ์–ธ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์—์„œ ๋น„๋กฏ๋ฉ๋‹ˆ๋‹ค. ํ˜ธ์ด์ŠคํŒ… ๋•๋ถ„์— ๊ฐœ๋ฐœ์ž๋Š” ์ฝ”๋“œ์˜ ๋ฌผ๋ฆฌ์  ์œ„์น˜์™€ ์ƒ๊ด€์—†์ด ๋ณ€์ˆ˜๋‚˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๋กœ ์ธํ•ด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ์–ด ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ๋ณ€์ˆ˜ ํ˜ธ์ด์ŠคํŒ…

var ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ํ˜ธ์ด์ŠคํŒ… ๊ณผ์ •์—์„œ ๋ณ€์ˆ˜ ์„ ์–ธ๊ณผ ๋™์‹œ์— undefined๋กœ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์ค„ ์ด์ „์— ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋”๋ผ๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  undefined ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” var๊ฐ€ ์„ ์–ธ(Declaration)๊ณผ ์ดˆ๊ธฐํ™”(Initialization)๊ฐ€ ๋™์‹œ์— ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด, let๊ณผ const ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ํ˜ธ์ด์ŠคํŒ…์ด ๋ฐœ์ƒํ•˜๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ์„ ์–ธ(Declaration)๊ณผ ์ดˆ๊ธฐํ™”(Initialization)๊ฐ€ ๋™์‹œ์— ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. let๊ณผ const๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์‹คํ–‰ ์ปจํ…์ŠคํŠธ ๋‚ด์˜ ์„ ์–ธ์  ํ™˜๊ฒฝ ๋ ˆ์ฝ”๋“œ(Declarative Environment Record)์— ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ ์ƒ์„ฑ ๋‹จ๊ณ„์—์„œ ๋ณ€์ˆ˜๋Š” ์„ ์–ธ ๋˜์—ˆ์œผ๋‚˜, ์ดˆ๊ธฐํ™”๋Š” ์‹ค์ œ ์ฝ”๋“œ ์‹คํ–‰ ์‹œ์ (๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์‹œ์ )์—์„œ ์ดˆ๊ธฐํ™”๊ฐ€ ์ด๋ฃจ์–ด ์ง‘๋‹ˆ๋‹ค.

๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์‹œ์ ๋ถ€ํ„ฐ ์‹ค์ œ ์ดˆ๊ธฐํ™”๊ฐ€ ์ด๋ฃจ์–ด์งˆ ๋•Œ๊นŒ์ง€์˜ ๊ตฌ๊ฐ„์„ TDZ(Temporary Dead Zone, ์ž„์‹œ ์‚ฌ๊ฐ์ง€๋Œ€)๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด ๊ตฌ๊ฐ„์—์„œ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„์ง ํ• ๋‹น๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ReferenceError๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ํ•จ์ˆ˜ ์„ ์–ธ๊ณผ ํ˜ธ์ด์ŠคํŒ…

ํ•จ์ˆ˜ ์„ ์–ธ(Function Declaration)์˜ ๊ฒฝ์šฐ, ๋ณ€์ˆ˜์™€๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ด์ŠคํŒ…๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์„ ์–ธ์€ ์„ ์–ธ๊ณผ ์ดˆ๊ธฐํ™”, ๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜ ๋ณธ๋ฌธ ์ „์ฒด๊ฐ€ ํ•จ๊ป˜ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์ค„ ์ด์ „์— ํ˜ธ์ถœํ•˜๋”๋ผ๋„ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ•จ์ˆ˜ ์„ ์–ธ์ด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ ์ƒ์„ฑ ๋‹จ๊ณ„์—์„œ ์™„์ „ํžˆ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹จ, ํ•จ์ˆ˜ ํ‘œํ˜„์‹(Function Expression)์œผ๋กœ ์ž‘์„ฑ๋œ ๊ฒฝ์šฐ์—๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
ํ•จ์ˆ˜ ํ‘œํ˜„์‹(Function Expression)์€ ๋ณ€์ˆ˜์— ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹์ด๋ฏ€๋กœ, ์‚ฌ์šฉ๋œ ๋ณ€์ˆ˜ ํ‚ค์›Œ๋“œ(var, let, const)์— ๋”ฐ๋ผ ๋™์ž‘์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
bar(); // TypeError: bar is not a function

var bar = function() {
  console.log("This is bar");
};
์œ„ ์˜ˆ์‹œ์—์„œ bar๋Š” var๋กœ ์„ ์–ธ๋˜์—ˆ์œผ๋ฏ€๋กœ undefined๋กœ ์ดˆ๊ธฐํ™”๋œ ์ƒํƒœ์—์„œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์‹œ๋„๋˜์–ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์‚ฌ์šฉ๋œ ๋ณ€์ˆ˜ ์„ ์–ธ ํ‚ค์›Œ๋“œ(var, let, const)์˜ ์ดˆ๊ธฐํ™” ๊ทœ์น™์„ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ์˜ ์ข…๋ฅ˜๋Š” ํ‚ค์›Œ๋“œ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution Context)

์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution Context)๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ์„ ์ •์˜ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋‚ด๋ถ€์ ์ธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์ฝ”๋“œ ์‹คํ–‰์„ ์ค€๋น„ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ, ํ•ด๋‹น ์ฝ”๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€์ˆ˜, ํ•จ์ˆ˜, ์Šค์ฝ”ํ”„, this ๋ฐ”์ธ๋”ฉ ๋“ฑ์„ ์ถ”์ ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ์ƒ์„ฑ ๋‹จ๊ณ„(Creation Phase)

์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution Context) ์ƒ์„ฑ ๋‹จ๊ณ„(Creation Phase)์—์„œ๋Š” ์ฝ”๋“œ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋ณ€์ˆ˜, ํ•จ์ˆ˜ ์„ ์–ธ, ํ•จ์ˆ˜์˜ ์ธ์ž ๋“ฑ์ด ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ES6 ์ดํ›„๋กœ๋Š” ํ™˜๊ฒฝ ๋ ˆ์ฝ”๋“œ(Environment Record)๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ ํ™•์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • var๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” undefined๋กœ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.
  • let๊ณผ const๋Š” ์„ ์–ธ๋งŒ ๋˜๊ณ  ์ดˆ๊ธฐํ™”๋Š” ๋‚˜์ค‘์— ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค(TDZ).
  • ํ•จ์ˆ˜ ์„ ์–ธ์€ ์ „์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ๊ฐ€ ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.
ํ˜„์žฌ ์ปจํ…์ŠคํŠธ์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์™ธ๋ถ€ ๋ณ€์ˆ˜๋“ค์„ ์Šค์ฝ”ํ”„ ์ฒด์ธ(Scope Chain)์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜์—์„œ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์ฝ”๋“œ์—์„œ this๊ฐ€ ๊ฐ€๋ฆฌํ‚ฌ ๊ฐ์ฒด๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹(์˜ˆ: ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ, ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋“ฑ)์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๐Ÿ“ ์‹คํ–‰ ๋‹จ๊ณ„(Execution Phase)

์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Execution Context) ์‹คํ–‰ ๋‹จ๊ณ„(Execution Phase)์—์„œ๋Š” ์ƒ์„ฑ ๋‹จ๊ณ„๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ฝ”๋“œ๊ฐ€ ํ•œ ์ค„์”ฉ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ๋ณ€์ˆ˜์— ๊ฐ’์ด ํ• ๋‹น(Assignment)๋˜๊ณ , ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ, ์‹ค์ œ ๋กœ์ง์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ์ปจํ…์ŠคํŠธ์˜ ์ข…๋ฅ˜

  • ์ „์—ญ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Global Execution Context): ์ „์—ญ ์Šค์ฝ”ํ”„์—์„œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์œ„ํ•œ ์ปจํ…์ŠคํŠธ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋  ๋•Œ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ๋˜๋ฉฐ, ์ „์—ญ ๊ฐ์ฒด(๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” window, Node.js์—์„œ๋Š” global)์™€ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
  • ํ•จ์ˆ˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Function Execution Context): ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ์€ ๋…๋ฆฝ์ ์ธ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋ฉด ํ•ด๋‹น ์ปจํ…์ŠคํŠธ๋Š” ์Šคํƒ์—์„œ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.
  • Eval ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Eval Execution Context): eval() ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค(๋“œ๋ฌผ๊ฒŒ ์‚ฌ์šฉ๋จ).

๊ด€๋ จ ํ‚ค์›Œ๋“œ

์ปจํ…์ŠคํŠธ(this)๋ฅผ ์ œ์–ดํ•˜๋Š” ํ•จ์ˆ˜ call()

์ปจํ…์ŠคํŠธ(this)๋ฅผ ์ œ์–ดํ•˜๋Š” ํ•จ์ˆ˜ apply()

์ปจํ…์ŠคํŠธ(this)๋ฅผ ์ œ์–ดํ•˜๋Š” ํ•จ์ˆ˜ bind()