μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μ μ΅κ³ μ±λ₯μ μ΄λμ΄λ΄μΈμ. μ΄ μ’ ν© κ°μ΄λλ λͺ¨λ λ©λͺ¨λ¦¬ κ΄λ¦¬, κ°λΉμ§ 컬λ μ , κ·Έλ¦¬κ³ κΈλ‘λ² κ°λ°μλ₯Ό μν λͺ¨λ² μ¬λ‘λ₯Ό νꡬν©λλ€.
λ©λͺ¨λ¦¬ λ§μ€ν°νκΈ°: μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ©λͺ¨λ¦¬ κ΄λ¦¬μ κ°λΉμ§ 컬λ μ μ λν κΈλ‘λ² μ¬μΈ΅ λΆμ
κ΄λνκ³ μνΈ μ°κ²°λ μννΈμ¨μ΄ κ°λ°μ μΈκ³μμ μλ°μ€ν¬λ¦½νΈλ 보νΈμ μΈ μΈμ΄λ‘μ, μΈν°λν°λΈν μΉ κ²½νλΆν° κ²¬κ³ ν μλ² μ¬μ΄λ μ ν리μΌμ΄μ , μ¬μ§μ΄ μλ² λλ μμ€ν μ μ΄λ₯΄κΈ°κΉμ§ λͺ¨λ κ²μ ꡬλν©λλ€. μ΄λ¬ν 보νΈμ±μ μλ°μ€ν¬λ¦½νΈμ ν΅μ¬ λ©μ»€λμ¦, νΉν λ©λͺ¨λ¦¬ κ΄λ¦¬ λ°©μμ μ΄ν΄νλ κ²μ΄ λ¨μν κΈ°μ μ μΈ μΈλΆ μ¬νμ΄ μλλΌ μ μΈκ³ κ°λ°μμκ² μ€μν κΈ°μ μμ μλ―Έν©λλ€. ν¨μ¨μ μΈ λ©λͺ¨λ¦¬ κ΄λ¦¬λ μ¬μ©μμ μμΉλ μ₯μΉμ κ΄κ³μμ΄ λ λΉ λ₯Έ μ ν리μΌμ΄μ , λ λμ μ¬μ©μ κ²½ν, 리μμ€ μλΉ κ°μ, μ΄μ λΉμ© μ κ°μΌλ‘ μ§μ μ΄μ΄μ§λλ€.
μ΄ μ’ ν© κ°μ΄λλ μλ°μ€ν¬λ¦½νΈμ 볡μ‘ν λ©λͺ¨λ¦¬ κ΄λ¦¬ μΈκ³λ‘ μ¬λ¬λΆμ μλ΄ν κ²μ΄λ©°, νΉν λͺ¨λμ΄ μ΄ κ³Όμ μ λ―ΈμΉλ μν₯κ³Ό μλ κ°λΉμ§ 컬λ μ (GC) μμ€ν μ΄ μλνλ λ°©μμ μ€μ μ λ κ²μ λλ€. μ°λ¦¬λ μΌλ°μ μΈ ν¨μ , λͺ¨λ² μ¬λ‘, κ·Έλ¦¬κ³ κΈλ‘λ² μ¬μ©μλ₯Ό μν κ³ μ±λ₯μ μμ μ μ΄λ©° λ©λͺ¨λ¦¬ ν¨μ¨μ μΈ μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ μ ꡬμΆνλ λ° λμμ΄ λ κ³ κΈ κΈ°μ λ€μ νꡬν κ²μ λλ€.
μλ°μ€ν¬λ¦½νΈ λ°νμ νκ²½κ³Ό λ©λͺ¨λ¦¬ κΈ°μ΄
κ°λΉμ§ 컬λ μ μ λν΄ μμΈν μμ보기 μ μ, λ³Έμ§μ μΌλ‘ κ³ μμ€ μΈμ΄μΈ μλ°μ€ν¬λ¦½νΈκ° λ©λͺ¨λ¦¬μ κ·Όλ³Έμ μΈ μμ€μμ μ΄λ»κ² μνΈ μμ©νλμ§ μ΄ν΄νλ κ²μ΄ μ€μν©λλ€. κ°λ°μκ° μλμΌλ‘ λ©λͺ¨λ¦¬λ₯Ό ν λΉνκ³ ν΄μ νλ μ μμ€ μΈμ΄μ λ¬λ¦¬, μλ°μ€ν¬λ¦½νΈλ μ΄λ¬ν 볡μ‘μ±μ λλΆλΆμ μΆμννκ³ μμ§(Chrome λ° Node.jsμ V8, Firefoxμ SpiderMonkey, Safariμ JavaScriptCore λ±)μ μμ‘΄νμ¬ μ΄λ¬ν μμ μ μ²λ¦¬ν©λλ€.
μλ°μ€ν¬λ¦½νΈκ° λ©λͺ¨λ¦¬λ₯Ό μ²λ¦¬νλ λ°©λ²
μλ°μ€ν¬λ¦½νΈ νλ‘κ·Έλ¨μ μ€ννλ©΄ μμ§μ λ κ°μ§ μ£Όμ μμμ λ©λͺ¨λ¦¬λ₯Ό ν λΉν©λλ€:
- μ½ μ€ν(The Call Stack): μ«μ, λΆλ¦¬μΈ, null, undefined, μ¬λ³Ό, bigint, λ¬Έμμ΄κ³Ό κ°μ μμ κ°κ³Ό κ°μ²΄μ λν μ°Έμ‘°κ° μ μ₯λλ κ³³μ λλ€. νμ μ μΆ(LIFO) μμΉμ λ°λΌ μλνλ©° ν¨μ μ€ν 컨ν μ€νΈλ₯Ό κ΄λ¦¬ν©λλ€. ν¨μκ° νΈμΆλλ©΄ μλ‘μ΄ νλ μμ΄ μ€νμ νΈμλκ³ , ν¨μκ° λ°νλλ©΄ νλ μμ΄ νλμ΄ κ΄λ ¨ λ©λͺ¨λ¦¬κ° μ¦μ νμλ©λλ€.
- ν(The Heap): κ°μ²΄, λ°°μ΄, ν¨μ, λͺ¨λκ³Ό κ°μ μ°Έμ‘° κ°μ΄ μ μ₯λλ κ³³μ λλ€. μ€νκ³Ό λ¬λ¦¬ νμ λ©λͺ¨λ¦¬λ λμ μΌλ‘ ν λΉλλ©° μ격ν LIFO μμλ₯Ό λ°λ₯΄μ§ μμ΅λλ€. κ°μ²΄λ μμ μ κ°λ¦¬ν€λ μ°Έμ‘°κ° μλ ν κ³μ μ‘΄μ¬ν μ μμ΅λλ€. νμ λ©λͺ¨λ¦¬λ ν¨μκ° λ°νλ λ μλμΌλ‘ ν΄μ λμ§ μμΌλ©°, λμ κ°λΉμ§ 컬λ ν°μ μν΄ κ΄λ¦¬λ©λλ€.
μ΄ μ°¨μ΄μ μ μ΄ν΄νλ κ²μ λ§€μ° μ€μν©λλ€. μ€νμ μμ κ°μ κ°λ¨νκ³ λΉ λ₯΄κ² κ΄λ¦¬λμ§λ§, νμ 볡μ‘ν κ°μ²΄λ κ·Έ μλͺ μ£ΌκΈ° κ΄λ¦¬λ₯Ό μν΄ λ μ κ΅ν λ©μ»€λμ¦μ΄ νμν©λλ€.
νλ μλ°μ€ν¬λ¦½νΈμμ λͺ¨λμ μν
νλ μλ°μ€ν¬λ¦½νΈ κ°λ°μ μ½λλ₯Ό μ¬μ¬μ© κ°λ₯νκ³ μΊ‘μνλ λ¨μλ‘ κ΅¬μ±νκΈ° μν΄ λͺ¨λμ ν¬κ² μμ‘΄ν©λλ€. λΈλΌμ°μ λ Node.jsμμ ES λͺ¨λ(import/export)μ μ¬μ©νλ , ꡬν Node.js νλ‘μ νΈμμ CommonJS(require/module.exports)λ₯Ό μ¬μ©νλ , λͺ¨λμ μ°λ¦¬κ° μ€μ½νμ κ·Έμ λ°λ₯Έ λ©λͺ¨λ¦¬ κ΄λ¦¬μ λν΄ μκ°νλ λ°©μμ κ·Όλ³Έμ μΌλ‘ λ°κΏλλ€.
- μΊ‘μν: κ° λͺ¨λμ μΌλ°μ μΌλ‘ μ체 μ΅μμ μ€μ½νλ₯Ό κ°μ§λλ€. λͺ¨λ λ΄μμ μ μΈλ λ³μμ ν¨μλ λͺ μμ μΌλ‘ λ΄λ³΄λ΄μ§ μλ ν ν΄λΉ λͺ¨λμ λ‘컬μ λλ€. μ΄λ ꡬν μλ°μ€ν¬λ¦½νΈ ν¨λ¬λ€μμμ νν λ©λͺ¨λ¦¬ λ¬Έμ μ μμΈμ΄μλ μ°λ°μ μΈ μ μ λ³μ μ€μΌ κ°λ₯μ±μ ν¬κ² μ€μ¬μ€λλ€.
- 곡μ μν: λͺ¨λμ΄ κ³΅μ μν(μ: μ€μ κ°μ²΄, μΊμ)λ₯Ό μμ νλ κ°μ²΄λ ν¨μλ₯Ό λ΄λ³΄λ΄λ©΄, μ΄λ₯Ό κ°μ Έμ€λ λ€λ₯Έ λͺ¨λ λͺ¨λμ ν΄λΉ κ°μ²΄μ λμΌν μΈμ€ν΄μ€λ₯Ό 곡μ νκ² λ©λλ€. μ’ μ’ μ±κΈν€κ³Ό μ μ¬ν μ΄ ν¨ν΄μ κ°λ ₯ν μ μμ§λ§, μ μ€νκ² κ΄λ¦¬νμ§ μμΌλ©΄ λ©λͺ¨λ¦¬ μ 보μ μμΈμ΄ λ μλ μμ΅λλ€. 곡μ κ°μ²΄λ μ ν리μΌμ΄μ μ μ΄λ€ λͺ¨λμ΄λ λΆλΆμ΄λ ν΄λΉ κ°μ²΄μ λν μ°Έμ‘°λ₯Ό κ°μ§κ³ μλ ν λ©λͺ¨λ¦¬μ λ¨μ μμ΅λλ€.
- λͺ¨λ μλͺ μ£ΌκΈ°: λͺ¨λμ μΌλ°μ μΌλ‘ ν λ²λ§ λ‘λλκ³ μ€νλ©λλ€. κ·Έλ° λ€μ λ΄λ³΄λΈ κ°μ μΊμλ©λλ€. μ΄λ λͺ¨λ λ΄μ μ€λ μ§μλλ λ°μ΄ν° ꡬ쑰λ μ°Έμ‘°κ° λͺ μμ μΌλ‘ nullλ‘ λ§λ€κ±°λ λ€λ₯Έ λ°©μμΌλ‘ λλ¬ν μ μκ² λ§λ€μ§ μλ ν μ ν리μΌμ΄μ μ μλͺ λμ μ§μλλ€λ κ²μ μλ―Έν©λλ€.
λͺ¨λμ ꡬ쑰λ₯Ό μ 곡νκ³ λ§μ μ ν΅μ μΈ μ μ μ€μ½ν λμλ₯Ό λ°©μ§νμ§λ§, νΉν 곡μ μνμ λͺ¨λ μ€μ½ν λ³μμ μ§μμ±κ³Ό κ΄λ ¨νμ¬ μλ‘μ΄ κ³ λ € μ¬νμ λμ ν©λλ€.
μλ°μ€ν¬λ¦½νΈμ μλ κ°λΉμ§ 컬λ μ μ΄ν΄νκΈ°
μλ°μ€ν¬λ¦½νΈλ μλ λ©λͺ¨λ¦¬ ν΄μ λ₯Ό νμ©νμ§ μκΈ° λλ¬Έμ, λ μ΄μ νμνμ§ μμ κ°μ²΄κ° μ°¨μ§νλ λ©λͺ¨λ¦¬λ₯Ό μλμΌλ‘ νμνκΈ° μν΄ κ°λΉμ§ 컬λ ν°(GC)μ μμ‘΄ν©λλ€. GCμ λͺ©νλ μ€ν μ€μΈ νλ‘κ·Έλ¨μμ λ μ΄μ μ κ·Όν μ μλ "λλ¬ν μ μλ" κ°μ²΄λ₯Ό μλ³νκ³ κ·Έλ€μ΄ μλΉνλ λ©λͺ¨λ¦¬λ₯Ό ν΄μ νλ κ²μ λλ€.
κ°λΉμ§ 컬λ μ (GC)μ΄λ 무μμΈκ°?
κ°λΉμ§ 컬λ μ μ μ ν리μΌμ΄μ μμ λ μ΄μ μ°Έμ‘°λμ§ μλ κ°μ²΄κ° μ°¨μ§νλ λ©λͺ¨λ¦¬λ₯Ό νμνλ €λ μλ λ©λͺ¨λ¦¬ κ΄λ¦¬ νλ‘μΈμ€μ λλ€. μ΄λ λ©λͺ¨λ¦¬ λμλ₯Ό λ°©μ§νκ³ μ ν리μΌμ΄μ μ΄ ν¨μ¨μ μΌλ‘ μλνλ λ° μΆ©λΆν λ©λͺ¨λ¦¬λ₯Ό ν보νλλ‘ λ³΄μ₯ν©λλ€. νλ μλ°μ€ν¬λ¦½νΈ μμ§μ μ ν리μΌμ΄μ μ±λ₯μ λ―ΈμΉλ μν₯μ μ΅μννλ©΄μ μ΄λ₯Ό λ¬μ±νκΈ° μν΄ μ κ΅ν μκ³ λ¦¬μ¦μ μ¬μ©ν©λλ€.
Mark-and-Sweep μκ³ λ¦¬μ¦: νλ GCμ κ·Όκ°
νλ μλ°μ€ν¬λ¦½νΈ μμ§(V8 λ±)μμ κ°μ₯ λ리 μ±νλ κ°λΉμ§ 컬λ μ μκ³ λ¦¬μ¦μ Mark-and-Sweep(νμνκ³ μΈκΈ°)μ λ³νμ λλ€. μ΄ μκ³ λ¦¬μ¦μ λ κ°μ§ μ£Όμ λ¨κ³λ‘ μλν©λλ€:
-
νμ(Mark) λ¨κ³: GCλ "루νΈ(roots)" μ§ν©μμ μμν©λλ€. 루νΈλ νμ± μνλ‘ μλ €μ Έ μμ΄ κ°λΉμ§ 컬λ μ
λ μ μλ κ°μ²΄λ€μ
λλ€. μ¬κΈ°μλ λ€μμ΄ ν¬ν¨λ©λλ€:
- μ μ κ°μ²΄ (μ: λΈλΌμ°μ μ
window, Node.jsμglobal). - νμ¬ μ½ μ€νμ μλ κ°μ²΄ (μ§μ λ³μ, ν¨μ λ§€κ°λ³μ).
- νμ± ν΄λ‘μ .
- μ μ κ°μ²΄ (μ: λΈλΌμ°μ μ
- μΈκΈ°(Sweep) λ¨κ³: νμ λ¨κ³κ° μλ£λλ©΄ GCλ μ 체 νμ μνν©λλ€. μ΄μ λ¨κ³μμ *νμλμ§ μμ* λͺ¨λ κ°μ²΄λ μ ν리μΌμ΄μ μ 루νΈμμ λ μ΄μ λλ¬ν μ μκΈ° λλ¬Έμ "μ£½μ" λλ "κ°λΉμ§"λ‘ κ°μ£Όλ©λλ€. μ΄λ¬ν νμλμ§ μμ κ°μ²΄κ° μ°¨μ§νλ λ©λͺ¨λ¦¬λ νμλμ΄ ν₯ν ν λΉμ μν΄ μμ€ν μ λ°νλ©λλ€.
κ°λ μ μΌλ‘λ κ°λ¨νμ§λ§, νλ GC ꡬνμ ν¨μ¬ λ 볡μ‘ν©λλ€. μλ₯Ό λ€μ΄ V8μ μΈλλ³ μ κ·Ό λ°©μμ μ¬μ©νμ¬ νμ μ¬λ¬ μΈλ(Young Generation λ° Old Generation)λ‘ λλμ΄ κ°μ²΄μ μλͺ μ λ°λΌ μμ§ λΉλλ₯Ό μ΅μ νν©λλ€. λν μ¦λΆ λ° λμ GCλ₯Ό μ¬μ©νμ¬ μμ§ νλ‘μΈμ€μ μΌλΆλ₯Ό λ©μΈ μ€λ λμ λ³λ ¬λ‘ μνν¨μΌλ‘μ¨ μ¬μ©μ κ²½νμ μν₯μ μ€ μ μλ "stop-the-world"(μ€ν μ€λ¨) μΌμ μ μ§λ₯Ό μ€μ λλ€.
μ°Έμ‘° μΉ΄μ΄ν μ΄ λ리 μ¬μ©λμ§ μλ μ΄μ
μ°Έμ‘° μΉ΄μ΄ν (Reference Counting)μ΄λΌλ λ μ€λλκ³ κ°λ¨ν GC μκ³ λ¦¬μ¦μ κ°μ²΄λ₯Ό κ°λ¦¬ν€λ μ°Έμ‘°μ μλ₯Ό μΆμ ν©λλ€. μΉ΄μ΄νΈκ° 0μΌλ‘ λ¨μ΄μ§λ©΄ ν΄λΉ κ°μ²΄λ κ°λΉμ§λ‘ κ°μ£Όλ©λλ€. μ§κ΄μ μ΄μ§λ§ μ΄ λ°©λ²μλ μΉλͺ μ μΈ κ²°ν¨μ΄ μμ΅λλ€: μν μ°Έμ‘°λ₯Ό κ°μ§νκ³ μμ§ν μ μμ΅λλ€. κ°μ²΄ Aκ° κ°μ²΄ Bλ₯Ό μ°Έμ‘°νκ³ κ°μ²΄ Bκ° κ°μ²΄ Aλ₯Ό μ°Έμ‘°νλ κ²½μ°, λ κ°μ²΄κ° μ ν리μΌμ΄μ μ 루νΈμμ λλ¬ν μ μλλΌλ μ°Έμ‘° μΉ΄μ΄νΈλ μ λ 0μΌλ‘ λ¨μ΄μ§μ§ μμ΅λλ€. μ΄λ λ©λͺ¨λ¦¬ λμλ‘ μ΄μ΄μ Έ, μ£Όλ‘ Mark-and-Sweepμ μ¬μ©νλ νλ μλ°μ€ν¬λ¦½νΈ μμ§μλ λΆμ ν©ν©λλ€.
μλ°μ€ν¬λ¦½νΈ λͺ¨λμ λ©λͺ¨λ¦¬ κ΄λ¦¬ λ¬Έμ
μλ κ°λΉμ§ 컬λ μ μ΄ μμμλ λΆκ΅¬νκ³ μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μμλ μ’ μ’ λͺ¨λ ꡬ쑰 λ΄μμ λ―Έλ¬νκ² λ©λͺ¨λ¦¬ λμκ° λ°μν μ μμ΅λλ€. λ©λͺ¨λ¦¬ λμλ λ μ΄μ νμνμ§ μμ κ°μ²΄κ° μ¬μ ν μ°Έμ‘°λμ΄ GCκ° ν΄λΉ λ©λͺ¨λ¦¬λ₯Ό νμνμ§ λͺ»νκ² ν λ λ°μν©λλ€. μκ°μ΄ μ§λ¨μ λ°λΌ μ΄λ¬ν μμ§λμ§ μμ κ°μ²΄λ€μ΄ μΆμ λμ΄ λ©λͺ¨λ¦¬ μλΉ μ¦κ°, μ±λ₯ μ ν, κ·Έλ¦¬κ³ κ²°κ΅μλ μ ν리μΌμ΄μ μΆ©λλ‘ μ΄μ΄μ§λλ€.
μ μ μ€μ½ν λμ vs. λͺ¨λ μ€μ½ν λμ
ꡬν μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ
μ μ°λ°μ μΈ μ μ λ³μ λμ(μ: var/let/constλ₯Ό μκ³ μ μ κ°μ²΄μ μμμ μΌλ‘ μμ±μ μμ±νλ κ²½μ°)μ μ·¨μ½νμ΅λλ€. λͺ¨λμ μ€κ³μ μ체 λ μ컬 μ€μ½νλ₯Ό μ 곡νμ¬ μ΄λ₯Ό λλΆλΆ μνν©λλ€. κ·Έλ¬λ λͺ¨λ μ€μ½ν μ체λ μ μ€νκ² κ΄λ¦¬νμ§ μμΌλ©΄ λμμ μμΈμ΄ λ μ μμ΅λλ€.
μλ₯Ό λ€μ΄, μ΄λ€ λͺ¨λμ΄ ν° λ΄λΆ λ°μ΄ν° ꡬ쑰μ λν μ°Έμ‘°λ₯Ό κ°μ§ ν¨μλ₯Ό λ΄λ³΄λ΄κ³ , κ·Έ ν¨μκ° μ ν리μΌμ΄μ μ μ€λ μ§μλλ λΆλΆμμ κ°μ Έμ μ¬μ©λλ€λ©΄, ν΄λΉ λͺ¨λμ λ€λ₯Έ ν¨μλ€μ΄ λ μ΄μ νλ°ν μ¬μ©λμ§ μλλΌλ λ΄λΆ λ°μ΄ν° ꡬ쑰λ μ λ ν΄μ λμ§ μμ μ μμ΅λλ€.
// cacheModule.js
let internalCache = {};
export function setCache(key, value) {
internalCache[key] = value;
}
export function getCache(key) {
return internalCache[key];
}
// If 'internalCache' grows indefinitely and nothing clears it,
// it can become a memory leak, especially since this module
// might be imported by a long-lived part of the app.
// The 'internalCache' is module-scoped and persists.
ν΄λ‘μ μ λ©λͺ¨λ¦¬ μν₯
ν΄λ‘μ λ μλ°μ€ν¬λ¦½νΈμ κ°λ ₯ν κΈ°λ₯μΌλ‘, λ΄λΆ ν¨μκ° μΈλΆ(λλ¬μΈλ) ν¨μμ μ€νμ΄ λλ νμλ μΈλΆ μ€μ½νμ λ³μμ μ κ·Όν μ μκ² ν΄μ€λλ€. λ§€μ° μ μ©νμ§λ§, ν΄λ‘μ λ μ λλ‘ μ΄ν΄νμ§ λͺ»νλ©΄ λΉλ²ν λ©λͺ¨λ¦¬ λμμ μμΈμ΄ λ©λλ€. ν΄λ‘μ κ° λΆλͺ¨ μ€μ½νμ ν° κ°μ²΄μ λν μ°Έμ‘°λ₯Ό μ μ§νλ©΄, κ·Έ κ°μ²΄λ ν΄λ‘μ μμ²΄κ° νμ± μνμ΄κ³ λλ¬ κ°λ₯ν ν λ©λͺ¨λ¦¬μ λ¨μ μκ² λ©λλ€.
function createLogger(moduleName) {
const messages = []; // This array is part of the closure's scope
return function log(message) {
messages.push(`[${moduleName}] ${message}`);
// ... potentially send messages to a server ...
};
}
const appLogger = createLogger('Application');
// 'appLogger' holds a reference to the 'messages' array and 'moduleName'.
// If 'appLogger' is a long-lived object, 'messages' will continue to accumulate
// and consume memory. If 'messages' also contains references to large objects,
// those objects are also retained.
μΌλ°μ μΈ μλ리μ€λ ν° κ°μ²΄μ λν ν΄λ‘μ λ₯Ό νμ±νλ μ΄λ²€νΈ νΈλ€λ¬λ μ½λ°±μΌλ‘, μ΄λ‘ μΈν΄ ν΄λΉ κ°μ²΄λ€μ΄ κ·Έλ μ§ μμλ€λ©΄ κ°λΉμ§ 컬λ μ λμμ μν©μμ μμ§λμ§ λͺ»νκ² λ©λλ€.
λΆλ¦¬λ DOM μμ
κ³ μ μ μΈ νλ‘ νΈμλ λ©λͺ¨λ¦¬ λμλ λΆλ¦¬λ DOM μμμμ λ°μν©λλ€. μ΄λ DOM μμκ° λ¬Έμ κ°μ²΄ λͺ¨λΈ(DOM)μμ μ κ±°λμμ§λ§ μ¬μ ν μΌλΆ μλ°μ€ν¬λ¦½νΈ μ½λμ μν΄ μ°Έμ‘°λ λ λ°μν©λλ€. μμ μ체μ κ·Έ μμλ€, κ·Έλ¦¬κ³ κ΄λ ¨λ μ΄λ²€νΈ 리μ€λλ€μ΄ λ©λͺ¨λ¦¬μ λ¨μ μκ² λ©λλ€.
const element = document.getElementById('myElement');
document.body.removeChild(element);
// If 'element' is still referenced here, e.g., in a module's internal array
// or a closure, it's a leak. The GC cannot collect it.
myModule.storeElement(element); // This line would cause a leak if element is removed from DOM but still held by myModule
μμλ μκ°μ μΌλ‘ μ¬λΌμ‘μ§λ§ λ©λͺ¨λ¦¬ 곡κ°μ κ³μ μ°¨μ§νκΈ° λλ¬Έμ μ΄λ νΉν κ΅νν©λλ€. νλ μμν¬μ λΌμ΄λΈλ¬λ¦¬λ μ’ μ’ DOM μλͺ μ£ΌκΈ° κ΄λ¦¬λ₯Ό λμ§λ§, 컀μ€ν μ½λλ μ§μ μ μΈ DOM μ‘°μμ μ¬μ ν μ΄ λ¬Έμ μ λΉ μ§ μ μμ΅λλ€.
νμ΄λ¨Έμ μ΅μ λ²
μλ°μ€ν¬λ¦½νΈλ setInterval, setTimeout λ° λ€μν μ νμ μ΅μ λ²(MutationObserver, IntersectionObserver, ResizeObserver)μ κ°μ λ€μν λΉλκΈ° λ©μ»€λμ¦μ μ 곡ν©λλ€. μ΄λ€μ΄ μ λλ‘ μ 리λκ±°λ μ°κ²° ν΄μ λμ§ μμΌλ©΄ κ°μ²΄μ λν μ°Έμ‘°λ₯Ό 무기νμΌλ‘ μ μ§ν μ μμ΅λλ€.
// In a module that manages a dynamic UI component
let intervalId;
let myComponentState = { /* large object */ };
export function startPolling() {
intervalId = setInterval(() => {
// This closure references 'myComponentState'
// If 'clearInterval(intervalId)' is never called,
// 'myComponentState' will never be GC'd, even if the component
// it belongs to is removed from the DOM.
console.log('Polling state:', myComponentState);
}, 1000);
}
// To prevent a leak, a corresponding 'stopPolling' function is crucial:
export function stopPolling() {
clearInterval(intervalId);
intervalId = null; // Also dereference the ID
myComponentState = null; // Explicitly nullify if it's no longer needed
}
λμΌν μμΉμ΄ μ΅μ λ²μλ μ μ©λ©λλ€: λ μ΄μ νμνμ§ μμ λλ νμ disconnect() λ©μλλ₯Ό νΈμΆνμ¬ μ°Έμ‘°λ₯Ό ν΄μ ν΄μΌ ν©λλ€.
μ΄λ²€νΈ 리μ€λ
μ΄λ²€νΈ 리μ€λλ₯Ό μ κ±°νμ§ μκ³ μΆκ°νλ κ²μ λ λ€λ₯Έ μΌλ°μ μΈ λμ μμΈμ΄λ©°, νΉν λμ μμλ 리μ€λμ κ΄λ ¨λ κ°μ²΄κ° μΌμμ μΈ μ©λμΌ κ²½μ° λμ± κ·Έλ μ΅λλ€. μ΄λ²€νΈ 리μ€λκ° μμμ μΆκ°λκ³ λμ€μ κ·Έ μμκ° DOMμμ μ κ±°λλλΌλ, 리μ€λ ν¨μ(λ€λ₯Έ κ°μ²΄μ λν ν΄λ‘μ μΌ μ μμ)κ° μ¬μ ν μ°Έμ‘°λλ€λ©΄ μμμ κ΄λ ¨ κ°μ²΄ λͺ¨λ λμλ μ μμ΅λλ€.
function attachHandler(element) {
const largeData = { /* ... potentially large dataset ... */ };
const clickHandler = () => {
console.log('Clicked with data:', largeData);
};
element.addEventListener('click', clickHandler);
// If 'removeEventListener' is never called for 'clickHandler'
// and 'element' is eventually removed from the DOM,
// 'largeData' might be retained through the 'clickHandler' closure.
}
μΊμμ λ©λͺ¨μ΄μ μ΄μ
λͺ¨λμ μ±λ₯ ν₯μμ μν΄ κ³μ° κ²°κ³Όλ κ°μ Έμ¨ λ°μ΄ν°λ₯Ό μ μ₯νλ μΊμ± λ©μ»€λμ¦μ μ’ μ’ κ΅¬νν©λλ€. κ·Έλ¬λ μ΄λ¬ν μΊμκ° μ λλ‘ μ νλκ±°λ μ 리λμ§ μμΌλ©΄ 무νμ μ»€μ Έ μλΉν λ©λͺ¨λ¦¬λ₯Ό μ°¨μ§νκ² λ μ μμ΅λλ€. μ κ±° μ μ± μμ΄ κ²°κ³Όλ₯Ό μ μ₯νλ μΊμλ μ¬μ€μ μ μ₯νλ λͺ¨λ λ°μ΄ν°λ₯Ό κ³μ μ μ§νμ¬ κ°λΉμ§ 컬λ μ μ λ°©ν΄ν©λλ€.
// In a utility module
const cache = {};
export function fetchDataCached(id) {
if (cache[id]) {
return cache[id];
}
// Assume 'fetchDataFromNetwork' returns a Promise for a large object
const data = fetchDataFromNetwork(id);
cache[id] = data; // Store the data in cache
return data;
}
// Problem: 'cache' will grow forever unless an eviction strategy (LRU, LFU, etc.)
// or a cleanup mechanism is implemented.
λ©λͺ¨λ¦¬ ν¨μ¨μ μΈ μλ°μ€ν¬λ¦½νΈ λͺ¨λμ μν λͺ¨λ² μ¬λ‘
μλ°μ€ν¬λ¦½νΈμ GCλ μ κ΅νμ§λ§, κ°λ°μλ λμλ₯Ό λ°©μ§νκ³ λ©λͺ¨λ¦¬ μ¬μ©μ μ΅μ ννκΈ° μν΄ μ μ€ν μ½λ© κ΄νμ μ±νν΄μΌ ν©λλ€. μ΄λ¬ν κ΄νμ 보νΈμ μΌλ‘ μ μ© κ°λ₯νλ©°, μ¬λ¬λΆμ μ ν리μΌμ΄μ μ΄ μ μΈκ³μ λ€μν μ₯μΉμ λ€νΈμν¬ μ‘°κ±΄μμ μ μλνλλ‘ λμ΅λλ€.
1. μ¬μ©νμ§ μλ κ°μ²΄λ₯Ό λͺ μμ μΌλ‘ μμ°Έμ‘°νκΈ° (μ μ ν κ²½μ°)
κ°λΉμ§ 컬λ ν°λ μλμ΄μ§λ§, λλ‘λ λ³μλ₯Ό λͺ
μμ μΌλ‘ nullμ΄λ undefinedλ‘ μ€μ νλ κ²μ΄ GCμκ² κ°μ²΄κ° λ μ΄μ νμνμ§ μλ€λ μ νΈλ₯Ό 보λ΄λ λ° λμμ΄ λ μ μμΌλ©°, νΉν μ°Έμ‘°κ° λ¨μμμ μ μλ κ²½μ°μ κ·Έλ μ΅λλ€. μ΄κ²μ 보νΈμ μΈ ν΄κ²°μ±
μ΄λΌκΈ°λ³΄λ€λ λ μ΄μ νμνμ§ μλ€κ³ νμ νλ κ°ν μ°Έμ‘°λ₯Ό λλ κ²μ κ°κΉμ΅λλ€.
let largeObject = generateLargeData();
// ... use largeObject ...
// When no longer needed, and you want to ensure no lingering references:
largeObject = null; // Breaks the reference, making it eligible for GC sooner
μ΄λ λͺ¨λ μ€μ½νλ μ μ μ€μ½νμ μ€λ μ§μλλ λ³μ, λλ DOMμμ λΆλ¦¬λμ΄ λ‘μ§μμ λ μ΄μ νλ°ν μ¬μ©λμ§ μλλ€κ³ νμ νλ κ°μ²΄λ₯Ό λ€λ£° λ νΉν μ μ©ν©λλ€.
2. μ΄λ²€νΈ 리μ€λμ νμ΄λ¨Έλ₯Ό λΆμ§λ°ν κ΄λ¦¬νκΈ°
νμ μ΄λ²€νΈ 리μ€λ μΆκ°λ μ κ±°μ, νμ΄λ¨Έ μμμ ν΄μ μ μ§μ μ΄λ£¨μ΄μΌ ν©λλ€. μ΄λ λΉλκΈ° μμ κ³Ό κ΄λ ¨λ λμλ₯Ό λ°©μ§νκΈ° μν κΈ°λ³Έ κ·μΉμ λλ€.
-
μ΄λ²€νΈ 리μ€λ: μμλ μ»΄ν¬λνΈκ° νκ΄΄λκ±°λ λ μ΄μ μ΄λ²€νΈμ λ°μν νμκ° μμ λ
removeEventListenerλ₯Ό μ¬μ©νμΈμ. μμμ μ§μ λΆμ°©λλ 리μ€λ μλ₯Ό μ€μ΄κΈ° μν΄ μμ λ 벨μμ λ¨μΌ νΈλ€λ¬λ₯Ό μ¬μ©νλ κ²(μ΄λ²€νΈ μμ)μ κ³ λ €νμΈμ. -
νμ΄λ¨Έ: λ°λ³΅λκ±°λ μ§μ°λ μμ
μ΄ λ μ΄μ νμνμ§ μμ λ νμ
setInterval()μ λν΄clearInterval()μ,setTimeout()μ λν΄clearTimeout()μ νΈμΆνμΈμ. -
AbortController: `fetch` μμ²μ΄λ μ₯κΈ° μ€ν κ³μ°κ³Ό κ°μ μ·¨μ κ°λ₯ν μμ μ κ²½μ°,AbortControllerλ κ·Έ μλͺ μ£ΌκΈ°λ₯Ό κ΄λ¦¬νκ³ μ»΄ν¬λνΈκ° μΈλ§μ΄νΈλκ±°λ μ¬μ©μκ° λ€λ₯Έ κ³³μΌλ‘ μ΄λν λ 리μμ€λ₯Ό ν΄μ νλ νλμ μ΄κ³ ν¨κ³Όμ μΈ λ°©λ²μ λλ€. μ΄κ²μsignalμ μ΄λ²€νΈ 리μ€λ λ° λ€λ₯Έ APIμ μ λ¬λ μ μμ΄ μ¬λ¬ μμ μ λν λ¨μΌ μ·¨μ μ§μ μ μ 곡ν©λλ€.
class MyComponent {
constructor() {
this.element = document.createElement('button');
this.data = { /* ... */ };
this.handleClick = this.handleClick.bind(this);
this.element.addEventListener('click', this.handleClick);
}
handleClick() {
console.log('Component clicked, data:', this.data);
}
destroy() {
// CRITICAL: Remove event listener to prevent leak
this.element.removeEventListener('click', this.handleClick);
this.data = null; // Dereference if not used elsewhere
this.element = null; // Dereference if not used elsewhere
}
}
3. "μ½ν" μ°Έμ‘°λ₯Ό μν΄ WeakMapκ³Ό WeakSet νμ©νκΈ°
WeakMapκ³Ό WeakSetμ λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό μν κ°λ ₯ν λꡬμ΄λ©°, νΉν κ°μ²΄κ° κ°λΉμ§ 컬λ μ
λλ κ²μ λ§μ§ μμΌλ©΄μ λ°μ΄ν°λ₯Ό κ°μ²΄μ μ°κ΄μμΌμΌ ν λ μ μ©ν©λλ€. μ΄λ€μ ν€(WeakMapμ κ²½μ°) λλ κ°(WeakSetμ κ²½μ°)μ λν "μ½ν" μ°Έμ‘°λ₯Ό κ°μ§λλ€. κ°μ²΄μ λν μ μΌν λ¨μ μ°Έμ‘°κ° μ½ν μ°Έμ‘°μΌ κ²½μ°, ν΄λΉ κ°μ²΄λ κ°λΉμ§ 컬λ μ
λ μ μμ΅λλ€.
-
WeakMapμ¬μ© μ¬λ‘:- λΉκ³΅κ° λ°μ΄ν°: κ°μ²΄ μ체μ μΌλΆλ‘ λ§λ€μ§ μκ³ κ°μ²΄μ λν λΉκ³΅κ° λ°μ΄ν°λ₯Ό μ μ₯νμ¬, κ°μ²΄κ° GCλ λ λ°μ΄ν°λ ν¨κ» GCλλλ‘ λ³΄μ₯ν©λλ€.
- μΊμ±: μΊμλ κ°μ΄ ν΄λΉ ν€ κ°μ²΄κ° κ°λΉμ§ 컬λ μ λ λ μλμΌλ‘ μ κ±°λλ μΊμλ₯Ό ꡬμΆν©λλ€.
- λ©νλ°μ΄ν°: DOM μμλ λ€λ₯Έ κ°μ²΄κ° λ©λͺ¨λ¦¬μμ μ κ±°λλ κ²μ λ§μ§ μμΌλ©΄μ λ©νλ°μ΄ν°λ₯Ό 첨λΆν©λλ€.
-
WeakSetμ¬μ© μ¬λ‘:- κ°μ²΄μ GCλ₯Ό λ§μ§ μμΌλ©΄μ νμ± μΈμ€ν΄μ€λ₯Ό μΆμ ν©λλ€.
- νΉμ νλ‘μΈμ€λ₯Ό κ±°μΉ κ°μ²΄λ₯Ό νμν©λλ€.
// A module for managing component states without holding strong references
const componentStates = new WeakMap();
export function setComponentState(componentInstance, state) {
componentStates.set(componentInstance, state);
}
export function getComponentState(componentInstance) {
return componentStates.get(componentInstance);
}
// If 'componentInstance' is garbage collected because it's no longer reachable
// anywhere else, its entry in 'componentStates' is automatically removed,
// preventing a memory leak.
ν΅μ¬μ WeakMapμ ν€(λλ WeakSetμ κ°)λ‘ κ°μ²΄λ₯Ό μ¬μ©νκ³ , κ·Έ κ°μ²΄κ° λ€λ₯Έ κ³³μμ λλ¬ν μ μκ² λλ©΄ κ°λΉμ§ 컬λ ν°κ° μ΄λ₯Ό νμνκ³ , μ½ν 컬λ μ
μ ν΄λΉ νλͺ©μ΄ μλμΌλ‘ μ¬λΌμ§λ€λ κ²μ
λλ€. μ΄λ μΌμμ μΈ κ΄κ³λ₯Ό κ΄λ¦¬νλ λ° λ§€μ° μ μ©ν©λλ€.
4. λ©λͺ¨λ¦¬ ν¨μ¨μ±μ μν λͺ¨λ μ€κ³ μ΅μ ν
μ μ€ν λͺ¨λ μ€κ³λ λ³Έμ§μ μΌλ‘ λ λμ λ©λͺ¨λ¦¬ μ¬μ©μΌλ‘ μ΄μ΄μ§ μ μμ΅λλ€:
- λͺ¨λ μ€μ½ν μν μ ν: λͺ¨λ μ€μ½νμ μ§μ μ μΈλ λ³κ²½ κ°λ₯νκ³ μ€λ μ§μλλ λ°μ΄ν° ꡬ쑰μ μ£ΌμνμΈμ. κ°λ₯νλ€λ©΄ λΆλ³μΌλ‘ λ§λ€κ±°λ, λͺ μμ μΌλ‘ λΉμ°κ±°λ μ¬μ€μ νλ ν¨μλ₯Ό μ 곡νμΈμ.
- μ μ κ°λ³ μν νΌνκΈ°: λͺ¨λμ΄ μ°λ°μ μΈ μ μ λμλ₯Ό μ€μ¬μ£Όμ§λ§, λͺ¨λμμ μλμ μΌλ‘ κ°λ³μ μΈ μ μ μνλ₯Ό λ΄λ³΄λ΄λ κ²μ μ μ¬ν λ¬Έμ λ‘ μ΄μ΄μ§ μ μμ΅λλ€. λ°μ΄ν°λ₯Ό λͺ μμ μΌλ‘ μ λ¬νκ±°λ μμ‘΄μ± μ£Όμ κ³Ό κ°μ ν¨ν΄μ μ νΈνμΈμ.
- ν©ν 리 ν¨μ μ¬μ©: λ§μ μνλ₯Ό 보μ νλ λ¨μΌ μΈμ€ν΄μ€(μ±κΈν€)λ₯Ό λ΄λ³΄λ΄λ λμ , μ μΈμ€ν΄μ€λ₯Ό μμ±νλ ν©ν 리 ν¨μλ₯Ό λ΄λ³΄λ΄μΈμ. μ΄λ₯Ό ν΅ν΄ κ° μΈμ€ν΄μ€λ μ체 μλͺ μ£ΌκΈ°λ₯Ό κ°μ§λ©° λ 립μ μΌλ‘ κ°λΉμ§ 컬λ μ λ μ μμ΅λλ€.
- μ§μ° λ‘λ©: ν° λͺ¨λμ΄λ μλΉν 리μμ€λ₯Ό λ‘λνλ λͺ¨λμ κ²½μ°, μ€μ λ‘ νμν λλ§ μ§μ° λ‘λ©νλ κ²μ κ³ λ €νμΈμ. μ΄λ νμν μμ κΉμ§ λ©λͺ¨λ¦¬ ν λΉμ μ§μ°μν€κ³ μ ν리μΌμ΄μ μ μ΄κΈ° λ©λͺ¨λ¦¬ μ¬μ©λμ μ€μΌ μ μμ΅λλ€.
5. λ©λͺ¨λ¦¬ λμ νλ‘νμΌλ§ λ° λλ²κΉ
μ΅κ³ μ κ΄νμ λ°λ₯΄λλΌλ λ©λͺ¨λ¦¬ λμλ μ°ΎκΈ° μ΄λ €μΈ μ μμ΅λλ€. νλ λΈλΌμ°μ κ°λ°μ λꡬ(λ° Node.js λλ²κΉ λꡬ)λ λ©λͺ¨λ¦¬ λ¬Έμ λ₯Ό μ§λ¨νλ κ°λ ₯ν κΈ°λ₯μ μ 곡ν©λλ€:
-
ν μ€λ
μ· (λ©λͺ¨λ¦¬ ν): ν μ€λ
μ·μ μ°μ΄ νμ¬ λ©λͺ¨λ¦¬μ μλ λͺ¨λ κ°μ²΄μ κ·Έλ€ μ¬μ΄μ μ°Έμ‘°λ₯Ό λ³Ό μ μμ΅λλ€. μ¬λ¬ μ€λ
μ·μ μ°κ³ λΉκ΅νλ©΄ μκ°μ΄ μ§λ¨μ λ°λΌ μΆμ λλ κ°μ²΄λ₯Ό κ°μ‘°ν μ μμ΅λλ€.
- DOM λμκ° μμ¬λλ©΄ "Detached HTMLDivElement" (λλ μ μ¬ν) νλͺ©μ μ°Ύμ보μΈμ.
- μμμΉ μκ² μ»€μ§λ λμ "Retained Size"λ₯Ό κ°μ§ κ°μ²΄λ₯Ό μλ³νμΈμ.
- "Retainers" κ²½λ‘λ₯Ό λΆμνμ¬ κ°μ²΄κ° μ μ¬μ ν λ©λͺ¨λ¦¬μ λ¨μ μλμ§(μ¦, μ΄λ€ λ€λ₯Έ κ°μ²΄λ€μ΄ μ¬μ ν μ°Έμ‘°λ₯Ό κ°μ§κ³ μλμ§) μ΄ν΄νμΈμ.
- μ±λ₯ λͺ¨λν°: μ€μκ° λ©λͺ¨λ¦¬ μ¬μ©λ(JS ν, DOM λ Έλ, μ΄λ²€νΈ 리μ€λ)μ κ΄μ°°νμ¬ λμλ₯Ό λνλ΄λ μ μ§μ μΈ μ¦κ°λ₯Ό λ°κ²¬νμΈμ.
- ν λΉ κ³μΈ‘: μκ° κ²½κ³Όμ λ°λ₯Έ ν λΉμ κΈ°λ‘νμ¬ λ§μ κ°μ²΄λ₯Ό μμ±νλ μ½λ κ²½λ‘λ₯Ό μλ³νκ³ λ©λͺ¨λ¦¬ μ¬μ©μ μ΅μ ννλ λ° λμμ λ°μΌμΈμ.
ν¨κ³Όμ μΈ λλ²κΉ μ μ’ μ’ λ€μμ ν¬ν¨ν©λλ€:
- λμλ₯Ό μ λ°ν μ μλ μμ μν (μ: λͺ¨λ¬ μ΄κ³ λ«κΈ°, νμ΄μ§ κ° μ΄λ).
- μμ *μ *μ ν μ€λ μ· μ°κΈ°.
- μμ μ μ¬λ¬ λ² μννκΈ°.
- μμ *ν*μ λ€λ₯Έ ν μ€λ μ· μ°κΈ°.
- λ μ€λ μ·μ λΉκ΅νμ¬ κ°μλ ν¬κΈ°κ° ν¬κ² μ¦κ°ν κ°μ²΄λ₯Ό νν°λ§νκΈ°.
κ³ κΈ κ°λ λ° ν₯ν κ³ λ € μ¬ν
μλ°μ€ν¬λ¦½νΈμ μΉ κΈ°μ μ νκ²½μ λμμμ΄ μ§ννλ©°, λ©λͺ¨λ¦¬ κ΄λ¦¬μ μν₯μ λ―ΈμΉλ μλ‘μ΄ λꡬμ ν¨λ¬λ€μμ κ°μ Έμ΅λλ€.
WebAssembly (Wasm) λ° κ³΅μ λ©λͺ¨λ¦¬
WebAssembly (Wasm)λ C++λ Rustμ κ°μ μΈμ΄μμ μ»΄νμΌλ κ³ μ±λ₯ μ½λλ₯Ό λΈλΌμ°μ μμ μ§μ μ€νν μ μλ λ°©λ²μ μ 곡ν©λλ€. μ£Όμ μ°¨μ΄μ μ Wasmμ΄ κ°λ°μμκ² μ ν λ©λͺ¨λ¦¬ λΈλ‘μ λν μ§μ μ μΈ μ μ΄κΆμ λΆμ¬νμ¬ ν΄λΉ νΉμ λ©λͺ¨λ¦¬μ λν΄ μλ°μ€ν¬λ¦½νΈμ κ°λΉμ§ 컬λ ν°λ₯Ό μ°ννλ€λ κ²μ λλ€. μ΄λ₯Ό ν΅ν΄ μΈλ°ν λ©λͺ¨λ¦¬ κ΄λ¦¬κ° κ°λ₯νλ©°, μ ν리μΌμ΄μ μ κ³ μ±λ₯μ΄ μ€μν λΆλΆμ μ μ΅ν μ μμ΅λλ€.
μλ°μ€ν¬λ¦½νΈ λͺ¨λμ΄ Wasm λͺ¨λκ³Ό μνΈ μμ©ν λ, λ μ¬μ΄μ μ λ¬λλ λ°μ΄ν°λ₯Ό κ΄λ¦¬νλ λ° μΈμ¬ν μ£Όμκ° νμν©λλ€. λν, SharedArrayBufferμ Atomicsλ Wasm λͺ¨λκ³Ό μλ°μ€ν¬λ¦½νΈκ° λ€λ₯Έ μ€λ λ(μΉ μ컀) κ°μ λ©λͺ¨λ¦¬λ₯Ό 곡μ ν μ μκ² νμ¬, λ©λͺ¨λ¦¬ λκΈ°ν λ° κ΄λ¦¬μ λν μλ‘μ΄ λ³΅μ‘μ±κ³Ό κΈ°νλ₯Ό λμ
ν©λλ€.
ꡬ쑰νλ ν΄λ‘ κ³Ό μ μ‘ κ°λ₯ν κ°μ²΄
μΉ μ컀μ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°μ λ, λΈλΌμ°μ λ μΌλ°μ μΌλ‘ λ°μ΄ν°μ κΉμ 볡μ¬λ³Έμ λ§λλ "ꡬ쑰νλ ν΄λ‘ " μκ³ λ¦¬μ¦μ μ¬μ©ν©λλ€. ν° λ°μ΄ν°μ
μ κ²½μ°, μ΄λ λ©λͺ¨λ¦¬μ CPUλ₯Ό λ§μ΄ μλͺ¨ν μ μμ΅λλ€. "μ μ‘ κ°λ₯ν κ°μ²΄"(ArrayBuffer, MessagePort, OffscreenCanvas λ±)λ μ΅μ νλ₯Ό μ 곡ν©λλ€: 볡μ¬νλ λμ , κΈ°λ³Έ λ©λͺ¨λ¦¬μ μμ κΆμ΄ ν μ€ν 컨ν
μ€νΈμμ λ€λ₯Έ 컨ν
μ€νΈλ‘ μ΄μ λμ΄ μλ κ°μ²΄λ μ¬μ©ν μ μκ² λμ§λ§, μ€λ λ κ° ν΅μ μμ ν¨μ¬ λΉ λ₯΄κ³ λ©λͺ¨λ¦¬ ν¨μ¨μ μ
λλ€.
μ΄λ 볡μ‘ν μΉ μ ν리μΌμ΄μ μ μ±λ₯μ λ§€μ° μ€μνλ©°, λ©λͺ¨λ¦¬ κ΄λ¦¬ κ³ λ € μ¬νμ΄ λ¨μΌ μ€λ λ μλ°μ€ν¬λ¦½νΈ μ€ν λͺ¨λΈμ λμ΄μ λ€λ μ μ κ°μ‘°ν©λλ€.
Node.js λͺ¨λμ λ©λͺ¨λ¦¬ κ΄λ¦¬
μλ² μΈ‘μμ V8 μμ§μ μ¬μ©νλ Node.js μ ν리μΌμ΄μ μ μ μ¬νμ§λ§ μ’ μ’ λ μ€μν λ©λͺ¨λ¦¬ κ΄λ¦¬ λ¬Έμ μ μ§λ©΄ν©λλ€. μλ² νλ‘μΈμ€λ μ₯μκ° μ€νλλ©° μΌλ°μ μΌλ‘ λ§μ μμ μμ²μ μ²λ¦¬νλ―λ‘ λ©λͺ¨λ¦¬ λμλ ν¨μ¬ λ ν° μν₯μ λ―ΈμΉ©λλ€. Node.js λͺ¨λμμ ν΄κ²°λμ§ μμ λμλ μλ²κ° κ³Όλν RAMμ μλΉνκ³ , μλ΅νμ§ μκ² λλ©°, κ²°κ΅ μΆ©λνμ¬ μ μΈκ³ μλ§μ μ¬μ©μμκ² μν₯μ λ―ΈμΉ μ μμ΅λλ€.
Node.js κ°λ°μλ --expose-gc νλκ·Έ(λλ²κΉ
μ μν΄ μλμΌλ‘ GCλ₯Ό νΈλ¦¬κ±°), `process.memoryUsage()`(ν μ¬μ©λ κ²μ¬), κ·Έλ¦¬κ³ `heapdump`λ `node-memwatch`μ κ°μ μ μ© ν¨ν€μ§λ₯Ό μ¬μ©νμ¬ μλ² μΈ‘ λͺ¨λμ λ©λͺ¨λ¦¬ λ¬Έμ λ₯Ό νλ‘νμΌλ§νκ³ λλ²κΉ
ν μ μμ΅λλ€. μ°Έμ‘°λ₯Ό λκ³ , μΊμλ₯Ό κ΄λ¦¬νλ©°, ν° κ°μ²΄μ λν ν΄λ‘μ λ₯Ό νΌνλ μμΉμ λκ°μ΄ μ€μν©λλ€.
μ±λ₯ λ° λ¦¬μμ€ μ΅μ νμ λν κΈλ‘λ² κ΄μ
μλ°μ€ν¬λ¦½νΈμμ λ©λͺ¨λ¦¬ ν¨μ¨μ±μ μΆκ΅¬νλ κ²μ λ¨μ§ νλ¬Έμ μΈ μ°μ΅μ΄ μλλλ€. μ΄λ μ μΈκ³ μ¬μ©μμ λΉμ¦λμ€μ μ€μ μ μΈ μν₯μ λ―ΈμΉ©λλ€:
- λ€μν μ₯μΉμμμ μ¬μ©μ κ²½ν: μΈκ³ μ¬λ¬ μ§μμμ μ¬μ©μλ€μ μ μ¬μ μ€λ§νΈν°μ΄λ RAMμ΄ μ νλ μ₯μΉλ‘ μΈν°λ·μ μ μν©λλ€. λ©λͺ¨λ¦¬λ₯Ό λ§μ΄ μ¬μ©νλ μ ν리μΌμ΄μ μ μ΄λ¬ν μ₯μΉμμ λλ¦¬κ³ , λ°μμ΄ μκ±°λ, μμ£Ό μΆ©λνμ¬ λμ μ¬μ©μ κ²½νκ³Ό μ μ¬μ μΈ μ΄νλ‘ μ΄μ΄μ§λλ€. λ©λͺ¨λ¦¬λ₯Ό μ΅μ ννλ©΄ λͺ¨λ μ¬μ©μμκ² λ 곡ννκ³ μ κ·Όμ± μλ κ²½νμ 보μ₯ν μ μμ΅λλ€.
- μλμ§ μλΉ: λμ λ©λͺ¨λ¦¬ μ¬μ©λκ³Ό λΉλ²ν κ°λΉμ§ 컬λ μ μ£ΌκΈ°λ λ λ§μ CPUλ₯Ό μλΉνκ³ , μ΄λ κ²°κ΅ λ λμ μλμ§ μλΉλ‘ μ΄μ΄μ§λλ€. λͺ¨λ°μΌ μ¬μ©μμκ² μ΄λ λ λΉ λ₯Έ λ°°ν°λ¦¬ μλͺ¨λ₯Ό μλ―Έν©λλ€. λ©λͺ¨λ¦¬ ν¨μ¨μ μΈ μ ν리μΌμ΄μ μ ꡬμΆνλ κ²μ λ μ§μ κ°λ₯νκ³ μΉνκ²½μ μΈ μννΈμ¨μ΄ κ°λ°μ ν₯ν ν κ±Έμμ λλ€.
- κ²½μ μ λΉμ©: μλ² μΈ‘ μ ν리μΌμ΄μ (Node.js)μ κ²½μ°, κ³Όλν λ©λͺ¨λ¦¬ μ¬μ©μ μ§μ μ μΌλ‘ λ λμ νΈμ€ν λΉμ©μΌλ‘ μ΄μ΄μ§λλ€. λ©λͺ¨λ¦¬κ° λμλλ μ ν리μΌμ΄μ μ μ€ννλ©΄ λ λΉμΌ μλ² μΈμ€ν΄μ€κ° νμνκ±°λ λ μ¦μ μ¬μμμ΄ νμν μ μμΌλ©°, μ΄λ κΈλ‘λ² μλΉμ€λ₯Ό μ΄μνλ λΉμ¦λμ€μ μμ΅μ μν₯μ λ―ΈμΉ©λλ€.
- νμ₯μ±κ³Ό μμ μ±: ν¨μ¨μ μΈ λ©λͺ¨λ¦¬ κ΄λ¦¬λ νμ₯ κ°λ₯νκ³ μμ μ μΈ μ ν리μΌμ΄μ μ μ΄μμ λλ€. μμ² λλ μλ°±λ§ λͺ μ μ¬μ©μμκ² μλΉμ€λ₯Ό μ 곡νλ , μΌκ΄λκ³ μμΈ‘ κ°λ₯ν λ©λͺ¨λ¦¬ λμμ λΆν μνμμ μ ν리μΌμ΄μ μ μ λ’°μ±κ³Ό μ±λ₯μ μ μ§νλ λ° νμμ μ λλ€.
μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ©λͺ¨λ¦¬ κ΄λ¦¬μ λͺ¨λ² μ¬λ‘λ₯Ό μ±νν¨μΌλ‘μ¨ κ°λ°μλ€μ λͺ¨λλ₯Ό μν λ μ’κ³ , λ ν¨μ¨μ μ΄λ©°, λ ν¬μ©μ μΈ λμ§νΈ μνκ³μ κΈ°μ¬ν©λλ€.
κ²°λ‘
μλ°μ€ν¬λ¦½νΈμ μλ κ°λΉμ§ 컬λ μ μ κ°λ°μλ₯Ό μν΄ λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό λ¨μννμ¬ μ ν리μΌμ΄μ λ‘μ§μ μ§μ€ν μ μκ² ν΄μ£Όλ κ°λ ₯ν μΆμνμ λλ€. κ·Έλ¬λ "μλ"μ΄ "λ Έλ ₯ μμ"μ μλ―Ένμ§λ μμ΅λλ€. νΉν νλ μλ°μ€ν¬λ¦½νΈ λͺ¨λμ λ§₯λ½μμ κ°λΉμ§ 컬λ ν°κ° μ΄λ»κ² μλνλμ§ μ΄ν΄νλ κ²μ κ³ μ±λ₯, μμ μ±, 리μμ€ ν¨μ¨μ μΈ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° νμμ μ λλ€.
μ΄λ²€νΈ 리μ€λμ νμ΄λ¨Έλ₯Ό λΆμ§λ°ν κ΄λ¦¬νλ κ²λΆν° WeakMapμ μ λ΅μ μΌλ‘ μ¬μ©νκ³ λͺ¨λ μνΈ μμ©μ μ μ€νκ² μ€κ³νλ κ²κΉμ§, κ°λ°μλ‘μ μ°λ¦¬κ° λ΄λ¦¬λ μ νμ μ ν리μΌμ΄μ
μ λ©λͺ¨λ¦¬ μ¬μ©λμ μ§λν μν₯μ λ―ΈμΉ©λλ€. κ°λ ₯ν λΈλΌμ°μ κ°λ°μ λꡬμ μ¬μ©μ κ²½ν λ° λ¦¬μμ€ νμ©μ λν κΈλ‘λ² κ΄μ μ ν΅ν΄ μ°λ¦¬λ λ©λͺ¨λ¦¬ λμλ₯Ό ν¨κ³Όμ μΌλ‘ μ§λ¨νκ³ μνν μ μλ μ’μ μ€λΉκ° λμ΄ μμ΅λλ€.
μ΄λ¬ν λͺ¨λ² μ¬λ‘λ₯Ό λ°μλ€μ΄κ³ , μ§μμ μΌλ‘ μ ν리μΌμ΄μ μ νλ‘νμΌλ§νλ©°, μλ°μ€ν¬λ¦½νΈμ λ©λͺ¨λ¦¬ λͺ¨λΈμ λν μ΄ν΄λ₯Ό κ³μν΄μ λ€λ¬μΌμμμ€. κ·Έλ κ² ν¨μΌλ‘μ¨ μ¬λ¬λΆμ κΈ°μ μ μλμ ν₯μμν¬ λΏλ§ μλλΌ, μ μΈκ³ μ¬μ©μλ₯Ό μν΄ λ λΉ λ₯΄κ³ , λ μ λ’°ν μ μμΌλ©°, λ μ κ·Όμ± μλ μΉμ κΈ°μ¬νκ² λ κ²μ λλ€. λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό λ§μ€ν°νλ κ²μ λ¨μν μΆ©λμ νΌνλ κ²μ΄ μλλΌ, μ§λ¦¬μ λ° κΈ°μ μ μ₯λ²½μ μ΄μνλ μ°μν λμ§νΈ κ²½νμ μ 곡νλ κ²μ λλ€.