κ²°λ‘ λΆ€ν„° λ§ν•˜λ©΄, ν˜„λŒ€ JavaScriptλŠ” λ‘˜ 닀이닀.

근데 이 말이 μ™œ λ‚˜μ˜€λŠ” 걸까?


πŸ”₯ 전톡적인 ꡬ뢄뢀터 μ΄ν•΄ν•˜μž

πŸ’» 컴파일 μ–Έμ–΄ (C, C++ λ“±)

μ½”λ“œλ₯Ό μ‹€ν–‰ 전에 ν•œ λ²ˆμ— λ²ˆμ—­ν•˜λŠ” ν”„λ‘œκ·Έλž¨ (λΉ„μœ  : μ˜μ–΄ 책을 ν•œκ΅­μ–΄λ‘œ μ „λΆ€ λ²ˆμ—­ν•œ λ’€ μ½λŠ” 것)

μ½”λ“œ β†’ 컴파일 β†’ 기계어 β†’ μ‹€ν–‰
  1. 전체 μ½”λ“œλ₯Ό κΈ°κ³„μ–΄λ‘œ λ²ˆμ—­ν•œλ‹€.
  2. μ‹€ν–‰ 파일(.exe 같은 것) μƒμ„±ν•œλ‹€.
  3. κ·Έ λ‹€μŒμ— μ‹€ν–‰ν•œλ‹€.

νŠΉμ§•

  • μ‹€ν–‰ 전에 전체 μ½”λ“œλ₯Ό λ²ˆμ—­ν•œλ‹€.
  • μ‹€ν–‰ 속도가 λΉ λ₯΄λ‹€.
  • μ‹€ν–‰ 전에 μ—λŸ¬λ₯Ό λ°œκ²¬ν•  κ°€λŠ₯성이 μžˆλ‹€.

πŸ“ 인터프리터 μ–Έμ–΄ (μ˜ˆμ „ Python, μ˜› JS 인식)

μ½”λ“œλ₯Ό ν•œ 쀄씩 μ½μœΌλ©΄μ„œ λ°”λ‘œ μ‹€ν–‰ν•˜λŠ” ν”„λ‘œκ·Έλž¨ (λΉ„μœ  : μ˜μ–΄ 책을 ν•œ λ¬Έμž₯μ”© λ³΄λ©΄μ„œ κ·Έλ•Œκ·Έλ•Œ ν•΄μ„ν•˜λ©° μ½λŠ” 것)

μ½”λ“œ β†’ ν•œ 쀄씩 읽으며 μ‹€ν–‰
  • μ‹€ν–‰ν•  λ•Œλ§ˆλ‹€ 읽고 ν•΄μ„ν•œλ‹€.
  • 미리 기계어 νŒŒμΌμ„ λ§Œλ“€μ§€ μ•Šκ³  λ²ˆμ—­ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • 비ꡐ적 느릴 수 μžˆλ‹€.

그런데 JSλŠ” 이 λ‘˜ 쀑 ν•˜λ‚˜κ°€ μ•„λ‹ˆλ‹€

μ˜›λ‚ μ—λŠ” JSλ₯Ό 인터프리터라고 λΆˆλ €λ‹€. μ™œλƒν•˜λ©΄ β€œν•œ 쀄씩 읽으며 μ‹€ν–‰ν•œλ‹€β€ 라고 μ•Œλ €μ Έ μžˆμ—ˆκΈ° λ•Œλ¬Έμ΄λ‹€. ν•˜μ§€λ§Œ ν˜„λŒ€ μ—”μ§„(V8, SpiderMonkey λ“±)은 λ‹€λ₯΄κ²Œ λ™μž‘ν•œλ‹€.




πŸ”Ž μ‹€μ œ JS μ—”μ§„ λ™μž‘ 흐름 (V8 κΈ°μ€€ λ‹¨μˆœν™”)

