자바스크립트 맵 객체(Map Object)
자바스크립트로 앱을 개발할 때 꼭 사용하는 자료형이 바로 객체(Object)일텐데요. 값을 키와 값으로 묶어 저장하고 조회하는 기능은 어떤 앱을 개발할 때나 쓰게 되는 경우가 많습니다. 이번 포스팅에서는 자바스크립트 객체를 좀 더 뺀-씨하게 사용할 수 있는 ES6 문법인 맵 객체에 대해 알아보려 합니다.
맵 객체 메소드
맵 객체는 기존 객체와는 다르게 메소드만을 이용해 값을 넣고 뺍니다. 기본적으로 삽입, 조회, 삭제를 할 수 있는 메소드들은 다음과 같습니다.
let max = new Map();
// set으로 맵 객체에 삽입
max.set('id', 0);
max.set('이름', '마이클');
max.set('전공', '영문학');
max.set('나이', 25);
// 이차원 배열로 넘겨주는 것도 가능합니다
let michael = new Map([
['id', 0],
['이름', '마이클'],
['전공', '영문학'],
['나이', 29],
]);
// get으로 맵 객체 조회
max.get('이름'); // "마이클"
// delete로 삭제
max.delete('나이'); // 삭제가 성공하면 true를 반환
// clear로 맵 안의 프로퍼티 전부삭제
max.clear();
이외에도 다른 메소드를 쓸 수 있습니다. 객체의 메소드가 매우 제한적인것에 반해, 맵 객체는 풍부한 메소드를 제공하고 있습니다. 맵 객체의 다른 메소드는 여기를 참조하세요!
맵 객체의 장점
문자열 아닌 값도 키로 사용 가능
객체에서는 문자열(String) 혹은 심볼(Symbol)만 프로퍼티의 키로 사용할 수 있었는데요. 맵 객체에서는 함수나 객체를 포함한 모든 자료형이 프로퍼티의 키로 쓰일 수 있습니다.
종종 키가 문자열이 아니라 숫자(Number)일 때 보기 더 편한 경우가 있습니다. 가령 오류코드에 따라 출력하는 메시지에 대한 정보를 가지고 있는 객체와 맵 객체를 생각해 볼게요.
const errorMessageObj = {
404 : "페이지가 없습니다",
500 : "서버 오류입니다",
401 : "권한이 없습니다"
}
const errorMessageMap = new Map([
[404, "페이지가 없습니다"],
[500, "서버 오류입니다"],
[401, "권한이 없습니다"],
])
errorMessageObj.404 // unexpected number 에러
errorMessageObj["404"] // '페이지가 없습니다'
errorMessageMap.get(404) // '페이지가 없습니다'
객체의 경우는 문자열을 통해서만 조회가 가능하고, .
뒤에 숫자를 입력하면 에러가 납니다. 하지만 맵 객체에서는 get
메소드의 인자로 숫자를 넘겨줘도 제대로 값을 찾아오는 것을 보실 수 있습니다.
메소드 사용의 명확성
일단 맵 객체를 다룰 때는 객체처럼 .
이나 []
로 접근할 필요 없이 메소드만으로 맵 객체 안에 들어있는 프로퍼티들을 수정하거나 조회할 수 있습니다. 메소드의 이름들(set
, get
, delete
, clear
)이 맵 객체를 어떻게 할지를 잘 나타내주고 있어, 객체보다 동작과 의도 를 더 정확하게 보여준다고 할 수 있습니다.
let maxInfoObj = {
name: '김맥스',
age: 25,
major: '영문학',
};
const maxInfoMap = new Map([
['name', '김맥스'],
['age', 25],
['major', '영문학'],
]);
// 객체 : let으로 선언해 빈 객체 할당해서 빈 객체로 초기화
maxInfoObj = {};
// 맵 객체 : clear 메소드 사용해 빈 맵 객체로 초기화
maxInfoMap.clear();
특히 맵의 프로퍼티를 명시적으로 지울 수 있는 clear
나 delete
같은 메소드를 제공하는게 인상적입니다. 객체의 경우처럼 삭제시 빈 객체를 할당하는 것 보다 개발자의 의도를 명확히 드러낸다고 할 수 있습니다.
깔끔한 순회
맵 객체는 그 자체로 for..of
문을 통해 순회가 가능합니다. 이때 순회는 맵 이터레이터의 형태로 이루어집니다. 맵 이터레이터는 키-값을 쌍으로 묶은 배열입니다. entries
메소드로 맵 이터레이터를 확인할 수 있습니다.
const maxInfoMap = new Map([
['name', '김맥스'],
['age', 25],
['major', '영문학'],
]);
maxInfoMap.entries();
// MapIterator { ["name", "김맥스"],["age", 25],["major", "영문학"]}
for (const [key, value] of maxInfoMap) {
console.log(key, value);
}
// 결과
// "name" "김맥스"
// "age" 25
// "major" "영문학"
객체는 for...in
문이나 Object.keys
를 사용하여 순회해 왔습니다. 저 두 가지 순회 방법은 기본적으로 객체 프로퍼티의 키 만을 순회하기 때문에, 그 키를 이용해서 객체의 값을 다시 얻어내야 합니다. (그런 불편함 때문에 ES2017에 Object.entries
가 등장하게 되었습니다. 이 메소드는 맵 객체처럼 키-값을 쌍으로 묶은 이터레이터를 반환한다고 하네요.)
const maxInfoObj = {
name: '김맥스',
age: 25,
major: '영문학',
};
// for in문 이용
for (key in maxInfoObj) {
console.log(key, maxInfoObj[key]);
}
// Object.keys() 이용
for (key of Object.keys(maxInfoObj)) {
console.log(key, maxinfoObj[key]);
}
언제 써야 할까
맵 객체는 객체의 프로퍼티를 자주 변경해야할 때 빛을 발합니다. 메소드 이름들이 예측 가능하여 동작이 명확하고, 기존 객체와 달리 순회도 쉽게 이루어져 데이터를 조작하기 적합한 것 같습니다. 물론 모든 상황에 맵 객체를 쓸 필요는 없고, 자주 변경하지 않는 정보들은 객체에 저장해도 무방할 것 같습니다.