신입 개발자에서 시니어 개발자가 되기까지

javascript fast Property mode(히든클래스) vs dictionary mode 본문

카테고리 없음

javascript fast Property mode(히든클래스) vs dictionary mode

Jin.K 2025. 4. 19. 01:45

히든 클래스에 대해서 공부하다보니 자바스크립트의 객체를 메모리에 저장할 때 두 가지 형태가 있다는 걸 알았다.

내가 이때까지 이해하고 있었던 객체는 dictionary mode에 가까움. key-value 쌍으로 이루어진 자료구조가 내가 이해한 객체였고, 그래서 객체는 key값에 접근하면 바로 value를 반환하기 때문에 O(1)으로 생각하고 있었다. 근데 히든클래스에 대해 공부하다보니 이건 완전히 오해였다.

히든 클래스 big O

결론적으로 히든 클래스 형태로 저장된 객체의 값에 접근할 때는 O(1)

Dictionary 형태의 객체에 접근할 때는 O(log n) ~ O(n)이라고 한다.

히든 클래스란?

객체를 선언 했을 때 객체의 속성과 타입이 고정되어 새로운 속성을 추가할 수 없는 정적 언어와 달리 자바스크립트는 객체를 선언했을 때와 다른 속성, 타입을 추가할 수 있다. 이런 특성때문에 성능면에서는 불리한데 이걸 보완해주기 위한 최적화 기법이 히든 클래스라고 한다. (JIT 최적화 중 하나)

히든 클래스, dictionary가 메모리에 저장되는 형태

히든 클래스 구조로 객체를 저장하면, 객체를 key-value 쌍의 형태로 메모리에 저장하는게 아니라, property의 이름(key)과 오프셋(key의 순서)를 저장한다.

const obj = { 
name : 'hj',
age: 35
}

객체가 있다고 하면, V8엔진에서 이 객체에 히든 클래스를 가리키는 Map Pointer를 저장한다. hidden class에는 name => 0, age =>1 의 형태로 프로퍼티의 이름과 그 이름의 순서를 저장한다. 그리고 실제 값은 Property Array로 저장하는데, 값만 따로 순서대로 배열 형태로 저장한다.

그래서 obj[name]으로 접근하면 바로 0번째에 있는 값을 가져온다.

이 때, 최적화를 위해 엔진 내부적으로 transition map이라는 걸 관리한다고 한다.

EX) C0 --(add 'name')--> C1 --(add 'age')--> C2

이런식으로 C0 히든클래스, C1 히든클래스, C2 히든 클래스를 만들어서 객체의 프로퍼티 추가 순서가 같으면 동일한 히든 클래스를 사용한다고 한다. 그래서 객체의 구조가 같으면 프로퍼티 추가 순서를 동일하게 해야 최적화를 할 수 있다고 한다. 객체의 프로퍼티가 동일해도 순서가 다르면, 다른 트랜지션을 사용해서 성능이 비교적 떨어진다.

delete 키워드를 사용하면 fast mode에서 dictionary 형태로 값을 저장한다고 한다. (dictionary는 다른 언어에서는 해당 타입이 있다고 함) key-value 쌍으로 저장하는 해시 테이블임. 아무튼 이걸 그대로 메모리에 저장해서 객체 값에 접근하면 key,value를 훑어서 찾기 때문에 히든 클래스보다 느리다.

히든 클래스가 dictionary로 전환될 때는?

delete를 쓰면 그렇다고 한다. delete 종종 사용했는데 사용하면 안 될 듯..

최적화가 중요할 때는 obj.name = undefined 으로 사용하라고 한다.

히든 클래스를 잘 사용하려면? (JIT 최적화를 하려면)

  1. 객체 선언할 때 모든 속성을 정의하면 좋다.
  2. 속성 추가 순서를 일관되게 해야 한다.
  3. 객체 구조를 되도록 고정시켜라.