Gitsunmin

TIL

TIL
(=Today I Learned)

Hidden Class

개요

JavaScript는 동적 타이핑 언어로, 객체에 프로퍼티를 자유롭게 추가하거나 삭제할 수 있습니다. 이러한 유연성은 개발에 편리함을 제공하지만, 성능 측면에서는 도전 과제가 될 수 있습니다. V8 엔진은 이러한 문제를 해결하기 위해 “히든 클래스(Hidden Class)“라는 내부 메커니즘을 도입하여 객체의 구조를 추적하고 최적화합니다.

히든 클래스란?

히든 클래스는 V8 엔진이 JavaScript 객체의 구조를 추적하고 최적화하기 위해 사용하는 내부 메타데이터 구조입니다. 객체의 프로퍼티 이름과 추가 순서 등을 기반으로 생성되며, 동일한 구조를 가진 객체들은 동일한 히든 클래스를 공유합니다. 이를 통해 프로퍼티 접근 시 메모리 오프셋을 이용한 빠른 접근이 가능해집니다.

히든 클래스의 구성 요소

  • Map: 객체의 구조(프로퍼티 정보 등)를 설명하는 메타데이터 객체로, 해당 객체가 어떤 프로퍼티를 어떤 순서로 가지는지를 정의합니다.
  • DescriptorArray: 각 프로퍼티의 이름, 타입, 접근자 등을 저장한 배열입니다.
  • TransitionArray: 현재 히든 클래스에서 새로운 프로퍼티가 추가되었을 때 어떤 히든 클래스로 전이되는지를 설명하는 정보입니다.

많은 경우, TransitionArray 대신 단일 포인터 전이가 사용되며 이는 더 빠른 탐색을 가능하게 합니다.

히든 클래스의 생성과 전이 예시

function Peak(name, height, extra) {
  this.name = name;
  this.height = height;
  if (isNaN(extra)) {
    this.experience = extra;
  } else {
    this.prominence = extra;
  }
}

const m1 = new Peak("Matterhorn", 4478, 1040);   // prominence 속성 보유
const m2 = new Peak("Wendelstein", 1838, "good"); // experience 속성 보유

위 코드에서 m1m2는 서로 다른 구조를 가지므로, 서로 다른 히든 클래스를 생성하게 됩니다. 이러한 전이(transitions)는 히든 클래스 간의 트리를 형성하게 되며, 최적화된 객체 탐색이 가능하게 됩니다.

TypeScript와 히든 클래스 최적화의 관계

TypeScript는 정적 타입 시스템을 제공하여 코드 작성 시점에 객체 구조를 명확히 정의할 수 있게 합니다. 런타임에 직접적인 최적화를 수행하진 않지만, 다음과 같은 간접적인 이점이 존재합니다:

  • 객체 구조를 사전에 명확히 정의하게 하여 일관성을 유지하게 유도합니다.
  • 동일한 구조의 객체를 생성하도록 도와 V8 엔진이 히든 클래스를 재사용할 수 있게 합니다.

예시:

type User = {
  id: number;
  name: string;
  age: number;
};

const a: User = { id: 1, name: "Kim", age: 30 };
const b: User = { id: 2, name: "Lee", age: 28 };

이러한 코드 구조는 a, b 객체가 같은 히든 클래스를 공유하도록 하여 V8 최적화에 유리한 패턴을 형성합니다.

주의할 점은 TypeScript에서도 as any, delete, 동적 속성 추가 등은 히든 클래스 최적화를 방해할 수 있다는 것입니다:

const obj = {} as any;
obj.x = 1;
obj.y = 2;
delete obj.x;

히든 클래스 최적화를 위한 팁

  • 생성자 함수 내에서 객체의 모든 속성을 초기화하세요.
  • 객체 생성 이후에는 가능한 프로퍼티를 추가하거나 삭제하지 마세요.
  • 프로퍼티를 항상 동일한 순서로 추가하세요.
  • delete 키워드를 지양하세요. 이는 객체를 사전(dictionary) 모드로 전환시켜 성능 저하를 초래합니다.

결론

히든 클래스는 V8 엔진이 JavaScript의 유연한 객체 모델을 고성능으로 유지할 수 있도록 해주는 중요한 최적화 메커니즘입니다. 코드 작성 시 객체의 구조를 일관되게 유지하고 불필요한 동적 변경을 피하면, 엔진 최적화의 혜택을 누릴 수 있습니다.

특히 TypeScript와 함께 사용하면 객체 구조의 일관성을 자연스럽게 유지할 수 있으므로, 히든 클래스 기반 최적화를 유도하는 데에도 큰 도움이 됩니다.

자세한 사항은 V8 공식 문서 https://v8.dev/docs/hidden-classes 를 참고하면 좋습니다.