๐ŸŽฏ 03. this ๋ฐ”์ธ๋”ฉ โ€” '๋‚˜๋Š” ๋ˆ„๊ตฌ์ธ๊ฐ€'๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” 5๊ฐ€์ง€ ๊ทœ์น™

2026๋…„ 3์›” 8์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

JS์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ํ—ท๊ฐˆ๋ฆฌ๋Š” this์˜ 5๊ฐ€์ง€ ๊ฒฐ์ • ๊ทœ์น™, ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์™€ ์ผ๋ฐ˜ ํ•จ์ˆ˜์˜ ๊ฒฐ์ •์  ์ฐจ์ด, call/apply/bind ์™„๋ฒฝ ์ •๋ณต.

๐ŸŽฏ ์ด ์„น์…˜์„ ์ฝ๊ณ  ๋‚˜๋ฉด:

  • this๊ฐ€ ํ˜ธ์ถœ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” 5๊ฐ€์ง€ ๊ทœ์น™์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๊ฐ€ this๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ์™€ ํ™œ์šฉ๋ฒ•์„ ์•ˆ๋‹ค.
  • call, apply, bind๋กœ this๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๊ณ ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‹ค๋ฌด์— ์ ์šฉํ•œ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 20๋ถ„(์ „์ฒด) / ํ•ต์‹ฌ ํŒŒํŠธ๋งŒ: 12๋ถ„

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
[this์˜ ์ •์ฒด] โ†’ [5๊ฐ€์ง€ ๊ฒฐ์ • ๊ทœ์น™] โ†’ [ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ ํŠน์ˆ˜์„ฑ] โ†’ [์‹ค๋ฌด ์ ์šฉ]

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • "this๊ฐ€ undefined์ธ๋ฐ์š”?" ์—๋Ÿฌ๋ฅผ ์ฆ‰์‹œ ์›์ธ ํŒŒ์•…ํ•˜๊ณ  ์ˆ˜์ •ํ•œ๋‹ค.
  • ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ์“ธ ๋•Œ this ์†์‹ค ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.
  • call, apply, bind๋ฅผ ๊ฐ๊ฐ ์–ธ์ œ ์“ฐ๋Š”์ง€ ๊ตฌ๋ถ„ํ•œ๋‹ค.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

๐Ÿฃ ์˜์ฒ : "์˜ํ˜ธ ๋‹˜, ์ € ๋“œ๋””์–ด ํฐ ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚ฌ์–ด์š”. ์œ ์ € ํ”„๋กœํ•„ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ๋„˜๊ฒผ๋Š”๋ฐ... this.userName์ด undefined์˜ˆ์š”. ๋ถ„๋ช… ๋ฉ”์„œ๋“œ ์•ˆ์— this.userName์ด ์žˆ๋Š”๋ฐ, ๋ฒ„ํŠผ ํด๋ฆญํ•˜๋ฉด Cannot read properties of undefined๊ฐ€ ๋– ์š”. this๊ฐ€ ๋Œ€์ฒด ๋ญ˜ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฑด์ง€ ๋ชจ๋ฅด๊ฒ ์–ด์š”. ์ฝ˜์†”์— this ์ฐ์–ด๋ดค๋”๋‹ˆ undefined๊ฐ€ ๋‚˜์™”์–ด์š”. ์ด๊ฑฐ React ๋ฒ„๊ทธ์ธ๊ฐ€์š”?"

๐Ÿฆ ์˜ํ˜ธ: "React ๋ฒ„๊ทธ ์•„๋‹ˆ์•ผ. this๋Š” ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœ๋๋А๋ƒ ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๊ฑฐ๋“ . ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋„˜๊ธฐ๋ฉด, ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹Œ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ์— ์˜ํ•ด ํ˜ธ์ถœ ๋ผ. ๊ทธ ์ˆœ๊ฐ„ this๋Š” ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹ˆ์•ผ. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ์„ ์–ธํ•˜๊ฑฐ๋‚˜ bind๋กœ ๊ณ ์ •ํ•˜๋ฉด ํ•ด๊ฒฐ๋ผ. ์˜ค๋Š˜ this 5๊ฐ€์ง€ ๊ทœ์น™ ๋ฐฐ์šฐ๋ฉด ์ด ์—๋Ÿฌ๋Š” ์˜์›ํžˆ ๋‹นํ•˜์ง€ ์•Š์„ ๊ฑฐ์•ผ."


