귀하는 로그인되어 있지 않습니다. 이대로 편집하면 귀하의 IP 주소가 편집 기록에 남게 됩니다.스팸 방지 검사입니다. 이것을 입력하지 마세요!== 구조와 동작 원리 == === 파싱과 추상 구문 트리 === V8은 JavaScript 소스 코드를 먼저 파싱하여 내부 표현으로 변환한다. 이 단계에서는 문법 오류를 검사하고, 스크립트 또는 모듈의 구조를 분석하며, 함수, 변수, 클래스, 블록, 표현식 등의 관계를 파악한다. 일반적으로 JavaScript 엔진은 소스 코드를 토큰화하고, 파서가 이를 구문 트리 형태로 구성한 뒤, 실행에 적합한 내부 형식으로 변환한다. V8은 전체 코드를 처음부터 모두 무겁게 컴파일하지 않는다. 실제 웹 페이지와 서버 프로그램에서는 많은 함수가 전혀 호출되지 않거나 드물게 호출된다. 따라서 V8은 필요한 부분을 늦게 파싱하거나 컴파일하는 방식으로 시작 시간을 줄이고 메모리 사용량을 낮춘다. === Ignition 인터프리터 === '''Ignition'''은 V8의 JavaScript 인터프리터이다. Ignition은 JavaScript를 V8 내부 바이트코드로 변환하고, 이 바이트코드를 실행한다.<ref name="ignition-turbofan" /> 바이트코드는 원본 JavaScript보다 실행 엔진이 다루기 쉽고, 이후 Sparkplug, Maglev, TurboFan 같은 컴파일러가 참고할 수 있는 기반이 된다. Ignition의 중요한 역할은 단순 실행뿐 아니라 피드백 수집이다. V8은 함수 호출, 객체 속성 접근, 산술 연산, 배열 접근, 함수 인자 타입 등에 대한 정보를 실행 중에 수집한다. 이 정보는 나중에 코드를 최적화할 때 사용된다. === 인라인 캐시와 타입 피드백 === JavaScript는 동적 타입 언어이므로 같은 코드가 서로 다른 타입의 값을 처리할 수 있다. 예를 들어 `obj.name`이라는 속성 접근은 어떤 순간에는 일반 객체의 문자열 속성을 읽을 수도 있고, 다른 순간에는 전혀 다른 구조의 객체를 읽을 수도 있다. V8은 이러한 동적 특성을 다루기 위해 '''인라인 캐시'''와 '''타입 피드백'''을 사용한다. 특정 코드 위치에서 반복적으로 같은 형태의 객체가 등장하면 V8은 그 패턴을 기록하고, 다음 실행 때 더 빠른 경로를 사용할 수 있다. 예를 들어 어떤 객체가 같은 hidden class 또는 map 구조를 가진다면, V8은 속성 이름을 매번 일반적인 해시 검색으로 찾지 않고 정해진 오프셋에서 빠르게 읽을 수 있다. === Hidden class와 Map === V8은 JavaScript 객체의 구조를 내부적으로 '''Map''' 또는 hidden class에 가까운 개념으로 표현한다. JavaScript 객체는 실행 중 속성이 추가되거나 삭제될 수 있지만, 실제 프로그램에서는 같은 생성자나 같은 객체 리터럴에서 만들어진 객체들이 비슷한 구조를 갖는 경우가 많다. V8은 이 구조적 공통성을 이용해 속성 접근을 최적화한다. 예를 들어 다음과 같은 객체들이 반복적으로 만들어진다고 가정할 수 있다. <syntaxhighlight lang="javascript"> function User(name, age) { this.name = name; this.age = age; } const a = new User("Kim", 20); const b = new User("Lee", 25); </syntaxhighlight> `a`와 `b`는 같은 순서로 `name`, `age` 속성이 추가되므로 내부적으로 비슷한 구조를 공유할 수 있다. V8은 이 점을 활용하여 `user.name` 같은 접근을 빠르게 만든다. === Sparkplug 컴파일러 === '''Sparkplug'''는 Ignition이 만든 바이트코드를 바탕으로 빠르게 기계어를 생성하는 비최적화 컴파일러이다.<ref name="sparkplug" /> Sparkplug는 복잡한 최적화 분석을 수행하지 않으므로 컴파일 비용이 낮다. 대신 인터프리터보다 빠른 실행 속도를 제공한다. Sparkplug의 핵심 가치는 시작 직후의 성능 개선이다. 웹 페이지는 사용자가 기다리지 않도록 빠르게 반응해야 하고, 서버 애플리케이션도 요청을 지연 없이 처리해야 한다. Sparkplug는 최적화 컴파일러가 충분한 정보를 모으기 전까지의 중간 성능을 높이는 역할을 한다. === Maglev 컴파일러 === '''Maglev'''는 Sparkplug와 TurboFan 사이에 위치한 중간 단계 최적화 컴파일러이다.<ref name="maglev" /> Maglev는 정적 단일 할당 형태와 제어 흐름 그래프 기반 구조를 사용하여 비교적 빠르게 최적화 코드를 생성한다. TurboFan만큼 깊은 최적화를 수행하지는 않지만, Sparkplug보다 훨씬 나은 실행 성능을 목표로 한다. Maglev의 도입은 V8의 실행 파이프라인을 더 세밀하게 만들었다. 단순히 인터프리터와 최종 최적화 컴파일러 사이에서 오가는 것이 아니라, 코드의 실행 빈도와 안정성에 따라 적절한 단계의 컴파일러를 선택할 수 있게 된 것이다. === TurboFan 컴파일러 === '''TurboFan'''은 V8의 고성능 최적화 컴파일러이다. 자주 실행되고 타입 정보가 안정적인 코드는 TurboFan에 의해 더 깊게 최적화될 수 있다.<ref name="ignition-turbofan" /> TurboFan은 인라인 확장, 불필요한 검사 제거, 상수 접기, dead code elimination, bounds check 최적화, escape analysis 등 다양한 컴파일러 최적화 기법을 적용할 수 있다. TurboFan은 JavaScript의 동적 특성 때문에 추측적 최적화를 많이 사용한다. 예를 들어 어떤 함수가 계속 숫자만 처리한다면, V8은 그 함수가 앞으로도 숫자를 처리할 것이라고 가정하고 숫자 연산에 특화된 빠른 코드를 만들 수 있다. 그러나 나중에 문자열이나 객체가 들어오면 그 가정은 깨질 수 있다. 이때 V8은 최적화된 코드를 버리고 안전한 코드 경로로 되돌아간다. === Deoptimization === '''Deoptimization'''은 V8 같은 JIT 엔진에서 매우 중요한 개념이다. 최적화 컴파일러는 실행 중 수집한 정보를 바탕으로 “이 코드는 앞으로도 이런 타입을 받을 가능성이 높다”는 가정을 세우고 빠른 코드를 만든다. 그러나 JavaScript는 동적 언어이므로 그 가정이 언제든 깨질 수 있다. 가정이 깨지면 V8은 최적화된 코드를 계속 실행하지 않고, 더 일반적인 코드 상태로 되돌아간다. 이 과정을 deoptimization이라고 한다. Deoptimization은 JavaScript의 유연성을 유지하면서도 일반적인 경우에는 빠르게 실행하기 위한 핵심 장치이다. === 가비지 컬렉션 === V8은 자동 메모리 관리를 위해 [[가비지 컬렉션]]을 수행한다. JavaScript 개발자는 일반적으로 객체를 명시적으로 해제하지 않고, 더 이상 도달할 수 없는 객체는 엔진이 회수한다. V8의 가비지 컬렉터는 세대별 수집, 증분 처리, 병렬 처리, 동시 처리 등을 활용하여 중단 시간을 줄이고 처리량을 높이는 방향으로 발전하였다. V8의 '''Orinoco''' 프로젝트는 가비지 컬렉션 작업을 병렬화하고 동시화하여 웹 페이지와 애플리케이션의 끊김을 줄이는 데 초점을 맞추었다.<ref name="v8-10years" /> 특히 브라우저 환경에서는 가비지 컬렉션으로 인해 사용자 인터페이스가 멈추는 현상이 체감 성능에 큰 영향을 주기 때문에, GC의 지연 시간을 줄이는 것이 중요하다. === 메모리 최적화 === V8은 성능뿐 아니라 메모리 사용량도 중요하게 다룬다. 모바일 기기, 저사양 장치, 서버의 고밀도 워크로드에서는 메모리 사용량이 곧 비용과 사용자 경험으로 이어진다. 대표적인 메모리 최적화로는 다음이 있다. * '''Pointer compression''': 64비트 환경에서 포인터를 압축하여 힙 메모리 사용량을 줄이는 기술이다.<ref name="pointer-compression">{{웹 인용|url=https://v8.dev/blog/pointer-compression|제목=Pointer Compression in V8|웹사이트=V8.dev|출판사=Google|날짜=2020-03-30|확인날짜=2026-06-16}}</ref> * '''Embedded builtins''': 여러 isolate가 공통 내장 코드를 공유하여 메모리 중복을 줄이는 방향의 최적화이다. * '''Startup snapshot''': 초기 실행에 필요한 객체와 내장 함수 상태를 스냅샷으로 저장하여 시작 속도를 높인다. * '''Code caching''': 이미 컴파일된 코드나 파싱 결과를 재사용하여 반복 실행 비용을 줄인다. 편집 요약 가온 위키에서의 모든 기여는 크리에이티브 커먼즈 저작자표시-동일조건변경허락 라이선스로 배포된다는 점을 유의해 주세요(자세한 내용에 대해서는 가온 위키:저작권 문서를 읽어주세요). 만약 여기에 동의하지 않는다면 문서를 저장하지 말아 주세요. 또한, 직접 작성했거나 퍼블릭 도메인과 같은 자유 문서에서 가져왔다는 것을 보증해야 합니다. 저작권이 있는 내용을 허가 없이 저장하지 마세요! 취소 편집 도움말 (새 창에서 열림)