λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ’» DEV/Javascript & NodeJS

[NodeJS] Node 의 this λž€? (+ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ this)

by vodkassi 2021. 9. 10.
728x90

✨ console.log(this) 의 결과

 

이전에 μ •λ¦¬ν•΄λ‘μ—ˆλ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ(μ΄ν•˜ JS)의 this μ—μ„œ μ£Όμ˜μ‚¬ν•­μœΌλ‘œ μ–ΈκΈ‰ν–ˆλ“―, λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰λ˜λŠ” JS 의 this 와 node μ—μ„œ μ‹€ν–‰λ˜λŠ” JS 의 this λŠ” λ‹€λ₯΄λ‹€.

 

 

[Javascript] Javascript 의 this λž€?

❗ μ£Όμ˜: Node μ—μ„œμ˜ this λŠ” 쑰금 λ‹€λ¦…λ‹ˆλ‹€. 이 κΈ€μ—μ„œ λ‹€λ£¨λŠ” λ‚΄μš©μ€ λΈŒλΌμš°μ €μ—μ„œ μž‘λ™ν•˜λŠ” JS μ—μ„œμ˜ this μž…λ‹ˆλ‹€. Javascript 의 this λŠ” 자주 λ“±μž₯ν•˜μ§€λ§Œ, μ •ν™•νžˆ μ•ŒκΈ° νž˜λ“  κ°œλ…μ΄λ‹€. 이번 κΈ€μ—μ„œ

haeunyah.tistory.com

 

λΈŒλΌμš°μ €μ˜ μ „μ—­κ°μ²΄λŠ” window 이닀. λ”°λΌμ„œ μ „μ—­ scope μ—μ„œ console.log(this) λ₯Ό μž…λ ₯ν•  경우 window κ°€ λœ¨λŠ” 것이 λ§žλ‹€.

 

console.log(this) // window


ν•˜μ§€λ§Œ λ™μΌν•œ μ½”λ“œλ₯Ό node ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•˜λ©΄ μ–΄λ–€ κ²°κ³Όκ°€ λ‚˜μ˜¬κΉŒ? κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

 

console.log(this) // {}


같은 μ½”λ“œλ₯Ό μ³€λŠ”λ°, μ™œ λ…Έλ“œμ—μ„œλŠ” 빈 객체가 λ‚˜μ˜¬κΉŒ? κ·Έ 이유λ₯Ό μžμ„Ένžˆ ν•œ 번 μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² λ‹€.

✨ JS λŸ°νƒ€μž„μ˜ μ’…λ₯˜μ™€ 차이


μ•žμ„œ μ–ΈκΈ‰ν–ˆλ“―, node μ—μ„œμ˜ this λŠ” 빈 객체이닀. 빈 객체가 λ‚˜μ˜€λŠ” μ΄μœ λŠ” λ‹¨μˆœνžˆ λ§ν•˜λ©΄ JS의 "λŸ°νƒ€μž„ ν™˜κ²½μ΄ λ‹¬λΌμ„œ" 이닀.
쑰금 ν˜Όλž€μŠ€λŸ¬μšΈ 수 μžˆμœΌλ‹ˆ, JS λŸ°νƒ€μž„μ˜ κ°œλ…κ³Ό μ’…λ₯˜λ₯Ό κ°„λž΅νžˆ 짚고 λ„˜μ–΄κ°€κ² λ‹€.

λŸ°νƒ€μž„ ν™˜κ²½μ΄λž€ ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” 곳이닀. μ€‘μš”ν•œ 점은, λŸ°νƒ€μž„ ν™˜κ²½μ΄ λ°”λ‘œ ν”„λ‘œκ·Έλž¨μ΄ μ ‘κ·Όν•  수 μžˆλŠ” μ „μ—­ 객체와 μž‘λ™ 방식을 κ²°μ •ν•œλ‹€λŠ” 사싀이닀. λŒ€ν‘œμ μΈ JS λŸ°νƒ€μž„μ€ λΈŒλΌμš°μ €μ™€ Node 두 κ°œκ°€ μžˆλ‹€.

