IT

🏠 λ©”λͺ¨λ¦¬ λˆ„μˆ˜(Memory Leak) μ‰½κ²Œ μ΄ν•΄ν•˜κΈ°: πŸ–₯ λ‚­λΉ„λ˜λŠ” μ»΄ν“¨ν„°μ˜ κΈ°μ–΅λ ₯ ❌

ν˜„λŒ€μ μΈ ν”„λ‘œκ·Έλž˜λ° ν™˜κ²½μ—μ„œ λ©”λͺ¨λ¦¬ λˆ„μˆ˜(Memory Leak)λŠ” μ—¬μ „νžˆ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ„±λŠ₯ μ €ν•˜μ™€ μΆ©λŒμ„ μΌμœΌν‚€λŠ” μ£Όμš” 원인 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ₯Ό ν•œλ§ˆλ””λ‘œ μ •μ˜ν•˜λ©΄, β€œλ” 이상 ν•„μš”ν•˜μ§€ μ•Šμ€ 데이터가 λ©”λͺ¨λ¦¬μ—μ„œ ν•΄μ œλ˜μ§€ μ•Šκ³  남아 μžˆλŠ” ν˜„μƒβ€μž…λ‹ˆλ‹€.


1️⃣ λ©”λͺ¨λ¦¬ λˆ„μˆ˜λž€ λ¬΄μ—‡μΈκ°€μš”? (μ‰½κ²Œ μ΄ν•΄ν•˜κΈ°)

μ»΄ν“¨ν„°μ˜ λ©”λͺ¨λ¦¬(RAM)λŠ” ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ 데이터λ₯Ό μž„μ‹œλ‘œ μ €μž₯ν•˜λŠ” μž‘μ—… κ³΅κ°„μž…λ‹ˆλ‹€. 이 μž‘μ—… 곡간은 ν•œμ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

  • 정상적인 κ³Όμ •: ν”„λ‘œκ·Έλž¨μ΄ 데이터λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ λ©”λͺ¨λ¦¬λ₯Ό ν• λ‹Ήλ°›κ³ , μ‚¬μš©μ΄ λλ‚˜λ©΄ λ©”λͺ¨λ¦¬λ₯Ό ν•΄μ œν•˜μ—¬ λ‹€λ₯Έ ν”„λ‘œκ·Έλž¨μ΄ μ‚¬μš©ν•  수 μžˆλ„λ‘ λŒλ €μ€λ‹ˆλ‹€.
  • λ©”λͺ¨λ¦¬ λˆ„μˆ˜: 마치 μ‹λ‹Ήμ—μ„œ μ†λ‹˜(데이터)이 식사λ₯Ό 마치고 퇴μž₯ν–ˆμ§€λ§Œ, 쒅업원(ν”„λ‘œκ·Έλž¨)이 ν…Œμ΄λΈ”μ„ μΉ˜μš°μ§€ μ•Šμ•„ λ‹€μŒ μ†λ‹˜(λ‹€λ₯Έ 데이터)이 μžλ¦¬μ— 앉을 수 μ—†κ²Œ λ˜λŠ” 상황과 κ°™μŠ΅λ‹ˆλ‹€.
    • λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ λ°œμƒν•˜λ©΄ ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ μˆ˜λ‘ μ‚¬μš© κ°€λŠ₯ν•œ λ©”λͺ¨λ¦¬κ°€ 점점 μ€„μ–΄λ“­λ‹ˆλ‹€.
    • κ²°κ΅­, μ»΄ν“¨ν„°λŠ” λŠλ €μ§€κ±°λ‚˜, λ©”λͺ¨λ¦¬ λΆ€μ‘±(Out of Memory) 였λ₯˜μ™€ ν•¨κ»˜ ν”„λ‘œκ·Έλž¨ λ˜λŠ” 전체 μ‹œμŠ€ν…œμ΄ μΆ©λŒν•˜κ²Œ λ©λ‹ˆλ‹€.