๐Ÿค” 1. ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€?

์˜์ฒ ์ด๊ฐ€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์•ˆ์—์„œ this.nickname ์„ ์ถœ๋ ฅํ•˜๋ ค๋‹ค undefined ๊ฐ€ ํŠ€์–ด๋‚˜์™”์„ ๋•Œ, ์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด ๋งํ–ˆ๋‹ค: "JS์˜ this ๋Š” Java์ฒ˜๋Ÿผ 'ํ˜„์žฌ ์ธ์Šคํ„ด์Šค'๊ฐ€ ์•„๋‹ˆ์•ผ. ํ˜ธ์ถœ ๋ฐฉ์‹์ด ๊ฒฐ์ •ํ•ด." this๋Š” JS์—์„œ ๊ฐ€์žฅ ์˜คํ•ด๊ฐ€ ๋งŽ์€ ํ‚ค์›Œ๋“œ ๋‹ค. ๋‹ค๋ฅธ ์–ธ์–ด(Java, C#)์—์„œ๋Š” this๊ฐ€ ํ•ญ์ƒ ํ˜„์žฌ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค์ง€๋งŒ, JS์˜ this๋Š” ํ˜ธ์ถœ ๋ฐฉ์‹ ์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.

JS์˜ this๋Š” ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์œ„์น˜๊ฐ€ ์•„๋‹ˆ๋ผ, ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ ๋ฐฉ์‹์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค.

์ด ์‚ฌ์‹ค ํ•˜๋‚˜๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ˆ˜๋งŽ์€ "์™œ this๊ฐ€ ์ด์ƒํ•ด?" ๋ฒ„๊ทธ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ“œ 2. this ๊ฒฐ์ • ๊ทœ์น™ 5๊ฐ€์ง€

๊ทœ์น™ 1: ์ „์—ญ ์ปจํ…์ŠคํŠธ

์–ด๋–ค ํ•จ์ˆ˜์—๋„ ์†ํ•˜์ง€ ์•Š์€ ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ, ์ฆ‰ ์ „์—ญ ๊ณต๊ฐ„์—์„œ this๋ฅผ ๋ถ€๋ฅด๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๊ทธ ์ •์ฒด๊ฐ€ ์กฐ๊ธˆ์”ฉ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

// ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ
console.log(this); // window ๊ฐ์ฒด
 
// strict mode ('use strict')
"use strict";
function showThis() {
  console.log(this); // undefined (strict mode์—์„œ๋Š” ์ „์—ญ ๋ฐ”์ธ๋”ฉ ์—†์Œ)
}
showThis();
 
// Node.js ํ™˜๊ฒฝ
console.log(this); // {} (๋นˆ module.exports ๊ฐ์ฒด)

๊ทœ์น™ 2: ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

๊ฐ€์žฅ ํ”ํ•˜๊ฒŒ ์ ‘ํ•˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ์ด๋ฆ„ํ‘œ๋ฅผ ๋‹ฌ๊ณ  ๋ฉ”์„œ๋“œ๋กœ ํ˜ธ์ถœ๋  ๋•Œ, this๋Š” ์ž๊ธฐ๋ฅผ ๋ถˆ๋Ÿฌ์ค€ ๊ทธ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์œ ์ € ๊ฐ์ฒด๋กœ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ โ€” ์œ ์ € ๊ฐ์ฒด
 
const user = {
  name: "์˜์ฒ ",
  role: "junior",
  greet() {
    console.log(`์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ${this.name}์ด์—์š”!`); // this โ†’ user ๊ฐ์ฒด
  },
  getRole: function () {
    return this.role; // this โ†’ user ๊ฐ์ฒด
  },
};
 
user.greet();     // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ์˜์ฒ ์ด์—์š”!"
user.getRole();   // "junior"
 
// โŒ ๋ฉ”์„œ๋“œ๋ฅผ ๋ณ€์ˆ˜์— ๊บผ๋‚ด๋Š” ์ˆœ๊ฐ„ this ์†์‹ค
const greetFn = user.greet;
greetFn(); // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” undefined์ด์—์š”!" โ€” this๊ฐ€ ์ „์—ญ(๋˜๋Š” undefined)์œผ๋กœ ๋ฐ”๋€œ!

ํ•ต์‹ฌ: ๊ฐ์ฒด.๋ฉ”์„œ๋“œ() ํ˜•ํƒœ๋กœ ํ˜ธ์ถœํ•  ๋•Œ๋งŒ this๊ฐ€ ๊ทธ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ๋ฉ”์„œ๋“œ๋ฅผ ๋ฝ‘์•„์„œ ๋”ฐ๋กœ ํ˜ธ์ถœ ํ•˜๋Š” ์ˆœ๊ฐ„, this๋Š” ์žƒ์–ด๋ฒ„๋ฆฐ๋‹ค.

๊ทœ์น™ 3: ์ƒ์„ฑ์ž ํ•จ์ˆ˜ (new)

new ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ˆœ๊ฐ„, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋‚ด๋ถ€์— ์ƒˆ๋กœ์šด ๋นˆ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  this๋ฅผ ๊ทธ๊ณณ์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

function User(name, role) {
  // new๋กœ ํ˜ธ์ถœ ์‹œ, this = {} (์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด)
  this.name = name;
  this.role = role;
  // ์•”๋ฌต์ ์œผ๋กœ return this;
}
 
const yc = new User("์˜์ฒ ", "junior");
const yh = new User("์˜ํ˜ธ", "lead");
 
console.log(yc.name); // "์˜์ฒ "
console.log(yh.role); // "lead"
 
// new ์—†์ด ํ˜ธ์ถœํ•˜๋ฉด?
const broken = User("์˜์ฒ ", "junior"); // this = window (๋ธŒ๋ผ์šฐ์ €) โ†’ ์ „์—ญ ์˜ค์—ผ!
console.log(broken); // undefined (return ์—†์Œ)

๊ทœ์น™ 4: ๋ช…์‹œ์  ๋ฐ”์ธ๋”ฉ (call/apply/bind)

์—”์ง„์—๊ฒŒ "์˜ค๋Š˜ this๋Š” ์ด ์นœ๊ตฌ์•ผ!"๋ผ๊ณ  ์ง์ ‘ ์ฃผ์ž…ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•๋“ค์ž…๋‹ˆ๋‹ค.

function introduce(greeting, punctuation) {
  console.log(`${greeting}, ์ €๋Š” ${this.name}์ž…๋‹ˆ๋‹ค${punctuation}`);
}
 
const yc = { name: "์˜์ฒ " };
const yh = { name: "์˜ํ˜ธ" };
 
// call โ€” ์ธ์ž๋ฅผ ์ฝค๋งˆ๋กœ ๋‚˜์—ด, ์ฆ‰์‹œ ์‹คํ–‰
introduce.call(yc, "์•ˆ๋…•ํ•˜์„ธ์š”", "!"); // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ์˜์ฒ ์ž…๋‹ˆ๋‹ค!"
introduce.call(yh, "๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค", "~"); // "๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค, ์ €๋Š” ์˜ํ˜ธ์ž…๋‹ˆ๋‹ค~"
 
// apply โ€” ์ธ์ž๋ฅผ ๋ฐฐ์—ด๋กœ, ์ฆ‰์‹œ ์‹คํ–‰
introduce.apply(yc, ["์•ˆ๋…•ํ•˜์„ธ์š”", "!"]); // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ์˜์ฒ ์ž…๋‹ˆ๋‹ค!"
 
// bind โ€” this๋ฅผ ๊ณ ์ •ํ•œ ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ (์ฆ‰์‹œ ์‹คํ–‰ ์•ˆ ํ•จ)
const introduceyc = introduce.bind(yc, "์•ˆ๋…•ํ•˜์„ธ์š”");
introduceyc("!"); // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ์˜์ฒ ์ž…๋‹ˆ๋‹ค!"
introduceyc("~"); // "์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” ์˜์ฒ ์ž…๋‹ˆ๋‹ค~"
// yc๋กœ this๊ฐ€ ์˜๊ตฌ ๊ณ ์ •๋จ
๋ฉ”์„œ๋“œํ˜ธ์ถœ ๋ฐฉ์‹์ธ์ž ์ „๋‹ฌ์‚ฌ์šฉ ์‹œ์ 
call์ฆ‰์‹œ ์‹คํ–‰๋‚˜์—ด์ง€๊ธˆ ๋‹น์žฅ ์‹คํ–‰ํ•  ๋•Œ
apply์ฆ‰์‹œ ์‹คํ–‰๋ฐฐ์—ด์ธ์ž๊ฐ€ ๋ฐฐ์—ด๋กœ ์žˆ์„ ๋•Œ
bindํ•จ์ˆ˜ ๋ฐ˜ํ™˜๋‚˜์—ด (์„ ํƒ)๋‚˜์ค‘์— ์‹คํ–‰ํ•  ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•  ๋•Œ

๊ทœ์น™ 5: ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ โ€” this๊ฐ€ ์—†๋‹ค

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ์ด๊ธฐ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ž์‹ ๋งŒ์˜ this๋ฅผ ๊ณ ์ง‘ํ•˜์ง€ ์•Š๊ณ , **์ž์‹ ์ด ํƒœ์–ด๋‚œ ๊ณณ์˜ this**๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฌผ๋ ค๋ฐ›์•„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด "๋ ‰์‹œ์ปฌ this๋ฅผ ์ดํ•ดํ•˜๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง„๋‹ค"๊ณ  ํ•œ ์ด์œ ๊ฐ€ ๋ฐ”๋กœ ์ด๊ฒƒ์ž…๋‹ˆ๋‹ค.

const user = {
  name: "์˜์ฒ ",
  friends: ["์˜ํ˜ธ", "์˜์ˆ˜", "์˜์ˆ™"],
 
  // โŒ ์ผ๋ฐ˜ ํ•จ์ˆ˜ โ€” forEach ์ฝœ๋ฐฑ์—์„œ this ์†์‹ค
  listFriendsWrong() {
    this.friends.forEach(function (friend) {
      // ์ด ์ฝœ๋ฐฑ์€ ๋…๋ฆฝ์ ์œผ๋กœ ํ˜ธ์ถœ๋จ โ†’ this๋Š” undefined (strict mode)
      console.log(`${this.name}์˜ ์นœ๊ตฌ: ${friend}`); // TypeError!
    });
  },
 
  // โœ… ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ โ€” ์ƒ์œ„ ์Šค์ฝ”ํ”„(listFriendsRight ๋ฉ”์„œ๋“œ)์˜ this๋ฅผ ๋ฌผ๋ ค๋ฐ›์Œ
  listFriendsRight() {
    this.friends.forEach((friend) => {
      // ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ โ†’ this = user ๊ฐ์ฒด (์ƒ์œ„ this ๊ทธ๋Œ€๋กœ)
      console.log(`${this.name}์˜ ์นœ๊ตฌ: ${friend}`); // โœ…
    });
  },
};
 
user.listFriendsWrong(); // TypeError
user.listFriendsRight(); // "์˜์ฒ ์˜ ์นœ๊ตฌ: ์˜ํ˜ธ", "์˜์ฒ ์˜ ์นœ๊ตฌ: ์˜์ˆ˜", ...

โšก 3. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ vs ์ผ๋ฐ˜ ํ•จ์ˆ˜ this ๋น„๊ต

์˜คํ”„๋‹์—์„œ ์˜์ฒ ์ด๊ฐ€ ๊ฒช์€ ๋ฒ„๊ทธ์˜ ์ •์ฒด๊ฐ€ ๋ฐ”๋กœ ์ด๊ฒƒ์ด๋‹ค. ๊ฐ™์€ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ์—์„œ setTimeout ์„ ํ˜ธ์ถœํ•  ๋•Œ, ์ผ๋ฐ˜ ํ•จ์ˆ˜ ์ฝœ๋ฐฑ์€ this ๋ฅผ ์žƒ์–ด๋ฒ„๋ฆฌ์ง€๋งŒ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ์„ ์–ธ๋œ ์‹œ์ ์˜ this ๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•œ๋‹ค. ์ด ์ฐจ์ด ํ•˜๋‚˜๊ฐ€ ์ˆ˜๋งŽ์€ ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ์˜ ์›์ธ์ด ๋œ๋‹ค.

// ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ โ€” ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ํƒ€์ด๋จธ
 
const notificationService = {
  message: "์ƒˆ ๊ฒŒ์‹œ๊ธ€์ด ์žˆ์Šต๋‹ˆ๋‹ค!",
  delay: 1000,
 
  // โŒ ์ผ๋ฐ˜ ํ•จ์ˆ˜ โ€” this ์†์‹ค
  startWrong() {
    setTimeout(function () {
      console.log(this.message); // undefined โ€” setTimeout์ด ์ „์—ญ์—์„œ ํ˜ธ์ถœ
    }, this.delay);
  },
 
  // โœ… ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ โ€” ๋ ‰์‹œ์ปฌ this ์œ ์ง€
  startRight() {
    setTimeout(() => {
      console.log(this.message); // "์ƒˆ ๊ฒŒ์‹œ๊ธ€์ด ์žˆ์Šต๋‹ˆ๋‹ค!" โ€” notificationService์˜ this ์œ ์ง€
    }, this.delay);
  },
 
  // โœ… bind โ€” ๋ช…์‹œ์  ๊ณ ์ •
  startWithBind() {
    setTimeout(
      function () {
        console.log(this.message);
      }.bind(this),
      this.delay
    );
  },
};
 
notificationService.startWrong();    // undefined
notificationService.startRight();    // "์ƒˆ ๊ฒŒ์‹œ๊ธ€์ด ์žˆ์Šต๋‹ˆ๋‹ค!"
notificationService.startWithBind(); // "์ƒˆ ๊ฒŒ์‹œ๊ธ€์ด ์žˆ์Šต๋‹ˆ๋‹ค!"

โš ๏ธ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๊ฐ€ ์ ์ ˆํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ:

  • ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋กœ ์ง์ ‘ ์ •์˜ํ•  ๋•Œ (๊ฐ์ฒด๋ฅผ this๋กœ ์žก์ง€ ๋ชปํ•จ)
  • prototype์— ๊ณตํ†ต ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ
  • ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•  ๋•Œ (new ์‚ฌ์šฉ ๋ถˆ๊ฐ€)

์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด ์‹ค์ˆ˜ํ•˜๊ธฐ ์‰ฌ์šด ํฌ์ธํŠธ๋ผ๋ฉฐ ์ฐ์–ด์ค€ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ๋ฉ”์„œ๋“œ๋กœ ์ผ์„ ๋•Œ ์–ด๋–ค ์ผ์ด ๋ฒŒ์–ด์ง€๋Š”์ง€ ๋ณด์„ธ์š”.

// โŒ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ๊ฐ์ฒด ๋ฉ”์„œ๋“œ๋กœ โ€” this ์†์‹ค
const post = {
  title: "ํด๋กœ์ € ์™„์ „์ •๋ณต",
  getTitle: () => {
    return this.title; // this โ†’ ์ „์—ญ (undefined)
  },
};
post.getTitle(); // undefined โ† ์˜๋„์™€ ๋‹ค๋ฆ„!
 
// โœ… ๊ฐ์ฒด ๋ฉ”์„œ๋“œ๋Š” ์ผ๋ฐ˜ ํ•จ์ˆ˜ (๋‹จ์ถ• ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ๊ถŒ์žฅ)
const post2 = {
  title: "ํด๋กœ์ € ์™„์ „์ •๋ณต",
  getTitle() {
    return this.title; // this โ†’ post2 ๊ฐ์ฒด
  },
};
post2.getTitle(); // "ํด๋กœ์ € ์™„์ „์ •๋ณต" โœ…

๐Ÿ—๏ธ 4. ์‹ค๋ฌด ํŒจํ„ด

์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜์ด ์˜์ฒ ์ด PR์— ๋‚จ๊ธด ๋ฆฌ๋ทฐ์—์„œ ์ œ์•ˆํ•œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด๋‹ค. ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋„˜๊ธธ ๋•Œ this ๊ฐ€ ์†์‹ค๋˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํŒจํ„ด์„ ๋น„๊ตํ•œ๋‹ค. ์ƒ์„ฑ์ž์—์„œ bind ํ•˜๋Š” ๋ฐฉ๋ฒ• ๊ณผ ํด๋ž˜์Šค ํ•„๋“œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ˜„๋Œ€์  ๋ฐฉ๋ฒ• ์ค‘, ํŒ€ ์ปจ๋ฒค์…˜์— ๋งž๋Š” ๋ฐฉ์‹์„ ์ผ๊ด€๋˜๊ฒŒ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

// ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ โ€” ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ this ๊ณ ์ •
 
class CommentForm {
  constructor(postId) {
    this.postId = postId;
    this.content = "";
 
    // ๋ฐฉ๋ฒ• 1: bind๋กœ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ this ๊ณ ์ •
    this.handleSubmit = this.handleSubmit.bind(this);
    document.getElementById("submit-btn").addEventListener("click", this.handleSubmit);
  }
 
  handleSubmit(event) {
    event.preventDefault();
    console.log(`๊ฒŒ์‹œ๊ธ€ ${this.postId}์— ๋Œ“๊ธ€ ์ „์†ก: ${this.content}`);
    // bind ์—†์œผ๋ฉด this.postId โ†’ undefined
  }
}
 
// ๋ฐฉ๋ฒ• 2 (๋” ํ˜„๋Œ€์ ): ํด๋ž˜์Šค ํ•„๋“œ + ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ์ž๋™ ๋ฐ”์ธ๋”ฉ
class CommentFormModern {
  constructor(postId) {
    this.postId = postId;
    this.content = "";
  }
 
  // ํด๋ž˜์Šค ํ•„๋“œ๋กœ ์„ ์–ธ๋œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ โ†’ this๊ฐ€ ์ธ์Šคํ„ด์Šค๋กœ ์ž๋™ ๊ณ ์ •
  handleSubmit = (event) => {
    event.preventDefault();
    console.log(`๊ฒŒ์‹œ๊ธ€ ${this.postId}์— ๋Œ“๊ธ€ ์ „์†ก: ${this.content}`);
  };
}
 
// React์—์„œ์˜ ๊ด€์šฉ์  ํŒจํ„ด
// function Component() {
//   const handleClick = () => { ... }; // ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ this ๊ฑฑ์ • ์—†์Œ
//   return <button onClick={handleClick}>ํด๋ฆญ</button>;
// }

๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. ์•„๋ž˜ ์ฝ”๋“œ์—์„œ ๊ฐ console.log์˜ ์ถœ๋ ฅ๊ฐ’์„ ์˜ˆ์ธกํ•˜๋ผ.

const obj = {
  value: 42,
  getValue() {
    return this.value;
  },
  getValueArrow: () => {
    return this.value;
  },
};
 
console.log(obj.getValue());      // ?
console.log(obj.getValueArrow()); // ?
 
const extracted = obj.getValue;
console.log(extracted());         // ?

โœ… ์ •๋‹ต: 42, undefined, undefined

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • obj.getValue(): ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ โ†’ this = obj โ†’ obj.value = 42 โœ…
  • obj.getValueArrow(): ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ์„ ์–ธ๋œ ์œ„์น˜(์ „์—ญ)์˜ this๋ฅผ ์‚ฌ์šฉ โ†’ this = window/undefined โ†’ undefined
  • extracted(): ๋ฉ”์„œ๋“œ๋ฅผ ๋ฝ‘์•„ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ โ†’ this = undefined (strict mode) ๋˜๋Š” window โ†’ undefined
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "์ (.)์˜ ์™ผ์ชฝ์ด this๋‹ค. ์ ์ด ์—†์œผ๋ฉด this๋Š” ์ „์—ญ์ด๊ฑฐ๋‚˜ undefined๋‹ค."

Q2. call, apply, bind์˜ ์ฐจ์ด๋ฅผ ํ•œ ๋ฌธ์žฅ์”ฉ ์„ค๋ช…ํ•˜๋ผ.

โœ… ์ •๋‹ต:

  • call: this์™€ ์ธ์ž๋ฅผ ์ง€์ •ํ•ด ์ฆ‰์‹œ ์‹คํ–‰
  • apply: this์™€ ์ธ์ž๋ฅผ ๋ฐฐ์—ด๋กœ ์ง€์ •ํ•ด ์ฆ‰์‹œ ์‹คํ–‰
  • bind: this๊ฐ€ ๊ณ ์ •๋œ ์ƒˆ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ (์‹คํ–‰ ์•ˆ ํ•จ)

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์…‹ ๋‹ค this๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ง€๋งŒ, ์‹คํ–‰ ์‹œ์  ๊ณผ ์ธ์ž ์ „๋‹ฌ ๋ฐฉ์‹ ์ด ๋‹ค๋ฅด๋‹ค.
  • ์‹ค๋ฌด์—์„œ bind๊ฐ€ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ธ๋‹ค: ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ, ์ฝœ๋ฐฑ, setTimeout ๋“ฑ "๋‚˜์ค‘์— ์‹คํ–‰"๋˜๋Š” ํ•จ์ˆ˜์— this๋ฅผ ๋ฏธ๋ฆฌ ๊ณ ์ •ํ•  ๋•Œ.
  • apply๋Š” ๊ฐ€๋ณ€ ์ธ์ž ๋ฐฐ์—ด์„ ๊ทธ๋Œ€๋กœ ๋„˜๊ธธ ๋•Œ ์œ ์šฉ: Math.max.apply(null, [1, 2, 3]) (์š”์ฆ˜์€ ์Šคํ”„๋ ˆ๋“œ Math.max(...arr)๋กœ ๋Œ€์ฒด).
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "call์€ ์ฝค๋งˆ(comma), apply๋Š” array, bind๋Š” ๋ฐ˜ํ™˜(bound)"

Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„ โ€” ์‹ค๋ฌด ๋”œ๋ ˆ๋งˆ

์˜์ฒ ์ด๊ฐ€ React ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ(๋ ˆ๊ฑฐ์‹œ)๋ฅผ ์œ ์ง€๋ณด์ˆ˜ํ•˜๋˜ ์ค‘, ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ this.setState๊ฐ€ undefined๋ผ๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. ์–ด๋””๊ฐ€ ๋ฌธ์ œ์ด๊ณ , ์–ด๋–ป๊ฒŒ ๊ณ ์ณ์•ผ ํ•˜๋Š”๊ฐ€?

class PostList extends React.Component {
  constructor(props) {
    super(props);
    this.state = { posts: [] };
  }
 
  fetchPosts() {
    // ํด๋ฆญ ์‹œ this๊ฐ€ ๋ฌด์—‡์ธ์ง€๊ฐ€ ๋ฌธ์ œ
    fetch("/api/posts")
      .then((res) => res.json())
      .then((data) => this.setState({ posts: data })); // ์—ฌ๊ธฐ์„œ ์—๋Ÿฌ
  }
 
  render() {
    return <button onClick={this.fetchPosts}>๊ฒŒ์‹œ๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ</button>;
  }
}

โœ… ์ •๋‹ต: onClick={this.fetchPosts} โ€” ๋ฉ”์„œ๋“œ๋ฅผ ๊บผ๋‚ด์–ด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋„˜๊ธฐ๋Š” ์ˆœ๊ฐ„ this๊ฐ€ ์†์‹ค๋œ๋‹ค. bind ๋˜๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ํด๋ž˜์Šค ํ•„๋“œ๋กœ ํ•ด๊ฒฐํ•œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • this.fetchPosts๋ฅผ onClick์— ๋„˜๊ธฐ๋Š” ๊ฒƒ์€ const fn = this.fetchPosts์™€ ๊ฐ™๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ํด๋ฆญ ์ด๋ฒคํŠธ์— ์˜ํ•ด ํ˜ธ์ถœ๋  ๋•Œ๋Š” PostList ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹Œ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ์˜ ์ปจํ…์ŠคํŠธ์—์„œ ์‹คํ–‰๋œ๋‹ค.
  • ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 1 (constructor bind):
    constructor(props) {
      super(props);
      this.fetchPosts = this.fetchPosts.bind(this); // ์ƒ์„ฑ์ž์—์„œ ๊ณ ์ •
    }
  • ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 2 (ํด๋ž˜์Šค ํ•„๋“œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜):
    fetchPosts = () => { // this๊ฐ€ ์ธ์Šคํ„ด์Šค๋กœ ์ž๋™ ๊ณ ์ •
      fetch("/api/posts")...
    }
  • ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 3 (์ธ๋ผ์ธ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜, ์„ฑ๋Šฅ ์ฃผ์˜):
    <button onClick={() => this.fetchPosts()}>
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "React์—์„œ ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋„˜๊ธธ ๋• ๋ฐ˜๋“œ์‹œ this๋ฅผ ๊ณ ์ • ํ•ด๋ผ. ํ™”์‚ดํ‘œ ํด๋ž˜์Šค ํ•„๋“œ๊ฐ€ ๊ฐ€์žฅ ๊น”๋”ํ•˜๋‹ค."

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

์˜ค๋Š˜ this ์™„์ „ํžˆ ์ •๋ณตํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ์‚ฌ์‹ค ์˜ˆ์ „์— this๊ฐ€ undefined๋ผ๋Š” ์—๋Ÿฌ ๋ณด๋ฉด ๋ฌด์ž‘์ • .bind(this) ๋ถ™์ด๊ฑฐ๋‚˜ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ๊ฐ์ŒŒ๋Š”๋ฐ, ์ด์ œ๋Š” ์™œ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผ ํ•˜๋Š”์ง€๊ฐ€ ์ดํ•ด๋œ๋‹ค.

"์ ์˜ ์™ผ์ชฝ์ด this๋‹ค" โ€” ์˜ํ˜ธ ๋‹˜์ด ์ด ํ•œ ๋งˆ๋””๋กœ ์ •๋ฆฌํ•ด์คฌ์„ ๋•Œ ์ง„์งœ ๋‡Œ์— ๋ฐ•ํ˜”๋‹ค. ์•ž์œผ๋กœ this ์—๋Ÿฌ ๋‚˜๋ฉด ์ฝœ ์Šคํƒ์—์„œ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœ๋๋Š”์ง€ ๋จผ์ € ํ™•์ธํ•˜๋ฉด ๋˜๊ฒ ๋‹ค.

๐Ÿ’ก ์˜ค๋Š˜์˜ ๊ตํ›ˆ: "this๋Š” ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ '๋ถˆ๋ ธ๋А๋ƒ'๋ฅผ ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋ฅผ ๋ถˆ๋Ÿฌ์ค€ ์ฃผ์ฒด๊ฐ€ ๊ณง this์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฃผ์ฒด ์—†์ด ํ™€๋กœ ๋ถˆ๋ ธ๋‹ค๋ฉด, ์ „์—ญ ๊ณต๊ฐ„์ด๋‚˜ undefined๋ฅผ ๋– ์˜ฌ๋ฆฌ์„ธ์š”."

ํ‡ด๊ทผํ•˜๊ณ  ์ง‘์—์„œ ๋ผ๋ฉด ๋“์—ฌ๋จน์œผ๋ฉด์„œ ๋‹ค์Œ ์ฑ•ํ„ฐ ํ›‘์–ด๋ด์•ผ์ง€. ํ”„๋กœํ† ํƒ€์ž…์ด๋ผ๋‹ˆ... ๋ญ”๊ฐ€ ์–ด๋ ค์šธ ๊ฒƒ ๊ฐ™์€ ์ด๋ฆ„์ธ๋ฐ. ๊ทธ๋ž˜๋„ ์ด๋ฒˆ ๊ธฐ์„ธ ์œ ์ง€ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ๋“  ๋˜๊ฒ ์ง€. ํŒŒ์ดํŒ…!


๐Ÿ”— ๋” ์•Œ์•„๋ณด๊ธฐ