πŸ“Œ λΈŒλΌμš°μ € (Chrome, Firefox λ“±)
- JS κ°€ μ‹€ν–‰λ˜λŠ” κ°€μž₯ 보편적인 λŸ°νƒ€μž„ ν™˜κ²½μ΄λ‹€.
- λΈŒλΌμš°μ €μ—λŠ” window λΌλŠ” 전역객체가 λ‚΄μž₯λ˜μ–΄ μžˆμ–΄, JS script λ₯Ό 톡해 window 와 κ΄€λ ¨λœ λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€. (μ˜ˆμ‹œ: window.alert())

πŸ“Œ Node
- λΈŒλΌμš°μ € 없이도 JS μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆλ„λ‘ ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ§„ λŸ°νƒ€μž„ ν™˜κ²½μ΄λ‹€.
- λΈŒλΌμš°μ €μ™€λŠ” μ „ν˜€ λ‹€λ₯Έ λŸ°νƒ€μž„ ν™˜κ²½μ΄κΈ° λ•Œλ¬Έμ—, λΈŒλΌμš°μ € κ΄€λ ¨ 객체 (window λ“±) μ—λŠ” μ ‘κ·Όν•  수 μ—†λ‹€.
- λŒ€μ‹ , μ„œλ²„λ₯Ό ꡬ좕할 λ•Œ ν•„μš”ν•œ λ‹€λ₯Έ λ³€μˆ˜λ“€ (ν™˜κ²½λ³€μˆ˜ λ“±) 에 μ ‘κ·Όν•  수 μžˆλ„λ‘ μ„€μ •λ˜μ–΄ μžˆλ‹€.

✨ Node 의 μ „μ—­ 객체

λ‹€μ‹œ 처음으둜 λŒμ•„κ°€, node μ—μ„œ this λ₯Ό 좜λ ₯ν•˜λ©΄ 빈 객체가 λ‚˜μ˜¨λ‹€λŠ” 사싀을 κΈ°μ–΅ν•˜μž.

 

console.log(this) // {}


Node μ—λŠ” window 와 document λŒ€μ‹  λ‹€λ₯Έ μ „μ—­ 객체가 μ‘΄μž¬ν•œλ‹€. λ°”λ‘œ global μ΄λΌλŠ” 객체이닀.
global κ°μ²΄λŠ” λ‹€μŒκ³Ό 같이 κ΅¬μ„±λ˜μ–΄ μžˆλ‹€.

 

<ref *1> Object [global] { 
    global: [Circular *1], 
    clearInterval: [Function: clearInterval], 
    clearTimeout: [Function: clearTimeout], 
    setInterval: [Function: setInterval], 
    setTimeout: [Function: setTimeout] { 
        [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)] 
    }, 
    queueMicrotask: [Function: queueMicrotask], 
    clearImmediate: [Function: clearImmediate], 
    setImmediate: [Function: setImmediate] { 
        [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
    }
}

 


πŸ“Œ μ „μ—­ 객체가 global 인데 μ™œ console.log(this) λ₯Ό μ‹€ν–‰ν•˜λ©΄ 빈 객체가 λ‚˜μ˜¬κΉŒ?

κ·Έ μ΄μœ λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

- Nodeμ—μ„œ μ‹€ν–‰λ˜λŠ” js νŒŒμΌμ€ ν•˜λ‚˜μ˜ λͺ¨λ“ˆ(module) 이닀.
- μ‹€μ œλ‘œ node λͺ…λ Ήμ–΄λ₯Ό 톡해 js 파일 ν•˜λ‚˜λ₯Ό μ‹€ν–‰ν•˜λ©΄, 파일의 전체 script κ°€ ν•˜λ‚˜μ˜ ν•¨μˆ˜ μ•ˆμ— λ“€μ–΄κ°€κ²Œ λœλ‹€.
- Node 엔진은 ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•¨μœΌλ‘œμ¨ μ‚¬μš©μžκ°€ μž‘μ„±ν•œ μ½”λ“œμ˜ κ²°κ³Όλ₯Ό 좜λ ₯ν•˜λŠ” 것이닀.
- 결과적으둜, js νŒŒμΌμ—μ„œ μž‘μ„±ν•˜λŠ” μ½”λ“œ μ „μ²΄λŠ” ν•˜λ‚˜μ˜ ν•¨μˆ˜ 내뢀에 λ“€μ–΄κ°€κ²Œ λ˜λŠ” κ²ƒμ΄λ―€λ‘œ, 지역 scope λ₯Ό κ°€μ§€κ²Œ λœλ‹€.