πŸ“ λ”₯ν•˜κ²Œ: λ©”λͺ¨λ¦¬ λˆ„μˆ˜λŠ” κ°œλ°œμžκ°€ λͺ…μ‹œμ μœΌλ‘œ λ©”λͺ¨λ¦¬λ₯Ό ν•΄μ œν•΄μ•Ό ν•˜λŠ” μ–Έμ–΄(C, C++)μ—μ„œ ν”ν–ˆμ§€λ§Œ, κ°€λΉ„μ§€ 컬렉터(Garbage Collector, GC)κ°€ μžˆλŠ” μ–Έμ–΄(Java, JavaScript, Python λ“±)μ—μ„œλ„ GCκ°€ β€œμ΄ λ°μ΄ν„°λŠ” μ—¬μ „νžˆ ν•„μš”ν•˜λ‹€β€κ³  μ˜€ν•΄ν•˜κ²Œ λ§Œλ“€ λ•Œ λ°œμƒν•©λ‹ˆλ‹€.


2️⃣ πŸ’‘ κ°€λΉ„μ§€ 컬렉터와 λ©”λͺ¨λ¦¬ λˆ„μˆ˜

JavaScript 같은 κ³ κΈ‰ μ–Έμ–΄μ—μ„œλŠ” κ°œλ°œμžκ°€ λ©”λͺ¨λ¦¬ ν•΄μ œμ— λŒ€ν•΄ μ‹ κ²½ μ“Έ ν•„μš”κ°€ 없도둝 κ°€λΉ„μ§€ 컬렉터(GC)λΌλŠ” μžλ™ λ©”λͺ¨λ¦¬ 관리 도ꡬ가 μž‘λ™ν•©λ‹ˆλ‹€.

  • GC의 μ—­ν• : GCλŠ” 주기적으둜 λ©”λͺ¨λ¦¬λ₯Ό κ²€μ‚¬ν•˜μ—¬ β€œλ„λ‹¬ λΆˆκ°€λŠ₯ν•œ 객체(unreachable objects)” (즉, ν”„λ‘œκ·Έλž¨ μ½”λ“œ μ–΄λ””μ—μ„œλ„ μ°Έμ‘°ν•  수 μ—†μ–΄ 더 이상 μ‚¬μš©λ  κ°€λŠ₯성이 μ—†λŠ” 객체)λ₯Ό μ°Ύμ•„ λ©”λͺ¨λ¦¬μ—μ„œ μžλ™μœΌλ‘œ μ œκ±°ν•©λ‹ˆλ‹€.
  • λˆ„μˆ˜μ˜ 원인: λ©”λͺ¨λ¦¬ λˆ„μˆ˜λŠ” GCκ°€ 객체λ₯Ό ν•΄μ œν•˜μ§€ λͺ»ν•  λ•Œ λ°œμƒν•©λ‹ˆλ‹€. μ΄λŠ” ν”„λ‘œκ·Έλž¨μ˜ μ–΄λ”˜κ°€μ—μ„œ ν•΄λ‹Ή 객체λ₯Ό μ‹€μˆ˜λ‘œ 계속 μ°Έμ‘°(reference)ν•˜κ³  있기 λ•Œλ¬Έμž…λ‹ˆλ‹€. GCλŠ” κ·Έ 객체가 β€œμ—¬μ „νžˆ 도달 κ°€λŠ₯ν•˜λ‹€β€κ³  νŒλ‹¨ν•˜μ—¬ μ‚­μ œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

3️⃣ πŸ–₯ JavaScriptμ—μ„œ ν”ν•œ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ μ˜ˆμ‹œ 3κ°€μ§€

JavaScript μ—”μ§„(예: V8 μ—”μ§„)은 Mark-and-Sweep λ“±μ˜ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜μ—¬ GCλ₯Ό μˆ˜ν–‰ν•©λ‹ˆλ‹€. λ‹€μŒμ€ 이 GCλ₯Ό λ°©ν•΄ν•˜λŠ” λŒ€ν‘œμ μΈ νŒ¨ν„΄μž…λ‹ˆλ‹€.

1. μ „μ—­ λ³€μˆ˜ (Global Variables)

