Javascript - 맵(Map)을 알아보자

2022. 4. 27. 16:01·👨‍💻 Dev Note/JavaScript
반응형

자바스크립트로 개발하면서 가장 많이 사용하게 되는 자료구조에는 객체와 배열이 있다. 객체는 키가 있는 컬렉션을 저장할 수 있고, 배열은 순서가 있는 컬렉션을 저장한다. 하지만 점차 복잡해져가는 소프트웨어 시장속에서 위의 두 자료구조만으로 개발하기에는 코드가 많이 복잡해짐에 따라 맵(Map)과 셋(Set)이 등장하게 됐다. (Set에 관해서는 다음 포스팅에서 다뤄볼 예정이다)

 

맵 (Map)

맵은 키가 있는 데이터를 저장한다는 관점에서는 객체와 유사하다. 하지만 맵은 키에 다양한 자료형을 허용한다는 점에서 차이가 있다.

아래의 코드처럼 다양한 자료형을 Key에 사용할 수 있다.

let map = new Map();

map.set('1', '1'); // 문자 Key
map.set(1, 'one');  // 숫자 key
map.set(true, 'bool_true'); // Boolean Key

 

맵의 메서드

위의 코드에서 볼 수 있듯 맵을 사용할 때는 메서드를 활용한다. 아래는 map의 주요 메서드 및 프로퍼티 목록이다.

  • new Map()
    맵을 만든다.
  • map.set(key, value)
    key값에 해당하는 value를 저장한다. 반환값은 맵 자신이다.
  • map.get(key)
    key에 해당하는 value를 반환한다. key가 존재하지 않는 경우 undefined를 반환한다.
  • map.has(key)
    key값이 있는지 확인한다. 존재하면 true, 존재하지 않는다면 false를 반환한다.
  • map.delete(key)
    key와 해당하는 값을 삭제한다
  • map.clear()
    맵 안의 모든 데이터를 삭제한다.
  • map.size
    맵에 저장된 사이즈를 반환한다.
  • map.keys()
    각 요소의 key를 모은 iterable 객체를 반환한다.
  • map.values()
    각 요소의 value를 모은 iterable 객체를 반환한다.
  • map.entries()
    요소의 [key, value]를 한 쌍으로 하는 iterable 객체를 반환한다. 이 객체는 for..or 반목문의 기초로 사용된다.

맵을 사용하면서 주의해야 할 사항은, 맵은 객체와 달리 키를 문자형으로 반환하지 않는다는 점이다. 키에는 자료형 제약이 없기 때문이다.

map[key] = value 와 같이 설정하는 방법을 사용할 수 있지만, 이렇게 사용했을 경우 map을 일반 객체처럼 취급하게 되어 여러 제약이 생기게 된다. 따라서 map을 사용할 때에는 get, set등의 메서드를 사용해야 한다.

 

객체를 키로 활용하기

맵은 다양한 자료형을 키로 사용할 수 있는데, 객체 역시 허용한다. 키엔 자료형의 제약이 없다.

let spr = { name: "soopiri" };

let moneyMap = new Map();

moneyMap.set(spr, 10000);

console.log(moneyMap.get(spr)); // 10000

 

객체를 키로 사용할 수 있다는 것은 맵의 활용도를 확장시켜주는 가장 중요한 기능 중 하나이다. 객체에는 문자열 키를 사용할 수 있지만 객체 키는 사용할 수 없다. 객체형 키를 객체에 사용하면 어떻게 될까? 아래 코드를 살펴보자.

let spr = { name: 'soopiri' };

let moneyObj = {};

moneyObj[spr] = 10000

// moneyObj는 객체이기 때문에 모든 키를 문자형으로 변환시킨다.
// 이 과정에서 spr은 문자형으로 변환되어 '[object Object]'로 변한다.
// 이 때문에 객체는 객체키를 사용할 수 없다.
console.log(moneyObj['[obejct Object]'])

 

맵의 key 비교 알고리즘

맵은 SameValueZero라고 불리는 알고리즘을 통해 값의 등가 여부를 확인한다. 이 알고리즘은 일치 연산자 (===)와 거의 비슷하지만, NaN과 NaN을 같다고 취급하는 것에서 일치 연산자와는 차이가 있다. 이 말은 맵에선 NaN도 키 값으로 활용할 수 있다.

SameValueZero 알고리즘은 수정 및 커스티마이징이 불가능하다.

 

Chaining

map.set의 반환 값은 맵 자신이다. 이를 활용하여 map.set 메서드를 체이닝 할 수 있다.

// example map chaining
map.set('s', 'soo').set(1, 'one').set(true, '참');

 

맵의 요소에 반복 작업하기

위에서 언급한 keys(), values(), entries() 메서드를 통해, 맵의 각 요소에 반복 작업을 할 수 있다. 아래 코드를 살펴보자.