μœ„ μ‚¬μ§„μ˜ μ½”λ“œ 쀑 κ°œλ°œμžκ°€ μž‘μ„±ν•œ μ½”λ“œκ°€ μ‹œμž‘ν•˜λŠ” μ‹œμ μ€ 첫 번째 μ€„μ˜ console.log 뢀터이닀.
μœ„μ²˜λŸΌ js μ½”λ“œλ₯Ό node μ‹€ν–‰ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•  λ•Œ debugger λ₯Ό μ—°κ²°ν•΄μ„œ 확인해보면, μ½”λ“œκ°€ ν•˜λ‚˜μ˜ ν•¨μˆ˜ μ•ˆμ— λ“€μ–΄κ°€ μžˆλ‹€λŠ” 것을 λ³Ό 수 μžˆμ„ 것이닀.

πŸ“Œ js νŒŒμΌμ€ ν•˜λ‚˜μ˜ ν•¨μˆ˜ μ•ˆμ—μ„œ μ‹€ν–‰λ˜λ―€λ‘œ, ν•΄λ‹Ή ν•¨μˆ˜ 내뢀에 μ‘΄μž¬ν•˜λŠ” κΈ°λ³Έ 객체가 this 의 참쑰값이 λœλ‹€.
λ”°λΌμ„œ, nodejs 파일 μ•ˆμ—μ„œμ˜ this λ₯Ό 좜λ ₯ν•œ κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

 

console.log(this, module.exports, exports); // {}, {}, {} 
console.log(this === module.exports); // true 
console.log(this === exports); // true 
console.log(module.exports === exports); // true 
console.log(this === global); // false


module.exports 와 exports λŠ” ν•˜λ‚˜μ˜ js νŒŒμΌμ„ λͺ¨λ“ˆλ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” 빈 객체이닀. 이 빈 객체가 곧 nodejs μ—μ„œ μ‹€ν–‰λ˜λŠ” 파일의 this κ°€ λœλ‹€.


πŸ“Œ κ·Έλ ‡λ‹€λ©΄ global 이 μ „μ—­ κ°μ²΄λΌλŠ” 것을 확인할 수 μžˆλŠ” 방법은 μ—†λ‚˜?
λ‹Ήμ—°νžˆ 확인할 수 μžˆλ‹€!!

JS 의 this 의 νŠΉμ§• 쀑, μ–΄λ–€ ν•¨μˆ˜λ“  일반 ν•¨μˆ˜λ‘œ μ‹€ν–‰λœλ‹€λ©΄ ν•΄λ‹Ή ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ°Έμ‘°ν•˜λŠ” this λŠ” μ „μ—­κ°μ²΄λΌλŠ” 점이 μžˆμ—ˆλ‹€. 이 νŠΉμ§•μ„ ν™œμš©ν•΄ js 파일 내뢀에 μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό 생성해 this λ₯Ό 좜λ ₯ν•˜λ„λ‘ ν•΄λ³΄μž.

 

function a() { 
    console.log(this) // global 
    console.log(this === global) // true 
} 

a()


a ν•¨μˆ˜λŠ” 일반 ν•¨μˆ˜λ‘œ μ‹€ν–‰λ˜μ—ˆκΈ° λ•Œλ¬Έμ— λ‚΄λΆ€μ—μ„œ 좜λ ₯ν•œ this λŠ” 전역객체이며, global μ΄λΌλŠ” 결과물이 좜λ ₯λœλ‹€. λ˜ν•œ, ν•΄λ‹Ή ν•¨μˆ˜ λ‚΄λΆ€μ˜ this 와 global 을 비ꡐ해보면 'λ™μΌν•˜λ‹€' (true) λΌλŠ” κ²°κ³Όκ°€ λ‚˜μ˜¨λ‹€.


✨ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ this