μ˜λ„μΉ˜ μ•Šκ²Œ λ³€μˆ˜λ₯Ό μ „μ—­ μŠ€μ½”ν”„μ— μ„ μ–Έν•˜κ±°λ‚˜, varλ‚˜ let/const 없이 λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œ λ°œμƒν•©λ‹ˆλ‹€. μ „μ—­ 객체(λΈŒλΌμš°μ €μ—μ„œλŠ” window 객체)에 ν•œ 번 λ“±λ‘λœ λ³€μˆ˜λŠ” ν”„λ‘œκ·Έλž¨μ΄ 끝날 λ•ŒκΉŒμ§€ GC의 λŒ€μƒμ΄ λ˜μ§€ μ•ŠμœΌλ―€λ‘œ, 큰 객체λ₯Ό 여기에 μ €μž₯ν•˜λ©΄ λˆ„μˆ˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

JavaScript

function createGlobalLeak() {
    // let, const, var ν‚€μ›Œλ“œ 없이 μ„ μ–Έν•˜λ©΄ μ „μ—­ 객체(window)의 속성이 λ©λ‹ˆλ‹€.
    // μ΄λŠ” μ˜λ„μΉ˜ μ•Šκ²Œ μ „μ—­ 객체λ₯Ό μ˜€μ—Όμ‹œν‚€κ³  λ©”λͺ¨λ¦¬μ—μ„œ ν•΄μ œλ˜μ§€ μ•Šκ²Œ ν•©λ‹ˆλ‹€.
    leakyData = new Array(1000000).fill('leak'); 
}
// leakyDataλŠ” ν•¨μˆ˜κ°€ μ’…λ£Œλœ 후에도 window.leakyData둜 계속 μ°Έμ‘°λ©λ‹ˆλ‹€.

2. 이벀트 λ¦¬μŠ€λ„ˆ (Event Listeners)

DOM μš”μ†Œμ— 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μΆ”κ°€ν–ˆμ§€λ§Œ, λ‚˜μ€‘μ— κ·Έ DOM μš”μ†Œ 자체λ₯Ό μ œκ±°ν•  λ•Œ λ¦¬μŠ€λ„ˆλ₯Ό ν•΄μ œν•˜μ§€ μ•Šμ•„ λ°œμƒν•©λ‹ˆλ‹€.

  • 문제: DOM μš”μ†ŒλŠ” μ œκ±°λ˜μ—ˆμ§€λ§Œ, 이벀트 ν•Έλ“€λŸ¬(콜백 ν•¨μˆ˜)λŠ” μ—¬μ „νžˆ DOM μš”μ†Œλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ, 이 ν•Έλ“€λŸ¬ μžμ²΄λ„ window 객체와 같은 μƒμœ„ 객체에 μ˜ν•΄ 참쑰될 수 μžˆμŠ΅λ‹ˆλ‹€.
  • ν•΄κ²°: μš”μ†Œλ₯Ό μ œκ±°ν•˜κΈ° 전에 λ°˜λ“œμ‹œ removeEventListenerλ₯Ό μ‚¬μš©ν•˜μ—¬ λ¦¬μŠ€λ„ˆλ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ œκ±°ν•΄μ•Ό ν•©λ‹ˆλ‹€.

JavaScript

const button = document.getElementById('myButton');
const dataStore = {}; // 큰 데이터가 μžˆλ‹€κ³  κ°€μ •

button.addEventListener('click', function onClick() {
    // 이 콜백 ν•¨μˆ˜λŠ” dataStore 객체λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
    console.log(dataStore.value); 
});

// λ§Œμ•½ λ‚˜μ€‘μ— button μš”μ†Œλ₯Ό DOMμ—μ„œ μ œκ±°ν•΄λ„, onClick ν•¨μˆ˜μ™€ 
// κ·Έ ν•¨μˆ˜κ°€ μ°Έμ‘°ν•˜λŠ” dataStoreλŠ” μ—¬μ „νžˆ λ©”λͺ¨λ¦¬μ— 남아 λˆ„μˆ˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.
// ❌ ν•΄κ²°μ±…: button.removeEventListener('click', onClick);

3. 타이머 및 μΈν„°λ²Œ (Timers and Intervals)

