μλ°μ€ν¬λ¦½νΈ λΉλκΈ° 컨ν μ€νΈ λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό λ§μ€ν°νκ³ , 컨ν μ€νΈ μλͺ μ£ΌκΈ°λ₯Ό μ΅μ ννμ¬ λΉλκΈ° μ ν리μΌμ΄μ μ μ±λ₯κ³Ό μμ μ±μ ν₯μμν€μΈμ.
μλ°μ€ν¬λ¦½νΈ λΉλκΈ° 컨ν μ€νΈ λ©λͺ¨λ¦¬ κ΄λ¦¬: 컨ν μ€νΈ μλͺ μ£ΌκΈ° μ΅μ ν
λΉλκΈ° νλ‘κ·Έλλ°μ νλ μλ°μ€ν¬λ¦½νΈ κ°λ°μ ν΅μ¬μΌλ‘, λ°μμ± λκ³ ν¨μ¨μ μΈ μ ν리μΌμ΄μ μ ꡬμΆν μ μκ² ν΄μ€λλ€. κ·Έλ¬λ λΉλκΈ° μμ μμ 컨ν μ€νΈλ₯Ό κ΄λ¦¬νλ κ²μ 볡μ‘ν΄μ§ μ μμΌλ©°, μ μ€νκ² λ€λ£¨μ§ μμΌλ©΄ λ©λͺ¨λ¦¬ λμλ μ±λ₯ λ¬Έμ λ₯Ό μΌμΌν¬ μ μμ΅λλ€. μ΄ κΈμμλ μλ°μ€ν¬λ¦½νΈμ λΉλκΈ° 컨ν μ€νΈμ 볡μ‘μ±μ κΉμ΄ νκ³ λ€μ΄, κ²¬κ³ νκ³ νμ₯ κ°λ₯ν μ ν리μΌμ΄μ μ μν μλͺ μ£ΌκΈ° μ΅μ νμ μ΄μ μ λ§μΆ₯λλ€.
μλ°μ€ν¬λ¦½νΈμ λΉλκΈ° 컨ν μ€νΈ μ΄ν΄νκΈ°
λκΈ°μ μΈ μλ°μ€ν¬λ¦½νΈ μ½λμμ 컨ν μ€νΈ(λ³μ, ν¨μ νΈμΆ, μ€ν μν)λ κ΄λ¦¬νκΈ°κ° κ°λ¨ν©λλ€. ν¨μκ° μ’ λ£λλ©΄ ν΄λΉ 컨ν μ€νΈλ μΌλ°μ μΌλ‘ ν΄μ λμ΄ κ°λΉμ§ 컬λ ν°κ° λ©λͺ¨λ¦¬λ₯Ό νμν μ μκ² λ©λλ€. κ·Έλ¬λ λΉλκΈ° μμ μ 볡μ‘μ±μ ν μΈ΅ λν©λλ€. APIμμ λ°μ΄ν°λ₯Ό κ°μ Έμ€κ±°λ μ¬μ©μ μ΄λ²€νΈλ₯Ό μ²λ¦¬νλ κ²κ³Ό κ°μ λΉλκΈ° μμ μ μ¦μ μλ£λμ§ μλ κ²½μ°κ° λ§μ΅λλ€. μ΄λ¬ν μμ λ€μ μ½λ°±, νλ‘λ―Έμ€(Promise), λλ async/awaitλ₯Ό ν¬ν¨νλ©°, μ΄λ ν΄λ‘μ λ₯Ό μμ±νκ³ μ£Όλ³ μ€μ½νμ λ³μμ λν μ°Έμ‘°λ₯Ό μ μ§ν μ μμ΅λλ€. μ΄λ‘ μΈν΄ 컨ν μ€νΈμ μΌλΆκ° νμ μ΄μμΌλ‘ μ€λ μ μ§λμ΄ μλμΉ μκ² λ©λͺ¨λ¦¬ λμλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
ν΄λ‘μ μ μν
ν΄λ‘μ λ λΉλκΈ° μλ°μ€ν¬λ¦½νΈμμ μ€μν μν μ ν©λλ€. ν΄λ‘μ λ ν¨μμ κ·Έ ν¨μκ° μ μΈλ λΉμμ λ μ컬 νκ²½(surrounding state)μ λν μ°Έμ‘°μ μ‘°ν©μ λλ€. μ¦, ν΄λ‘μ λ λ΄λΆ ν¨μμμ μΈλΆ ν¨μμ μ€μ½νμ μ κ·Όν μ μκ² ν΄μ€λλ€. λΉλκΈ° μμ μ΄ μ½λ°±μ΄λ νλ‘λ―Έμ€μ μμ‘΄ν λ, μ’ μ’ ν΄λ‘μ λ₯Ό μ¬μ©νμ¬ λΆλͺ¨ μ€μ½νμ λ³μμ μ κ·Όν©λλ€. λ§μ½ μ΄ ν΄λ‘μ λ€μ΄ λ μ΄μ νμνμ§ μμ ν° κ°μ²΄λ λ°μ΄ν° ꡬ쑰μ λν μ°Έμ‘°λ₯Ό μ μ§νλ€λ©΄, λ©λͺ¨λ¦¬ μλΉμ μλΉν μν₯μ λ―ΈμΉ μ μμ΅λλ€.
λ€μ μμ λ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€:
function fetchData(url) {
const largeData = new Array(1000000).fill('some data'); // Simulate a large dataset
return new Promise((resolve, reject) => {
setTimeout(() => {
// Simulate fetching data from an API
const result = `Data from ${url}`; // Uses url from the outer scope
resolve(result);
}, 1000);
});
}
async function processData() {
const data = await fetchData('https://example.com/api/data');
console.log(data);
// largeData is still in scope here, even if it's not used directly
}
processData();
μ΄ μμ μμ `processData`κ° κ°μ Έμ¨ λ°μ΄ν°λ₯Ό λ‘κ·Έμ κΈ°λ‘ν νμλ, `fetchData` λ΄μ `setTimeout` μ½λ°±μ μν΄ μμ±λ ν΄λ‘μ λλ¬Έμ `largeData`λ μ¬μ ν μ€μ½ν λ΄μ λ¨μ μμ΅λλ€. λ§μ½ `fetchData`κ° μ¬λ¬ λ² νΈμΆλλ€λ©΄, μ¬λ¬ `largeData` μΈμ€ν΄μ€κ° λ©λͺ¨λ¦¬μ μ μ§λμ΄ μ μ¬μ μΌλ‘ λ©λͺ¨λ¦¬ λμλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
λΉλκΈ° μλ°μ€ν¬λ¦½νΈμμ λ©λͺ¨λ¦¬ λμ μλ³νκΈ°
λΉλκΈ° μλ°μ€ν¬λ¦½νΈμμ λ©λͺ¨λ¦¬ λμλ₯Ό κ°μ§νλ κ²μ μ΄λ €μΈ μ μμ΅λλ€. λ€μμ λͺ κ°μ§ μΌλ°μ μΈ λꡬμ κΈ°μ μ λλ€:
- λΈλΌμ°μ κ°λ°μ λꡬ: λλΆλΆμ μ΅μ λΈλΌμ°μ λ λ©λͺ¨λ¦¬ μ¬μ©λμ νλ‘νμΌλ§νκΈ° μν κ°λ ₯ν κ°λ°μ λꡬλ₯Ό μ 곡ν©λλ€. μλ₯Ό λ€μ΄, ν¬λ‘¬ κ°λ°μ λꡬ(Chrome DevTools)λ₯Ό μ¬μ©νλ©΄ ν μ€λ μ·μ μ°κ³ , λ©λͺ¨λ¦¬ ν λΉ νμλΌμΈμ κΈ°λ‘νλ©°, κ°λΉμ§ 컬λ μ λμ§ μλ κ°μ²΄λ₯Ό μλ³ν μ μμ΅λλ€. μ μ¬μ μΈ λμλ₯Ό μ‘°μ¬ν λλ μ μ§λ ν¬κΈ°(retained size)μ μμ±μ μ νμ μ£Όμλ₯Ό κΈ°μΈμ΄μΈμ.
- Node.js λ©λͺ¨λ¦¬ νλ‘νμΌλ¬: Node.js μ ν리μΌμ΄μ μ κ²½μ°, `heapdump`λ `v8-profiler`μ κ°μ λꡬλ₯Ό μ¬μ©νμ¬ ν μ€λ μ·μ μΊ‘μ²νκ³ λ©λͺ¨λ¦¬ μ¬μ©λμ λΆμν μ μμ΅λλ€. Node.js μΈμ€νν°(`node --inspect`) λν ν¬λ‘¬ κ°λ°μ λꡬμ μ μ¬ν λλ²κΉ μΈν°νμ΄μ€λ₯Ό μ 곡ν©λλ€.
- μ±λ₯ λͺ¨λν°λ§ λꡬ: New Relic, Datadog, Sentryμ κ°μ μ ν리μΌμ΄μ μ±λ₯ λͺ¨λν°λ§(APM) λꡬλ μκ° κ²½κ³Όμ λ°λ₯Έ λ©λͺ¨λ¦¬ μ¬μ©λ μΆμΈμ λν ν΅μ°°λ ₯μ μ 곡ν μ μμ΅λλ€. μ΄λ¬ν λꡬλ ν¨ν΄μ μλ³νκ³ μ½λμμ λ©λͺ¨λ¦¬ λμμ κΈ°μ¬ν μ μλ μμμ μ νν μ°Ύμλ΄λ λ° λμμ΄ λ©λλ€.
- μ½λ 리뷰: μ κΈ°μ μΈ μ½λ 리뷰λ μ μ¬μ μΈ λ©λͺ¨λ¦¬ κ΄λ¦¬ λ¬Έμ κ° μ¬κ°ν΄μ§κΈ° μ μ μλ³νλ λ° λμμ΄ λ μ μμ΅λλ€. λΉλκΈ° μμ μμ μ¬μ©λλ ν΄λ‘μ , μ΄λ²€νΈ 리μ€λ, λ°μ΄ν° ꡬ쑰μ νΉν μ£Όμλ₯Ό κΈ°μΈμ΄μΈμ.
λ©λͺ¨λ¦¬ λμμ μΌλ°μ μΈ μ§ν
λ€μμ μ¬λ¬λΆμ μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ΄ λ©λͺ¨λ¦¬ λμλ₯Ό κ²ͺκ³ μμ μ μλ€λ λͺ κ°μ§ λͺ λ°±ν μ§νμ λλ€:
- μ μ§μ μΈ λ©λͺ¨λ¦¬ μ¬μ©λ μ¦κ°: μ ν리μΌμ΄μ μ΄ νλ°νκ² μμ μ μννμ§ μμ λμλ μκ°μ΄ μ§λ¨μ λ°λΌ λ©λͺ¨λ¦¬ μλΉκ° κΎΈμ€ν μ¦κ°ν©λλ€.
- μ±λ₯ μ ν: μ ν리μΌμ΄μ μ΄ λ μ€λ κΈ°κ° μ€νλ μλ‘ λλ €μ§κ³ λ°μμ±μ΄ λ¨μ΄μ§λλ€.
- μ¦μ κ°λΉμ§ 컬λ μ μ£ΌκΈ°: κ°λΉμ§ 컬λ ν°κ° λ μμ£Ό μ€νλλ©°, μ΄λ λ©λͺ¨λ¦¬ νμμ μ΄λ €μμ κ²ͺκ³ μμμ λνλ λλ€.
- μ ν리μΌμ΄μ μΆ©λ: κ·Ήλ¨μ μΈ κ²½μ°, λ©λͺ¨λ¦¬ λμλ λ©λͺ¨λ¦¬ λΆμ‘± μ€λ₯λ‘ μΈν΄ μ ν리μΌμ΄μ μΆ©λλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
λΉλκΈ° 컨ν μ€νΈ μλͺ μ£ΌκΈ° μ΅μ ν
μ΄μ λΉλκΈ° 컨ν μ€νΈ λ©λͺ¨λ¦¬ κ΄λ¦¬μ μ΄λ €μμ μ΄ν΄νμΌλ―λ‘, 컨ν μ€νΈ μλͺ μ£ΌκΈ°λ₯Ό μ΅μ ννκΈ° μν λͺ κ°μ§ μ λ΅μ μ΄ν΄λ³΄κ² μ΅λλ€:
1. ν΄λ‘μ μ€μ½ν μ΅μν
ν΄λ‘μ μ μ€μ½νκ° μμμλ‘ λ μ μ λ©λͺ¨λ¦¬λ₯Ό μλΉν©λλ€. ν΄λ‘μ μμ λΆνμν λ³μλ₯Ό μΊ‘μ²νλ κ²μ νΌνμΈμ. λμ , λΉλκΈ° μμ μ μ격νκ² νμν λ°μ΄ν°λ§ μ λ¬νμΈμ.
μμ :
λμ μ:
function processUserData(user) {
const userData = { ...user, extraData: 'some extra info' }; // Create a new object
setTimeout(() => {
console.log(`Processing user: ${userData.name}`); // Access userData
}, 1000);
}
μ΄ μμ μμλ `setTimeout` μ½λ°± λ΄λΆμμ `name` μμ±λ§ μ¬μ©λ¨μλ λΆκ΅¬νκ³ μ 체 `userData` κ°μ²΄κ° ν΄λ‘μ μ μΊ‘μ²λ©λλ€.
μ’μ μ:
function processUserData(user) {
const userData = { ...user, extraData: 'some extra info' };
const userName = userData.name; // Extract the name
setTimeout(() => {
console.log(`Processing user: ${userName}`); // Access only userName
}, 1000);
}
μ΄ μ΅μ νλ λ²μ μμλ `userName`λ§ ν΄λ‘μ μ μΊ‘μ²λμ΄ λ©λͺ¨λ¦¬ μ¬μ©λμ μ€μ λλ€.
2. μν μ°Έμ‘° λκΈ°
μν μ°Έμ‘°λ λ κ° μ΄μμ κ°μ²΄κ° μλ‘λ₯Ό μ°Έμ‘°νμ¬ κ°λΉμ§ 컬λ μ λλ κ²μ λ§μ λ λ°μν©λλ€. μ΄λ λΉλκΈ° μλ°μ€ν¬λ¦½νΈμμ, νΉν μ΄λ²€νΈ 리μ€λλ 볡μ‘ν λ°μ΄ν° ꡬ쑰λ₯Ό λ€λ£° λ νν λ¬Έμ κ° λ μ μμ΅λλ€.
μμ :
class MyObject {
constructor() {
this.eventListeners = [];
}
addListener(listener) {
this.eventListeners.push(listener);
}
removeListener(listener) {
this.eventListeners = this.eventListeners.filter(l => l !== listener);
}
doSomethingAsync() {
const listener = () => {
console.log('Something happened!');
this.doSomethingElse(); // Circular reference: listener references this
};
this.addListener(listener);
setTimeout(() => {
this.removeListener(listener);
}, 1000);
}
doSomethingElse() {
console.log('Doing something else.');
}
}
const myObject = new MyObject();
myObject.doSomethingAsync();
μ΄ μμ μμ `doSomethingAsync` λ΄μ `listener` ν¨μλ `this`(`MyObject` μΈμ€ν΄μ€)μ λν μ°Έμ‘°λ₯Ό μΊ‘μ²ν©λλ€. `MyObject` μΈμ€ν΄μ€ λν `eventListeners` λ°°μ΄μ ν΅ν΄ `listener`μ λν μ°Έμ‘°λ₯Ό κ°μ§κ³ μμ΅λλ€. μ΄λ‘ μΈν΄ `setTimeout` μ½λ°±μ΄ μ€νλ νμλ `MyObject` μΈμ€ν΄μ€μ `listener` λͺ¨λ κ°λΉμ§ 컬λ μ λλ κ²μ λ§λ μν μ°Έμ‘°κ° μμ±λ©λλ€. λΉλ‘ 리μ€λκ° eventListeners λ°°μ΄μμ μ κ±°λλλΌλ, ν΄λ‘μ μ체λ μ¬μ ν `this`μ λν μ°Έμ‘°λ₯Ό μ μ§ν©λλ€.
ν΄κ²°μ± : λ μ΄μ νμνμ§ μμ λ μ°Έμ‘°λ₯Ό λͺ μμ μΌλ‘ `null` λλ undefinedλ‘ μ€μ νμ¬ μν μ°Έμ‘°λ₯Ό λμ΅λλ€.
class MyObject {
constructor() {
this.eventListeners = [];
}
addListener(listener) {
this.eventListeners.push(listener);
}
removeListener(listener) {
this.eventListeners = this.eventListeners.filter(l => l !== listener);
}
doSomethingAsync() {
let listener = () => {
console.log('Something happened!');
this.doSomethingElse();
listener = null; // Break the circular reference
};
this.addListener(listener);
setTimeout(() => {
this.removeListener(listener);
}, 1000);
}
doSomethingElse() {
console.log('Doing something else.');
}
}
const myObject = new MyObject();
myObject.doSomethingAsync();
μμ ν΄κ²°μ± μ΄ μν μ°Έμ‘°λ₯Ό λλ κ²μ²λΌ λ³΄μΌ μ μμ§λ§, `setTimeout` λ΄μ 리μ€λλ μ¬μ ν μλμ `listener` ν¨μλ₯Ό μ°Έμ‘°νκ³ , μ΄λ λ€μ `this`λ₯Ό μ°Έμ‘°ν©λλ€. λ κ²¬κ³ ν ν΄κ²°μ± μ 리μ€λ λ΄μμ `this`λ₯Ό μ§μ μΊ‘μ²νλ κ²μ νΌνλ κ²μ λλ€.
class MyObject {
constructor() {
this.eventListeners = [];
}
addListener(listener) {
this.eventListeners.push(listener);
}
removeListener(listener) {
this.eventListeners = this.eventListeners.filter(l => l !== listener);
}
doSomethingAsync() {
const self = this; // Capture 'this' in a separate variable
const listener = () => {
console.log('Something happened!');
self.doSomethingElse(); // Use the captured 'self'
};
this.addListener(listener);
setTimeout(() => {
this.removeListener(listener);
}, 1000);
}
doSomethingElse() {
console.log('Doing something else.');
}
}
const myObject = new MyObject();
myObject.doSomethingAsync();
μ΄κ²μ μ΄λ²€νΈ 리μ€λκ° μ€λ«λμ μ°κ²°λμ΄ μλ κ²½μ° λ¬Έμ λ₯Ό μμ ν ν΄κ²°νμ§ λͺ»ν©λλ€. κ°μ₯ μ λ’°ν μ μλ μ κ·Ό λ°©μμ `MyObject` μΈμ€ν΄μ€λ₯Ό μ§μ μ°Έμ‘°νλ ν΄λ‘μ λ₯Ό νΌνκ³ μ΄λ²€νΈ λ°μ λ©μ»€λμ¦μ μ¬μ©νλ κ²μ λλ€.
3. μ΄λ²€νΈ 리μ€λ κ΄λ¦¬
μ΄λ²€νΈ 리μ€λλ μ λλ‘ μ κ±°λμ§ μμΌλ©΄ λ©λͺ¨λ¦¬ λμμ νν μμΈμ΄ λ©λλ€. μμλ κ°μ²΄μ μ΄λ²€νΈ 리μ€λλ₯Ό 첨λΆνλ©΄, 리μ€λλ λͺ μμ μΌλ‘ μ κ±°λκ±°λ μμ/κ°μ²΄κ° νκ΄΄λ λκΉμ§ νμ± μνλ‘ μ μ§λ©λλ€. 리μ€λλ₯Ό μ κ±°νλ κ²μ μμΌλ©΄ μκ°μ΄ μ§λ¨μ λ°λΌ λμ λμ΄ λ©λͺ¨λ¦¬λ₯Ό μλΉνκ³ μ μ¬μ μΌλ‘ μ±λ₯ λ¬Έμ λ₯Ό μΌμΌν¬ μ μμ΅λλ€.
μμ :
const button = document.getElementById('myButton');
function handleClick() {
console.log('Button clicked!');
}
button.addEventListener('click', handleClick);
// PROBLEM: The event listener is never removed!
ν΄κ²°μ± : λ μ΄μ νμνμ§ μμ λ νμ μ΄λ²€νΈ 리μ€λλ₯Ό μ κ±°νμΈμ.
const button = document.getElementById('myButton');
function handleClick() {
console.log('Button clicked!');
button.removeEventListener('click', handleClick); // Remove the listener
}
button.addEventListener('click', handleClick);
// Alternatively, remove the listener after a certain condition:
setTimeout(() => {
button.removeEventListener('click', handleClick);
}, 5000);
`WeakMap`μ μ¬μ©νμ¬ DOM μμμ κ°λΉμ§ 컬λ μ μ λ°©ν΄νμ§ μμΌλ©΄μ ν΄λΉ μμμ λ°μ΄ν°λ₯Ό μ°κ²°νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ.
4. WeakRefμ FinalizationRegistry μ¬μ©νκΈ° (κ³ κΈ)
λ 볡μ‘ν μλ리μ€μμλ `WeakRef`μ `FinalizationRegistry`λ₯Ό μ¬μ©νμ¬ κ°μ²΄ μλͺ μ£ΌκΈ°λ₯Ό λͺ¨λν°λ§νκ³ κ°μ²΄κ° κ°λΉμ§ 컬λ μ λ λ μ 리 μμ μ μνν μ μμ΅λλ€. `WeakRef`λ κ°μ²΄μ κ°λΉμ§ 컬λ μ μ λ°©ν΄νμ§ μμΌλ©΄μ ν΄λΉ κ°μ²΄μ λν μ°Έμ‘°λ₯Ό μ μ§ν μ μκ² ν΄μ€λλ€. `FinalizationRegistry`λ κ°μ²΄κ° κ°λΉμ§ 컬λ μ λ λ μ€νλ μ½λ°±μ λ±λ‘ν μ μκ² ν΄μ€λλ€.
μμ :
const registry = new FinalizationRegistry(heldValue => {
console.log(`Object with value ${heldValue} was garbage collected.`);
});
let obj = { data: 'some data' };
const weakRef = new WeakRef(obj);
registry.register(obj, obj.data); // Register the object with the registry
obj = null; // Remove the strong reference to the object
// At some point in the future, the garbage collector will reclaim the memory used by the object,
// and the callback in the FinalizationRegistry will be executed.
μ¬μ© μ¬λ‘:
- μΊμ κ΄λ¦¬: `WeakRef`λ₯Ό μ¬μ©νμ¬ ν΄λΉ κ°μ²΄κ° λ μ΄μ μ¬μ©λμ§ μμ λ μλμΌλ‘ νλͺ©μ μ κ±°νλ μΊμλ₯Ό ꡬνν μ μμ΅λλ€.
- 리μμ€ μ 리: `FinalizationRegistry`λ₯Ό μ¬μ©νμ¬ κ°μ²΄κ° κ°λΉμ§ 컬λ μ λ λ 리μμ€(μ: νμΌ νΈλ€, λ€νΈμν¬ μ°κ²°)λ₯Ό ν΄μ ν μ μμ΅λλ€.
μ€μ κ³ λ €μ¬ν:
- κ°λΉμ§ 컬λ μ μ λΉκ²°μ μ μ΄λ―λ‘ `FinalizationRegistry` μ½λ°±μ΄ νΉμ μκ°μ μ€νλ κ²μ΄λΌκ³ μμ‘΄ν μ μμ΅λλ€.
- μ½λμ 볡μ‘μ±μ λν μ μμΌλ―λ‘ `WeakRef`μ `FinalizationRegistry`λ λλ¬Όκ² μ¬μ©νμΈμ.
5. μ μ λ³μ νΌνκΈ°
μ μ λ³μλ μλͺ μ΄ κΈΈκ³ μ ν리μΌμ΄μ μ΄ μ’ λ£λ λκΉμ§ κ°λΉμ§ 컬λ μ λμ§ μμ΅λλ€. μΌμμ μΌλ‘λ§ νμν ν° κ°μ²΄λ λ°μ΄ν° ꡬ쑰λ₯Ό μ μ₯νκΈ° μν΄ μ μ λ³μλ₯Ό μ¬μ©νλ κ²μ νΌνμΈμ. λμ , ν¨μλ λͺ¨λ λ΄μ μ§μ λ³μλ₯Ό μ¬μ©νλ©΄ ν΄λΉ μ€μ½νλ₯Ό λ²μ΄λ λ κ°λΉμ§ 컬λ μ λ©λλ€.
μμ :
λμ μ:
// Global variable
let myLargeArray = new Array(1000000).fill('some data');
function processData() {
// ... use myLargeArray
}
processData();
μ’μ μ:
function processData() {
// Local variable
const myLargeArray = new Array(1000000).fill('some data');
// ... use myLargeArray
}
processData();
λ λ²μ§Έ μμ μμ `myLargeArray`λ `processData` λ΄μ μ§μ λ³μμ΄λ―λ‘ `processData` μ€νμ΄ λλλ©΄ κ°λΉμ§ 컬λ μ λ©λλ€.
6. λͺ μμ μΌλ‘ 리μμ€ ν΄μ νκΈ°
μ΄λ€ κ²½μ°μλ λΉλκΈ° μμ μ΄ λ³΄μ νκ³ μλ 리μμ€λ₯Ό λͺ μμ μΌλ‘ ν΄μ ν΄μΌ ν μλ μμ΅λλ€. μλ₯Ό λ€μ΄, λ°μ΄ν°λ² μ΄μ€ μ°κ²°μ΄λ νμΌ νΈλ€μ μ¬μ©νλ κ²½μ°, μμ μ΄ λλλ©΄ λ«μμΌ ν©λλ€. μ΄λ 리μμ€ λμλ₯Ό λ°©μ§νκ³ μ ν리μΌμ΄μ μ μ λ°μ μΈ μμ μ±μ ν₯μμν€λ λ° λμμ΄ λ©λλ€.
μμ :
const fs = require('fs');
async function readFileAsync(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
async function processFile(filePath) {
let fileHandle = null;
try {
fileHandle = await fs.promises.open(filePath, 'r');
const data = await readFileAsync(filePath); // Or fileHandle.readFile()
console.log(data.toString());
} catch (error) {
console.error('Error reading file:', error);
} finally {
if (fileHandle) {
await fileHandle.close(); // Explicitly close the file handle
console.log('File handle closed.');
}
}
}
processFile('myFile.txt');
`finally` λΈλ‘μ νμΌ μ²λ¦¬ μ€ μ€λ₯κ° λ°μνλλΌλ νμΌ νΈλ€μ΄ νμ λ«νλλ‘ λ³΄μ₯ν©λλ€.
7. λΉλκΈ° μ΄ν°λ μ΄ν°μ μ λλ μ΄ν° μ¬μ©νκΈ°
λΉλκΈ° μ΄ν°λ μ΄ν°μ μ λλ μ΄ν°λ λλμ λ°μ΄ν°λ₯Ό λΉλκΈ°μ μΌλ‘ μ²λ¦¬νλ λ ν¨μ¨μ μΈ λ°©λ²μ μ 곡ν©λλ€. λ°μ΄ν°λ₯Ό μ²ν¬(chunk) λ¨μλ‘ μ²λ¦¬ν μ μκ² νμ¬ λ©λͺ¨λ¦¬ μλΉλ₯Ό μ€μ΄κ³ λ°μμ±μ ν₯μμν΅λλ€.
μμ :
async function* generateData() {
for (let i = 0; i < 100; i++) {
await new Promise(resolve => setTimeout(resolve, 10)); // Simulate asynchronous operation
yield i;
}
}
async function processData() {
for await (const item of generateData()) {
console.log(item);
}
}
processData();
μ΄ μμ μμ `generateData` ν¨μλ λ°μ΄ν°λ₯Ό λΉλκΈ°μ μΌλ‘ μμ±(yield)νλ λΉλκΈ° μ λλ μ΄ν°μ λλ€. `processData` ν¨μλ `for await...of` 루νλ₯Ό μ¬μ©νμ¬ μμ±λ λ°μ΄ν°λ₯Ό λ°λ³΅ν©λλ€. μ΄λ₯Ό ν΅ν΄ μ 체 λ°μ΄ν°μ μ΄ ν λ²μ λ©λͺ¨λ¦¬μ λ‘λλλ κ²μ λ°©μ§νκ³ λ°μ΄ν°λ₯Ό μ²ν¬ λ¨μλ‘ μ²λ¦¬ν μ μμ΅λλ€.
8. λΉλκΈ° μμ μ€λ‘νλ§ λ° λλ°μ΄μ±
μ¬μ©μ μ λ ₯ μ²λ¦¬λ APIμμ λ°μ΄ν° κ°μ Έμ€κΈ°μ κ°μ΄ λΉλ²ν λΉλκΈ° μμ μ λ€λ£° λ, μ€λ‘νλ§(throttling)κ³Ό λλ°μ΄μ±(debouncing)μ λ©λͺ¨λ¦¬ μλΉλ₯Ό μ€μ΄κ³ μ±λ₯μ ν₯μμν€λ λ° λμμ΄ λ μ μμ΅λλ€. μ€λ‘νλ§μ ν¨μκ° μ€νλλ λΉλλ₯Ό μ ννλ λ°λ©΄, λλ°μ΄μ±μ λ§μ§λ§ νΈμΆ μ΄ν μΌμ μκ°μ΄ μ§λ λκΉμ§ ν¨μ μ€νμ μ§μ°μν΅λλ€.
μμ (λλ°μ΄μ±):
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
function handleInputChange(event) {
console.log('Input changed:', event.target.value);
// Perform asynchronous operation here (e.g., search API call)
}
const debouncedHandleInputChange = debounce(handleInputChange, 300); // Debounce for 300ms
const inputElement = document.getElementById('myInput');
inputElement.addEventListener('input', debouncedHandleInputChange);
μ΄ μμ μμ `debounce` ν¨μλ `handleInputChange` ν¨μλ₯Ό κ°μλλ€. λλ°μ΄μ±λ ν¨μλ 300λ°λ¦¬μ΄ λμ μλ¬΄λ° νλμ΄ μμ λλ§ μ€νλ©λλ€. μ΄λ κ³Όλν API νΈμΆμ λ°©μ§νκ³ λ©λͺ¨λ¦¬ μλΉλ₯Ό μ€μ λλ€.
9. λΌμ΄λΈλ¬λ¦¬ λλ νλ μμν¬ μ¬μ© κ³ λ €
λ§μ μλ°μ€ν¬λ¦½νΈ λΌμ΄λΈλ¬λ¦¬μ νλ μμν¬λ λΉλκΈ° μμ μ κ΄λ¦¬νκ³ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§νκΈ° μν λ΄μ₯ λ©μ»€λμ¦μ μ 곡ν©λλ€. μλ₯Ό λ€μ΄, 리μ‘νΈ(React)μ useEffect ν μ μ¬μ©νλ©΄ λΆμ ν¨κ³Ό(side effects)λ₯Ό μ½κ² κ΄λ¦¬νκ³ μ»΄ν¬λνΈκ° λ§μ΄νΈ ν΄μ λ λ μ 리ν μ μμ΅λλ€. λ§μ°¬κ°μ§λ‘, μ΅κ·€λ¬(Angular)μ RxJS λΌμ΄λΈλ¬λ¦¬λ λΉλκΈ° λ°μ΄ν° μ€νΈλ¦Όμ μ²λ¦¬νκ³ κ΅¬λ μ κ΄λ¦¬νκΈ° μν κ°λ ₯ν μ°μ°μ μΈνΈλ₯Ό μ 곡ν©λλ€.
μμ (React useEffect):
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
let isMounted = true; // Track component mount state
async function fetchData() {
const response = await fetch('https://example.com/api/data');
const result = await response.json();
if (isMounted) {
setData(result);
}
}
fetchData();
return () => {
// Cleanup function
isMounted = false; // Prevent state updates on unmounted component
// Cancel any pending asynchronous operations here
};
}, []); // Empty dependency array means this effect runs only once on mount
return (
{data ? Data: {data.value}
: Loading...
}
);
}
export default MyComponent;
`useEffect` ν μ μ»΄ν¬λνΈκ° μ¬μ ν λ§μ΄νΈλ κ²½μ°μλ§ μνλ₯Ό μ λ°μ΄νΈνλλ‘ λ³΄μ₯ν©λλ€. μ 리 ν¨μλ `isMounted`λ₯Ό `false`λ‘ μ€μ νμ¬ μ»΄ν¬λνΈκ° λ§μ΄νΈ ν΄μ λ ν λ μ΄μμ μν μ λ°μ΄νΈλ₯Ό λ°©μ§ν©λλ€. μ΄λ λΉλκΈ° μμ μ΄ μ»΄ν¬λνΈκ° νκ΄΄λ νμ μλ£λ λ λ°μν μ μλ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§ν©λλ€.
κ²°λ‘
ν¨μ¨μ μΈ λ©λͺ¨λ¦¬ κ΄λ¦¬λ κ²¬κ³ νκ³ νμ₯ κ°λ₯ν μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° λ§€μ° μ€μνλ©°, νΉν λΉλκΈ° μμ μ λ€λ£° λ λμ± κ·Έλ μ΅λλ€. λΉλκΈ° 컨ν μ€νΈμ 볡μ‘μ±μ μ΄ν΄νκ³ , μ μ¬μ μΈ λ©λͺ¨λ¦¬ λμλ₯Ό μλ³νλ©°, μ΄ κΈμμ μ€λͺ ν μ΅μ ν κΈ°μ μ ꡬνν¨μΌλ‘μ¨ μ ν리μΌμ΄μ μ μ±λ₯κ³Ό μμ μ±μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€. νλ‘νμΌλ§ λꡬλ₯Ό μ¬μ©νκ³ , μ² μ ν μ½λ 리뷰λ₯Ό μννλ©°, `WeakRef` λ° `FinalizationRegistry`μ κ°μ μ΅μ μλ°μ€ν¬λ¦½νΈ κΈ°λ₯μ νμ νμ©νμ¬ μ ν리μΌμ΄μ μ΄ λ©λͺ¨λ¦¬ ν¨μ¨μ μ΄κ³ μ±λ₯μ΄ λ°μ΄λλλ‘ νμμμ€.