2025-11-17
π¨ Vue In-DOM ν νλ¦Ώ, λΉμ μ script μ½λλ₯Ό λ λ² μ€ννκ³ μλ€!
λ κ±°μ μ½λμμ λ§μ£Όν μλ¬Έ
κ°λ°μ νλ€ λ³΄λ©΄ μμμΉ λͺ»ν λ²κ·Έλ₯Ό λ§μ£Όν λκ° μμ΄μ. νΉν λ κ±°μ νλ‘μ νΈλ₯Ό μ μ§λ³΄μνλ€ λ³΄λ©΄ λμ± κ·Έλ μ£ . μ λν νμ¬μ λ κ±°μ μ½λλ₯Ό κ°μ νλ μ€, μ΄μν μ΄μλ₯Ό λ°κ²¬νμ΄μ.
1<!DOCTYPE html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> 6 <title>Document</title> 7 </head> 8 <body> 9 <div id="vue-container"> 10 <div>컨ν μΈ </div> 11 <script type="application/javascript"> 12 console.log('script executed') 13 </script> 14 </div> 15 16 <script> 17 const vm = new Vue({ 18 el: '#vue-container', 19 mounted() { 20 console.log('vm mounted') 21 }, 22 }) 23 </script> 24 </body> 25</html>
μ½μ μΆλ ₯:
script executed
script executed // μ λ λ²?
vm mounted
λΆλͺ
script νκ·Έλ νλμΈλ°, μ½μμλ script executedκ° λ λ² μΆλ ₯λκ³ μμμ΄μ. μ΄λ¬ν λ¬Έμ λ μμμΉ λͺ»ν λΆμμ©μ μΌμΌν¬ μ μκ³ , νΉν API νΈμΆμ΄λ DOM μ‘°μμ΄ ν¬ν¨λ κ²½μ° μ¬κ°ν λ²κ·Έλ‘ μ΄μ΄μ§ μ μμ΄μ.
κ³Όμ° Vueλ Scriptλ₯Ό μ΄λ»κ² μ²λ¦¬νλ κ±ΈκΉ?
SFCμ In-DOM Templateμ μ°¨μ΄
μ²μμλ SFC(Single File Component)μ In-DOM templateμ λμ λ°©μ μ°¨μ΄ λλ¬Έμ΄λΌκ³ μκ°νμ΄μ.
- SFC (
.vueνμΌ): λΉλ νμμ μ»΄νμΌλμ΄createElementν¨μλ‘ λ³νλκΈ° λλ¬Έμtemplateμμscriptλ μ€νλμ§ μμ - In-DOM template: HTMLμ μ§μ μμ±λμ΄ λΈλΌμ°μ κ° νμ±νλ©΄μ μ€νλ¨
νμ§λ§ In-DOM templateλΌλ ν λ²λ§ μ€νλ κ±°λΌκ³ μμνλλ°, μ€μ λ‘λ λ λ² μ€νλκ³ μμμ΄μ.
λλ²κ±°λ‘ μΆμ ν μ€ν κ²½λ‘
μ νν μμΈμ μ°ΎκΈ° μν΄ debugger λ¬Έμ μΆκ°νκ³ Call Stackμ νμΈνμ΄μ.
1<script type="application/javascript"> 2 debugger 3 console.log('script executed') 4 console.trace() 5</script>
1μ°¨ μ€ν (λΈλΌμ°μ νμ±):
(anonymous) @ inline script
2μ°¨ μ€ν (Vue λ΄λΆ):
(anonymous) @ inline script
insertBefore (native)
insert @ vue.js:xxxx
createElm @ vue.js:xxxx
patch @ vue.js:xxxx
Vue._update @ vue.js:xxxx
μ¬κΈ°μ ν΅μ¬μ Vueμ insertBeforeμμ scriptκ° λ€μ μ€νλκ³ μλ€λ μ μ΄μμ.
Vueμ DOM Patching λ©μ»€λμ¦
Vueκ° In-DOM templateμ μ²λ¦¬νλ κ³Όμ μ μ΄ν΄λ³΄λ©΄:
#vue-containerμ λ΄μ©μ templateμΌλ‘ μ½κΈ°- Virtual DOM μμ±
- μ€μ DOMμΌλ‘ patch (μ¬κΈ°μ
insertBeforeνΈμΆ) - script λ Έλκ° DOMμ μ½μ λλ©΄μ μ¬μ€ν
μ€μν μ μ, insertBeforeλ appendChildλ‘ script λ
Έλλ₯Ό DOMμ μ½μ
νλ©΄ λΈλΌμ°μ κ° μλμΌλ‘ μ€ννλ€λ κ±°μμ.
1// κ°λ¨ν ν μ€νΈ 2const script = document.createElement('script') 3script.textContent = 'console.log("test")' 4// μ¬κΈ°κΉμ§λ μ€ν μ λ¨ 5 6document.body.appendChild(script) 7// μ¬κΈ°μ μ€νλ¨!
κ·Έλ°λ° λͺ¨λ Scriptκ° λ λ² μ€νλλ 건 μλμλ€
μ¬κΈ°κΉμ§ μ΄ν΄νκ³ λλ, λ λ€λ₯Έ μλ¬Έμ΄ μκ²Όμ΄μ. "κ·ΈλΌ λͺ¨λ In-DOM templateμ scriptκ° λ λ² μ€νλλ 건κ°?" μ€μ λ‘ ν μ€νΈλ₯Ό ν΄λ³΄μμ΅λλ€.
1<div id="vue-container"> 2 <script type="text/javascript"> 3 console.log('text/javascript') 4 </script> 5 <script type="application/javascript"> 6 console.log('application/javascript') 7 </script> 8</div>
κ²°κ³Ό:
text/javascript (1νλ§ μ€ν!)
application/javascript (2ν μ€ν)
λλκ²λ text/javascriptλ ν λ²λ§ μ€νλκ³ , application/javascriptλ§ λ λ² μ€νλμμ΄μ.
Vueμ Script νν°λ§ λ‘μ§
Vueλ μ νΉμ Scriptλ§ μ κ±°ν κΉ?
Vue 2λ In-DOM templateμ μ²λ¦¬ν λ, νΉμ script νκ·Έλ₯Ό μ κ±°νλ λ‘μ§μ΄ μμ΄μ. μ΄λ―Έ λΈλΌμ°μ κ° μ€ννλ€κ³ κ°μ£Όνκ³ , μ¬μ€νμ λ°©μ§νκΈ° μν΄μμ£ .
1// Vue 2 λ΄λΆ λ‘μ§ (μΆμ ) 2function shouldRemoveScript(type) { 3 // νμ€ νμ λ§ μ κ±° 4 return !type || type === '' || type === 'text/javascript' 5} 6 7if (tagName === 'script' && shouldRemoveScript(scriptType)) { 8 // templateμμ μ κ±° β μ¬μ€ν μ λ¨ 9} else { 10 // μΌλ° μμλ‘ μ μ§ β μ¬μ½μ μ μ¬μ€νλ¨ 11}
MDNμμ μ°Ύμ λ΅
MDN λ¬Έμλ₯Ό μ΄ν΄λ³΄λ λͺ νν λ΅μ΄ μμμ΄μ.
JavaScript content should always be served with the MIME type text/javascript.
Legacy JavaScript MIME types (λͺ¨λ Deprecated):
application/javascript- Deprecatedapplication/ecmascript- Deprecatedtext/ecmascript- Deprecated- κ·Έ μΈ λ€μν λΉνμ€ νμ λ€...
application/javascriptλ μμ¬μ μΈ μ΄μ λ‘ λΈλΌμ°μ κ° μ§μνμ§λ§, deprecatedλ λ κ±°μ νμ
μ΄μμ΄μ. Vueλ νμ€μ λ°λ₯΄λ νμ
λ§ νν°λ§νκ³ , deprecated νμ
μ κ°λ°μκ° νΉμν λͺ©μ μΌλ‘ μ¬μ©νμ μ μλ€κ³ κ°μ£Όνμ¬ κ·Έλλ‘ μ μ§νλ κ²μΌλ‘ 보μ¬μ.
ν΄κ²° λ°©λ²
1. νμ€μ λ°λ₯΄λ κ²μ΄ κ°μ₯ μμ ν΄μ
κ°μ₯ κ°λ¨ν ν΄κ²°μ±
μ type μμ±μ μλ΅νκ±°λ text/javascriptλ₯Ό μ¬μ©νλ κ±°μμ.
1<!-- κΆμ₯: type μλ΅ --> 2<div id="vue-container"> 3 <script> 4 console.log('1νλ§ μ€νλ¨!') 5 </script> 6</div>
1<!-- λλ λͺ μμ μΌλ‘ text/javascript μ¬μ© --> 2<div id="vue-container"> 3 <script type="text/javascript"> 4 console.log('1νλ§ μ€νλ¨!') 5 </script> 6</div>
2. In-DOM Templateμμ Script μ¬μ©μ νΌνκΈ°
In-DOM templateμ μ€ν κ°λ₯ν scriptλ₯Ό λ£λ 건 μ’μ ν¨ν΄μ΄ μλμμ. Vueμ λΌμ΄νμ¬μ΄ν΄ ν μ νμ©νλ κ²μ΄ λ λͺ ννκ³ μμ ν΄μ.
1<div id="vue-container"> 2 <div>컨ν μΈ </div> 3</div> 4 5<script> 6 const vm = new Vue({ 7 el: '#vue-container', 8 mounted() { 9 // νμν λ‘μ§μ μ¬κΈ°μ μ€ν 10 console.log('μμ νκ² 1ν μ€ν!') 11 }, 12 }) 13</script>
3. λ°μ΄ν° μ μ₯μ΄ λͺ©μ μ΄λΌλ©΄
λ§μ½ μ€νμ΄ μλ λ°μ΄ν° μ μ₯μ΄ λͺ©μ μ΄λΌλ©΄, application/json νμ
μ μ¬μ©νλ©΄ λ©λλ€. μ΄ κ²½μ° λΈλΌμ°μ κ° μ€ννμ§ μμμ.
1<div id="vue-container"> 2 <script type="application/json" id="config"> 3 { 4 "apiUrl": "https://api.example.com", 5 "timeout": 5000 6 } 7 </script> 8</div> 9 10<script> 11 new Vue({ 12 el: '#vue-container', 13 mounted() { 14 const config = JSON.parse(document.getElementById('config').textContent) 15 console.log(config) 16 }, 17 }) 18</script>
μ μ°ν μ¬κ³ μ μΉ νμ€μ λν μ΄ν΄
μ΄ λ²κ·Έλ₯Ό ν΄κ²°νλ κ³Όμ μμ λͺ κ°μ§ μ€μν κ΅νμ μ»μμ΄μ.
- νμ€μ λ°λ₯΄λ κ²μ μ€μμ±:
application/javascriptμ²λΌdeprecatedλ νμ μ μμμΉ λͺ»ν λμμ μΌμΌν¬ μ μμ΄μ. - νλ μμν¬μ λ΄λΆ λμ μ΄ν΄: Vueκ° μ νΉμ λ°©μμΌλ‘ λμνλμ§ μ΄ν΄νλ©΄, λ λμ μ½λλ₯Ό μμ±ν μ μμ΄μ.
- λλ²κΉ λꡬμ νμ©: Call Stackμ μΆμ νμ¬ μ νν μ€ν κ²½λ‘λ₯Ό νμ νλ κ²μ΄ λ¬Έμ ν΄κ²°μ ν΅μ¬μ΄μμ.
λ λμκ°, λ κ±°μ μ½λλ₯Ό μ μ§λ³΄μν λλ "μ΄κ² μ μ΄λ κ² μμ±λμμκΉ?"λΌλ μλ¬Έμ νμ κ°μ§κ³ μ κ·Όνλ κ²μ΄ μ€μν΄μ. λλ‘λ κ³Όκ±°μ μ½λκ° λΉμμ μ μ½μ¬νμ΄λ λ²μ μ΄μ λλ¬Έμ μμ±λ κ²μΌ μ μκ³ , νμ¬λ λ λμ λ°©λ²μ΄ μμ μ μμ΄μ.