setInterval λ˜λŠ” setTimeout이 μ„€μ •λ˜μ—ˆμ§€λ§Œ, λ‚˜μ€‘μ— λͺ…μ‹œμ μœΌλ‘œ ν•΄μ œλ˜μ§€ μ•Šμ€ κ²½μš°μ— λ°œμƒν•©λ‹ˆλ‹€.

  • 문제: 콜백 ν•¨μˆ˜κ°€ 싀행을 κΈ°λ‹€λ¦¬λŠ” λ™μ•ˆ, ν•΄λ‹Ή ν•¨μˆ˜κ°€ μ°Έμ‘°ν•˜λŠ” λͺ¨λ“  μ™ΈλΆ€ λ³€μˆ˜(ν΄λ‘œμ €)λŠ” GC λŒ€μƒμ—μ„œ μ œμ™Έλ©λ‹ˆλ‹€. μΈν„°λ²Œμ΄ λ¬΄ν•œμ • 반볡되면 λˆ„μˆ˜κ°€ κ³„μ†λ©λ‹ˆλ‹€.
  • ν•΄κ²°: μž‘μ—…μ΄ λλ‚˜λ©΄ λ°˜λ“œμ‹œ clearIntervalμ΄λ‚˜ clearTimeout을 μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

JavaScript

let count = 0;
// 큰 객체λ₯Ό μ°Έμ‘°ν•˜λŠ” ν΄λ‘œμ €λ₯Ό ν¬ν•¨ν•œ μΈν„°λ²Œ
const bigData = new Array(10000).fill('heavy'); 

const intervalId = setInterval(() => {
    count++;
    // 이 ν•¨μˆ˜λŠ” bigDataλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆμ–΄, bigDataλŠ” GC λŒ€μƒμ΄ 될 수 μ—†μŠ΅λ‹ˆλ‹€.
    console.log(count, bigData.length);
}, 1000);

// 이 μ½”λ“œκ°€ μ‹€ν–‰λ˜μ§€ μ•ŠμœΌλ©΄, bigDataλŠ” λ©”λͺ¨λ¦¬μ—μ„œ ν•΄μ œλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
// ❌ ν•΄κ²°μ±…: clearInterval(intervalId);

4️⃣ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ λ°©μ§€ 팁 및 κ²°λ‘ 

λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ₯Ό λ°©μ§€ν•˜λŠ” κ°€μž₯ 쒋은 방법은 β€œν•„μš” μ—†λŠ” μ°Έμ‘°λŠ” μ¦‰μ‹œ λŠμ–΄μ£ΌλŠ” κ²ƒβ€μž…λ‹ˆλ‹€.

  1. λ³€μˆ˜ μŠ€μ½”ν”„ 관리: 항상 let λ˜λŠ” constλ₯Ό μ‚¬μš©ν•˜κ³ , μ „μ—­ λ³€μˆ˜ μ‚¬μš©μ„ μ΅œμ†Œν™”ν•©λ‹ˆλ‹€.
  2. 이벀트/타이머 정리: 이벀트 λ¦¬μŠ€λ„ˆ, setInterval, setTimeout을 μ„€μ •ν–ˆλ‹€λ©΄, ν•΄λ‹Ή μž‘μ—…μ΄ 끝날 λ•Œ removeEventListener λ˜λŠ” clearInterval/clearTimeout을 톡해 λ°˜λ“œμ‹œ ν•΄μ œν•©λ‹ˆλ‹€.
  3. WeakMap/WeakSet μ‚¬μš©: 객체 μ°Έμ‘°κ°€ λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ₯Ό μΌμœΌν‚¬ λ•Œ, WeakMapμ΄λ‚˜ WeakSet을 μ‚¬μš©ν•˜λ©΄ ν‚€κ°€ GC λŒ€μƒμ΄ 될 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” β€œμ•½ν•œ 참쑰”λ₯Ό μƒμ„±ν•˜μ—¬ GCκ°€ 객체λ₯Ό μ œκ±°ν•˜λŠ” 것을 λ°©ν•΄ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ©”λͺ¨λ¦¬ λˆ„μˆ˜λŠ” λ‹Ήμž₯ λˆˆμ— 띄지 μ•Šμ§€λ§Œ, μž₯μ‹œκ°„ μ‹€ν–‰λ˜λŠ” μ„œλΉ„μŠ€λ‚˜ νŠΈλž˜ν”½μ΄ λ§Žμ€ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” 치λͺ…적인 μ„±λŠ₯ 문제λ₯Ό μΌμœΌν‚΅λ‹ˆλ‹€. 주기적인 ν”„λ‘œνŒŒμΌλ§ 툴(예: Chrome 개발자 λ„κ΅¬μ˜ Performance, Memory νƒ­)을 μ‚¬μš©ν•˜μ—¬ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ λͺ¨λ‹ˆν„°λ§ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.