1. 전체 μ½”λ“œ Parsing (νŒŒμ‹±) & AST 생성
2. ν•„μš”ν•œ λΆ€λΆ„λ§Œ Bytecode 생성
4. μ‹€ν–‰
5. 자주 ν˜ΈμΆœλ˜λŠ” 뢀뢄은 JIT μ΅œμ ν™”

1. Parsing

const a = 10;

엔진은 이걸 λ°”λ‘œ μ‹€ν–‰ν•˜μ§€ μ•Šκ³  λ¨Όμ € 전체 μ½”λ“œλ₯Ό 읽고 문법 λΆ„μ„ν•΄μ„œ 문법 ꡬ쑰둜 λ°”κΎΌλ‹€. (전체 슀크립트 λ‹¨μœ„λ‘œ μ§„ν–‰λœλ‹€.) β†’ AST (Abstract Syntax Tree)

즉, μ½”λ“œ ꡬ쑰λ₯Ό 트리둜 λ§Œλ“œλŠ” 거라고 λ³΄λ©΄λœλ‹€.

2. Bytecode둜 λ³€ν™˜ (컴파일)

ASTλŠ” λ°”λ‘œ μ‹€ν–‰λ˜μ§€ μ•Šκ³  엔진은 ASTλ₯Ό Bytecode(쀑간 μ½”λ“œ)둜 λ³€ν™˜ν•˜λŠ”λ° 이 과정이 이미 β€œμ»΄νŒŒμΌβ€μ΄λ‹€.

πŸ‘‰ μ—¬κΈ°μ„œ JSλŠ” 이미 인터프리터가 μ•„λ‹ˆλΌλŠ”κ±Έ 확인할 수 μžˆλ‹€.

μ—¬κΈ°μ„œ μ€‘μš”ν•œ 뢀뢄은 엔진은 μ„±λŠ₯κ³Ό 초기 λ‘œλ”© 속도 λ•Œλ¬Έμ— μ§€κΈˆ λ‹Ήμž₯ μ‹€ν–‰ μ•ˆ ν•  ν•¨μˆ˜λŠ” 깊게 μ»΄νŒŒμΌν•˜μ§€ μ•ŠλŠ”λ‹€. κ·Έλž˜μ„œ 이 κ³Όμ •μ—μ„œλŠ” ν•„μš”ν•œ λΆ€λΆ„λ§Œ Bytecode둜 μƒμ„±ν•œλ‹€.

3. μ‹€ν–‰

이 Bytecodeλ₯Ό 인터프리터가 μ‹€ν–‰ν•œλ‹€.

4. JIT (Just-In-Time) μ΅œμ ν™”

JSλŠ” μ–΄λ–€ ν•¨μˆ˜κ°€ 자주 μ‹€ν–‰λ˜λ©΄, 엔진은 κ·Έ 뢀뢄을 κΈ°κ³„μ–΄λ‘œ λ‹€μ‹œ μ»΄νŒŒμΌν•΄μ„œ μ΅œμ ν™” μ‹œν‚€λŠ”λ° 이걸 JIT라고 ν•œλ‹€. 즉, μ²˜μŒμ—” κ°€λ³κ²Œ μ‹€ν–‰ν•˜λ‹€κ°€ 자주 쓰이면 κ³ μ„±λŠ₯ μ½”λ“œλ‘œ μ—…κ·Έλ ˆμ΄λ“œλ₯Ό μ‹œν‚¨λ‹€.




🧢 핡심 정리

JSλŠ”:

  • 미리 전체λ₯Ό κΈ°κ³„μ–΄λ‘œ μ»΄νŒŒμΌν•˜μ§€λ„ μ•ŠλŠ”λ‹€.
  • ν•œ 쀄씩 λ‹¨μˆœ ν•΄μ„ν•˜μ§€λ„ μ•ŠλŠ”λ‹€.
  • μ‹€ν–‰ 쀑 μ΅œμ ν™”κΉŒμ§€ ν•œλ‹€.