이전 κΈ€μ—μ„œ this 의 νŠΉμ§• λŒ€λΆ€λΆ„μ„ 짚고 λ„˜μ–΄κ°”μ§€λ§Œ, ν™”μ‚΄ν‘œ ν•¨μˆ˜μΌ λ•Œ λ‚˜νƒ€λ‚˜λŠ” this 의 νŠΉμˆ˜ν•œ νŠΉμ§•μ„ λˆ„λ½ν•˜μ—¬ 이번 글에 μ΄μ–΄μ„œ μ„€λͺ…ν•΄λ³Έλ‹€.

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” λ‹€λ₯Έ ν•¨μˆ˜μ™€ λ‹€λ₯΄κ²Œ, μžμ‹ μ˜ thisκ°€ μ—†λ‹€. 이 말의 μ˜λ―ΈλŠ”, ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ this λŠ” 일반적인 ν•¨μˆ˜μ²˜λŸΌ ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜ μ†Œμœ ν•œ 객체λ₯Ό μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것이닀. λŒ€μ‹ , ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ this λŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό λ‘˜λŸ¬μ‹ΈλŠ” μƒμœ„ μŠ€μ½”ν”„μ˜ this λ₯Ό μ‚¬μš©ν•œλ‹€. (λ•Œλ¬Έμ— lexical this 둜 λΆˆλ¦¬κΈ°λ„ ν•œλ‹€)

μ˜ˆμ‹œλ₯Ό 듀어보겠닀.

 

const temp = { 
    age: 10, 
    tempFunc() { 
    	console.log(this.age) // 10 
    } 
} 

temp.tempFunc(); 

const temp1 = { 
    age: 10, 
    tempFunc: () => { 
    	console.log(this.age) // undefined 
    } 
} 

temp1.tempFunc();


temp 객체의 tempFunc 의 경우 일반 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμœΌλ―€λ‘œ, λ©”μ„œλ“œλ‘œ 호좜될 μ‹œ 호좜된 객체λ₯Ό this 의 κ°’μœΌλ‘œ μ°Έμ‘°ν•˜μ—¬ temp λ‚΄μ—μ„œ age λ₯Ό μ°Ύκ³ , κ·Έ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

κ·ΈλŸ¬λ‚˜ temp1 객체의 tempFunc λŠ” 쑰금 λ‹€λ₯΄λ‹€. ν•΄λ‹Ή ν•¨μˆ˜λŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜μ΄κΈ° λ•Œλ¬Έμ—, μƒμœ„ μŠ€μ½”ν”„μ˜ this λ₯Ό μ‚¬μš©ν•œλ‹€. tempFunc 의 μƒμœ„ μŠ€μ½”ν”„μΈ μ „μ—­ κ°μ²΄μ—μ„œλŠ” age λΌλŠ” 값이 μ„ μ–Έλ˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ—, undefined κ°€ 좜λ ₯λ˜μ—ˆλ‹€.


πŸ“Œ λΆˆνŽΈν•΄λ„, ν•„μš”ν•œ 이유

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ—μ„œμ˜ this λŠ” μž‘λ™ 원리λ₯Ό μ΄ν•΄ν•˜κΈ°λ„, μ‚¬μš©ν•˜κΈ°λ„ μ–΄λ €μš΄ 것이 사싀이닀. κ·ΈλŸ¬λ‚˜ μ΄λŸ¬ν•œ νŠΉμ§•μ΄ ν•„μš”ν•œ κ²½μš°κ°€ κ°„ν˜Ή λ°œμƒν•œλ‹€.
λ¨Όμ € λ‹€μŒ μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄μž.

 

let group = { 
    title: "1λͺ¨λ‘ ", 
    students: ["보라", "ν˜Έμ§„", "지민"], 
    showList() { 
        this.students.forEach(function(student) { 
            // TypeError: Cannot read property 'title' of undefined 
            console.log(this.title + ': ' + student) 
        }); 
    } 
};