infodori1234

Recent Posts

πŸ–₯ NetBIOS over TCP IP NBT μ™„μ „ κ°€μ΄λ“œ

둜컬 λ„€νŠΈμ›Œν¬ ν™˜κ²½μ„ μ‘°κΈˆμ΄λΌλ„ 닀뀄본 μ‚¬λžŒμ΄λΌλ©΄ ν•œ λ²ˆμ―€μ€ λ§ˆμ£ΌμΉ˜λŠ” μ΅μˆ™ν•œ 단어가 μžˆμŠ΅λ‹ˆλ‹€. λ°”λ‘œ NetBIOS와 NBTμž…λ‹ˆλ‹€.…

2κ°œμ›” ago

🏠 JSON Schema: 데이터 μœ νš¨μ„± κ²€μ¦μ˜ ν‘œμ€€ 섀계도 πŸ–₯

μ•ˆλ…•ν•˜μ„Έμš”! ν˜„λŒ€ μ›Ή κ°œλ°œμ—μ„œ 데이터 κ΅ν™˜μ˜ 핡심인 JSON(JavaScript Object Notation)을 λ”μš± κ°•λ ₯ν•˜κ³  μ•ˆμ •μ μœΌλ‘œ λ§Œλ“€μ–΄μ£ΌλŠ” 도ꡬ,…

2κ°œμ›” ago

🏠 ECMAScript 3 ν˜Έν™˜μ„± μ™„μ „ 정리 κ°€μ΄λ“œ

❌ ECMAScript 3(E3)λž€ λ¬΄μ—‡μΌκΉŒ ECMAScript 3λŠ” 1999년에 κ³΅μ‹ν™”λœ μžλ°”μŠ€ν¬λ¦½νŠΈ ν‘œμ€€μ΄λ‹€. μ§€κΈˆ 보면 였래된 기술 κ°™μ§€λ§Œ,…

2κ°œμ›” ago

πŸ–₯ CoffeeScript μ™„μ „ κ°€μ΄λ“œ

CoffeeScriptλŠ” ν•œλ•Œ ν”„λ‘ νŠΈμ—”λ“œ 개발 μƒνƒœκ³„μ—μ„œ 맀우 인기 μžˆμ—ˆλ˜ μ–Έμ–΄μ˜€κ³ , μ§€κΈˆλ„ νŠΉμ • ν”„λ‘œμ νŠΈλ‚˜ λ ˆκ±°μ‹œ μ‹œμŠ€ν…œ, κ°„κ²°ν•œ…

2κ°œμ›” ago

πŸ–₯️ λΈŒλΌμš°μ € λ Œλ”λ§ κ³Όμ • (CRP) : μ›ΉνŽ˜μ΄μ§€κ°€ λˆˆμ•žμ— λ‚˜νƒ€λ‚˜κΈ°κΉŒμ§€μ˜ λ§ˆλ²•

(Critical Rendering Path, 핡심 λ Œλ”λ§ 경둜 μ™„λ²½ 이해) μ›Ή λΈŒλΌμš°μ €μ— μ£Όμ†Œλ₯Ό μž…λ ₯ν•˜κ³  μ—”ν„°λ₯Ό λˆ„λ₯΄λŠ” μˆœκ°„,…

3κ°œμ›” ago

πŸ›‘ CORS 였λ₯˜ 원리 μ™„λ²½ ν•΄μ„€: λΈŒλΌμš°μ € λ³΄μ•ˆμ˜ ν•„μˆ˜ κ΄€λ¬Έ! πŸ›‘οΈ

μ›Ή κ°œλ°œμ„ ν•˜λ‹€ 보면 λˆ„κ΅¬λ‚˜ ν•œ 번쯀 뢉은색 κΈ€μ”¨μ˜ CORS 였λ₯˜(Cross-Origin Resource Sharing Error)λ₯Ό λ§Œλ‚˜κ²Œ…

3κ°œμ›” ago