let priceMap = new Map([
    ['iPhone', 1300], ['iPad', 1500], ['macbook', 3000]
]);

// key iterate
for (let product of priceMap.keys()){
    console.log(product) // iPhone, iPad, macbook
}

// value iterate
for (let price of priceMap.values()){
    console.log(price) // 1300, 1500, 3000
}

// [key, value] iterate
for (let pp of priceMap) {
    console.log(pp)
    // ['iPhone', 1300]
    // ['iPad', 1500]
    // ['macbook', 3000]
}

// foreach loop
priceMap.forEach( (value, key, map) => {
  console.log(value)
});

맵의 삽입 순서

맵은 값이 삽입(set) 된 순서를 기억하여 순서대로 반복한다. 객체가 Property의 순서를 기억하지 못하는 것과 다른 모습이다.

 

객체를 맵으로 바꾸기 (Object.entries)

위에서 살펴본 바와 같이 각 요소가 key, value 쌍인 iterable 객체 또는 배열을 초기화 용도로 맵에 전달하여 맵을 만들 수 있다.

더 나아가 평범한 객체를 가지고 맵을 만들고 싶다면 Object.entries(obj) 내장 함수를 활용하면 된다. 이 함수는 객체의 key, value 쌍을 [key, value]를 요소로 가지는 배열을 반환한다.

let obj = {
    name: 'soopiri',
    age: 99
}

let map = new Map(Object.entries(obj));

console.log(map.get('name')) // soopiri

Object.entries 함수를 통해 객체 obj를 배열 [['name',  'soopiri'], ['age',  99]]로 변경하여, 해당 배열을 이용해 맵을 만든 코드이다.

 

맵을 객체로 바꾸기 (Object.fromEntries)

반대로, 맵을 객체로 바꾸는 방법도 있다. Object.fromEntries 메서드를 활용하여 각 요소가 [key, value]쌍인 배열을 객체로 변경해준다.

let map = new Map();
map.set('s', 'o');
map.set('p', 'i');
map.set('r', 'i');

// change map to normal object
let obj = Object.fromEntries(map.entries());

// obj = {s: 'o', p: 'i', r: 'i' }

 

마무리하며..

맵(Map)은 Key가 있는 Value가 저장된 Collection이며, 메소들을 활용하여 사용한다. 일반적인 객체와의 차이점은 Key값의 타입에 제약이 없으며 객체 역시 Key가 될 수 있다. size등의 유영한 method나 property를 활용할 수 있다.

 

 

참고링크

JAVASCRIPT.INFO

반응형
저작자표시 비영리 변경금지 (새창열림)

'👨‍💻 Dev Note > JavaScript' 카테고리의 다른 글

Javascript - 원시값(Primitive)의 메서드  (0) 2022.04.27
Javascript - Set을 알아보자  (0) 2022.04.27
구조 분해 할당(Destructuring Assignment) - 객체, 중첩구조 편  (0) 2022.04.26
구조 분해 할당(Destructuring Assignment) - 배열편  (0) 2022.04.25
콜백지옥 (Callback Hell)과 비동기(async) 처리  (0) 2022.04.23
'👨‍💻 Dev Note/JavaScript' 카테고리의 다른 글
  • Javascript - 원시값(Primitive)의 메서드
  • Javascript - Set을 알아보자
  • 구조 분해 할당(Destructuring Assignment) - 객체, 중첩구조 편
  • 구조 분해 할당(Destructuring Assignment) - 배열편
수피리
수피리
다양한 시도를 통해, 나만의 방식과 감각을 찾는 중
  • 수피리
    경험기록 아카이브
    수피리
  • 전체
    오늘
    어제
    • 분류 전체보기 (56)
      • 🌿 My Side B (13)
        • 🏕️ 캠핑 (1)
        • 🍜 맛집 탐방 (3)
        • ✍️ 블로그 전략 (3)
        • 🌱 나를 브랜딩하다 (5)
        • 🏋️‍♀️ 운동 (1)
      • 📝 Tips (7)
        • 💻 Tech Tips (4)
        • ⚒️ Tool Tips (3)
        • 🧠 Life Tips (0)
      • 👨‍💻 Dev Note (36)
        • JavaScript (8)
        • TypeScript (5)
        • React (3)
        • 디자인패턴 (10)
        • Git (2)
        • Redis (1)
        • 코딩테스트 (7)
  • 인기 글

  • 최근 글

  • 태그

    javascript
    TypeScript
    코딩테스트
    designpatterns
    designPattern
    디자인패턴
    퍼스널브랜딩
    타입스크립트
    코딩테스트 연습
    Programming
  • hELLO· Designed By정상우.v4.10.3
수피리
Javascript - 맵(Map)을 알아보자
상단으로

티스토리툴바