[Javascript] Object vs Map

Falcon·2022년 1월 24일
1

javascript

목록 보기
12/28
post-thumbnail

🎯 Goals

  • 언제 Object 를 쓰고, 언제 Map 을 써야할까?
  • 배열을 키-값 형태의 Object, Map 으로 만드는데 소요되는 시간 차이는?
  • 추가, 삭제 성능 차이? (업데이트 예정)

테스트 (Array -> Object, Array -> Map)

다음과 같은 형태를 갖는 Dummy 데이터를 생성했다.

interface User {
    id: number;
    name: string;
    email: string;
    registerDate: string;
}
[
  {
    "id":81662,
    "name":"Isaac Graham",
    "email":"Russell.Watsica27@example.org",
    "registerDate":"Sun Jan 23 2022 21:38:33 GMT+0900 (Korean Standard Time)"
  },
  {
    "id":92228,
    "name":"Timothy Romaguera",
    "email":"Pink.Haley26@example.org",
    "registerDate":"Mon Jan 24 2022 06:15:19 GMT+0900 (Korean Standard Time)"
  }, 
  {
    ...
  }

Array To Object

function arrayToObject(users : User[]) {
    // key: id, value: 나머지 모든 값

    return users.reduce((previousObj, currentValue)=>{
        return {
            // previousObj has already previous key value pair
            ...previousObj,
            [currentValue.id] : currentValue
        }
    }, {});
}

Array To Map

function arrayToMap(users : User[]) {
    const userTable : Map<id, User> = new Map();

    for (const user of users) {
        if (userTable.has(user.id)) {
            //NOTHING TO DO
        } else {
            userTable.set(user.id, user);
        }
    }
}

만들고자 하는 테이블은 사용자의 아이디를 키값으로 갖고 모든 정보를 값으로 갖는다.

📊 테스트 결과

테이블로 변환하는 데이터 갯수에 따라 다음과 같은 소요시간이 측정되었다.

user100
  Data byte length: 14.6 kB
  arrToObject: 1.907ms
  arrToMap: 0.052ms
user1000
  Data byte length: 147 kB
  arrToObject: 186.226ms
  arrToMap: 0.125ms
user10000
  Data byte length: 1.46 MB
  arrToObject: 39.957s
  arrToMap: 3.304ms

유저 수가 1만명에 도달하니 오브젝트로의 변환은 무려 39.9초가 소요되었다.
반면에, 맵으로의 변환은 3ms 로 매우 훌륭한 성능을 보여주었다.

테스트 환경


Node.js 버전은 14.17.5 를 사용했다.

원인

arrToObject 메소드는 매번 데이터를 추가할 때마다 모든 데이터를 펼친다. (Spread)

... (Spread)

    return users.reduce((previousObj, currentValue)=>{
        return {
            ...previousObj, // 💡 Spread
            [currentValue.id] : currentValue
        }
    }, {});

이는 사전(테이블)에 데이터를 하나씩 추가할 때마다 테이블을 열고 (펼치고) 추가하고 닫는 과정을 반복하는 것이다.

📝 결론

배열을 오브젝트로 reduce 와 spread 를 사용해 변환하는 것 보다 Map 을 생성하는게 훨씬 빠르다.
그럼, 무조건 Map을 사용하는게 좋은가? 꼭 그렇지만은 않다.
Map 은 JSON.stringify() 로 데이터를 곧바로 변환할 수가 없기 때문에
JSON 으로 데이터를 주고받고자 할 때 별도의 파서를 사용하거나 다음과 변환 과정이 필요하다.

const map1 = new Map([
  ['name', 'falcon'],
  ['postNumber', 192]
]);

const obj = Object.fromEntries(map1);
// { name: 'falcon', postNumber: 192 }
const jsonData = JSON.stringify(obj);

따라서, 배열로부터 테이블을 생성하고자 할 때 다음과 같은 기준을 갖고 구현 방식을 결정하기로 했다.

Array to Object

  • JSON 데이터를 주고 받아야 할 때
  • 처리할 데이터 양이 적을 때
    (나는 나름대로 0.1MB 라는 기준을 정했다.)

Array to Map

  • 외부 API 로 JSON 을 주고받지 않을 때
  • 처리할 데이터 양이 많을 때
  • 애플리케이션 내에서 테이블을 계속 유지해야할 때

p.s.

reduce 를 활용한 배열-> 오브젝트 변환 방식은 스택오버플로우에서 찾았다.

최초 글 등록일이 2011년이라 "너무 예전 방식 써서 그런거 아니야?" 라고 할 수도 있겠지만 2019년에 등재된 다른 기술 포스트 글 에도 이와 유사한 방식의 코드 스니펫을 볼 수 있었다.

원하는 기능의 코드 스니펫을 아무데서나 찾고, IDE에서 적은 데이터로 돌려보고 "어, 돌아가네?" 하고 썼다간 이렇게 예상치 못한 경우에 당황스러운 상황이 발생할 수 있겠다는 교훈을 얻었다.

profile
I'm still hungry

0개의 댓글