showList() ν•¨μˆ˜μ˜ this λŠ” group 객체이기 λ•Œλ¬Έμ—, this.students λ₯Ό μ°Έμ‘°ν•˜μ—¬ forEach 문을 λŒλ¦¬λŠ” 것이 κ°€λŠ₯ν•˜λ‹€. κ·ΈλŸ¬λ‚˜ κ·Έ λ‚΄λΆ€μ—μ„œ μž‘λ™ν•˜λŠ” ν•¨μˆ˜λŠ” 일반 ν•¨μˆ˜μ΄κΈ° λ•Œλ¬Έμ—, this κ°€ μ°Έμ‘°ν•˜λŠ” 값이 μ „μ—­ 객체인 window (λ˜λŠ” global) 이 λ˜μ–΄, λ”°λ‘œ 선언이 λ˜μ–΄ μžˆμ§€ μ•Šμ€ 이상 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•˜κ²Œ λœλ‹€.

μ•žμ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμœ„ μŠ€μ½”ν”„μ˜ this λ₯Ό μ‚¬μš©ν•œλ‹€κ³  μ–ΈκΈ‰ν–ˆμ—ˆλŠ”λ°, κ·Έλ ‡λ‹€λ©΄ λ˜‘κ°™μ€ μ½”λ“œλ₯Ό ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ λ°”κΎΌλ‹€λ©΄ μ–΄λ–»κ²Œ 될까?

 

let group1 = { 
    title: "1λͺ¨λ‘ ", 
    students: ["보라", "ν˜Έμ§„", "지민"], 
    showList() { 
        this.students.forEach( student => { 
            console.log(this.title + ': ' + student)  // 1λͺ¨λ‘  : 보라, 1λͺ¨λ‘  : ν˜Έμ§„, 1λͺ¨λ‘₯ : 지민
        }); 
    } 
};


μ˜λ„ν•œ 결과인 "1λͺ¨λ‘  : 보라", "1λͺ¨λ‘  : ν˜Έμ§„", "1λͺ¨λ‘₯ : 지민"이 μ°¨λ‘€λ‘œ 좜λ ₯될 것이닀. κ·Έ μ΄μœ λŠ” λ°”λ‘œ forEach λ¬Έ μ•ˆμ˜ ν•¨μˆ˜κ°€ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ΄λ―€λ‘œ, μƒμœ„ μŠ€μ½”ν”„ (showList() ν•¨μˆ˜ μŠ€μ½”ν”„) 의 this λ₯Ό μ°Έμ‘°ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€.

이와 같이 일반 ν•¨μˆ˜μ˜ μ‚¬μš©μœΌλ‘œ 인해 this 의 참쑰값이 λ°”λ€ŒλŠ” 경우, ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ κ·Έ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆκΈ°λ„ ν•˜λ‹€.


πŸ“Œ λ§ˆμ§€λ§‰μœΌλ‘œ, ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” thisκ°€ μ—†κΈ° λ•Œλ¬Έμ— μƒμ„±μž ν•¨μˆ˜λ‘œ μ‚¬μš©ν•  수 μ—†μœΌλ©°, new 와 ν•¨κ»˜ ν˜ΈμΆœν•  μˆ˜λ„ μ—†λ‹€.

✨ 배운 점

  • ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ κ³ μœ ν•œ κ·œμΉ™μ΄ λ„ˆλ¬΄ λ³΅μž‘ν•˜κ³  어렡기도 ν•˜μ§€λ§Œ, λ³΅μž‘ν•œλ§ŒνΌ μœ μš©ν•˜κ²Œ μ‚¬μš©λ  λ•Œκ°€ λΆ„λͺ… μ°Ύμ•„μ˜¬ 것이라고 μƒκ°ν•œλ‹€. 그런 μ˜λ―Έμ—μ„œ Javascript λŠ” 은근 만λŠ₯ μ–Έμ–΄λΌλŠ” 생각이 λ“ λ‹€. "이걸 μ΄λ ‡κ²Œ ν•΄μ£ΌλŠ” 건 μ™œ 없지?" ν•΄μ„œ 찾아보면 λŒ€λΆ€λΆ„ μ‘΄μž¬ν•˜λŠ” κΈ°λŠ₯이닀... λ‚˜μ˜ 곡뢀가 λΆ€μ‘±ν•  뿐!

 

✨ 참고자료

λŒ“κΈ€