JS 엔진은:

  • 일단 λŒμ•„κ°€κ²Œ λ§Œλ“ λ‹€.
  • 자주 쓰이면 μ΅œμ ν™”ν•œλ‹€.
  • κ·Έλž˜μ„œ JSλŠ” 생각보닀 λΉ λ₯΄λ‹€
  • μ „λž΅: Adaptive Optimization (μ²˜μŒμ—” κ°€λ³κ²Œ, 많이 쓰이면 λΉ λ₯΄κ²Œ μ „λž΅μ„ κ°€μ§€κ³  μžˆλ‹€.)

πŸ‘‰ 인터프리터 + 컴파일러 + JIT μ΅œμ ν™” μ—”μ§„ = JavaScript




더 깊게 νŒŒκ³ λ“€κΈ°

1. JSλŠ” μ™œ μ‹€ν–‰ 전에 μ—λŸ¬λ₯Ό μ „λΆ€ μž‘μ§€ λͺ»ν• κΉŒ?

  • JSλŠ” 정적 νƒ€μž… μ–Έμ–΄κ°€ μ•„λ‹ˆλ‹€.
    • JSλŠ” μ‹€ν–‰ 전에 νƒ€μž…μ„ ν™•μ •ν•  수 μ—†κΈ°λ•Œλ¬Έμ— let a =10 μ—μ„œ aκ°€ μˆ«μžμΈμ§€, λ¬Έμžμ—΄μΈμ§€, 객체인지 ν™•μ •ν•  수 μ—†λ‹€.
  • λ³€μˆ˜ 쑴재 μ—¬λΆ€λŠ” μ‹€ν–‰ μ‹œμ μ— κ²°μ •λœλ‹€
    • ν•¨μˆ˜ μ•ˆμ—μ„œ λ³€μˆ˜κ°€ μ‘΄μž¬ν•˜λŠ”μ§€λŠ” 호좜될 λ•Œ λ˜λŠ” ν•΄λ‹Ή μŠ€μ½”ν”„ 체인을 탐색할 λ•Œ κ²°μ •λ˜κΈ°μ— νŒŒμ‹± λ‹¨κ³„μ—μ„œλŠ” μž‘μ§€ λͺ»ν•œλ‹€.
  • Lazy Compilation
    • λ‹Ήμž₯ μ‹€ν–‰ μ•ˆ λ˜λŠ” ν•¨μˆ˜ λ‚΄λΆ€κΉŒμ§€ 깊게 μ΅œμ ν™”ν•˜μ§€ μ•Šκ³  λ¬Έλ²•λ§Œ λ‹€ κ²€μ‚¬ν•œλ‹€..

2. νƒ€μž…μ΄ 동적인데 μ–΄λ–»κ²Œ μ΅œμ ν™”κ°€ κ°€λŠ₯ν• κΉŒ?

function multiply(x, y) {
  return x * y;
}

μœ„μ˜ ν•¨μˆ˜λ₯Ό 엔진이 "κ΄€μ°°"ν•˜λ‹€κ°€ 같은 ν•¨μˆ˜λ₯Ό 1000번 μ‹€ν–‰ν–ˆλŠ”λ° x 와y κ°€ μ „λΆ€ 숫자 μ˜€λ‹€λ©΄ 엔진은 λ‚΄λΆ€μ μœΌλ‘œ ν•¨μˆ˜λ₯Ό 숫자 μ „μš©μ΄λΌκ³  μƒκ°ν•œλ‹€. κ·Έλž˜μ„œ 숫자 μ „μš© λ¨Έμ‹  μ½”λ“œλ‘œ μ΅œμ ν™”ν•œλ‹€.

ν•˜μ§€λ§Œ λ§Œμ•½, κ°‘μžκΈ° multiply("a",3) μ½”λ“œκ°€ λ“€μ–΄μ˜€λ©΄, 엔진은 νƒ€μž…μ΄ λ°”λ€œμ„ μΈμ§€ν•˜κ³  μ΅œμ ν™” μ½”λ“œλ₯Ό 버리고 λ‹€μ‹œ 일반 μ½”λ“œλ‘œ λŒμ•„κ°„λ‹€. 이걸 de-optimization이라고 ν•œλ‹€.