JavaScript의 Map 데이터 구조와 의의
JavaScript의 Map 데이터 구조는 키-값(Key-Value) 쌍을 가진 데이터 구조이다. Map 데이터 구조는 키 생성 시 키에 대해 해싱을 사용해서 키의 해시값의 중복이 되지 않는 이상 Value에 접근하기 위해 O(1)의 복잡도를 가질 수 있다는 점에서 프로그램의 최적화를 위해 많이 쓰인다. 또한 키의 해시값이 중복이 되더라도 중복인 대상 K개에 대해서만 O(K)의 복잡도를 가지기 때문에 값 접근을 위한 시간을 매우 낮출 수 있다.
이 때문에 대부분 언어들에서는 무조건 Map 데이터 구조를 지원하고 있다. 가끔 Map 대신 Dictionary로 쓰는 Swift 같은 언어가 있기는 하지만, JavaScript, Java, Kotlin 등의 언어들은 Map이라 명명한다.
자 Map이 왜 중요한지 이해했으면 이제 JavaScript에서 Map을 생성하고 조작하는 방법에 대해 알아보자.
JavaScript Map 생성하기
JavaScript에서 Map 데이터 구조를 사용하기 위해서는 MapConstructor Interface를 사용하면 된다. MapConstructor Interface는 Map을 Map<any, any=""> 타입으로 생성한다.</any,>
interface MapConstructor {
new(): Map<any, any>;
new<K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
readonly prototype: Map<any, any>;
}
Map 빈 값으로 생성하기
Map을 아무런 원소가 없이 생성하려면 다음과 같이 new Map() 메서드를 사용해 생성하면 된다. 이렇게 생성된 blog 변수를 Map<any,any> 타입을 가지게 된다.
const blog = new Map();
Map을 원소와 같이 초기화하기
Map을 원소와 같이 생성하려면 Map의 생성자에 entries 값을 넘기면 된다. entries는 Array<Array<any>> 타입이며, 안쪽 Array<any>의 첫 원소가 Key가 되고 둘째 원소가 Value가 된다.
예를 들어 blog 라는 Map을 생성하고 이름을 "Dev World"로, 작성자를 "Dev Cho"로, "total post"를 350으로 설정하려면 다음과 같이 초기화하면 된다.
const blog = new Map([
["name", "Dev World"],
["author", "Dev Cho"],
["total posts", 350]
]);
console.log(blog.get("name")); // Dev World
console.log(blog.get("author")); // Dev Cho
console.log(blog.get("total posts")); // 350
그렇다면 이미 생성된 Map에 값은 어떻게 추가할 수 있을까?
JavaScript Map의 다양한 함수들 : set, get, has, delete, clear
Map은 인터페이스로 다양한 메서드들을 가지고 있다. 각 메서드들은 Map을 조작하는 데 사용한다. 이제 이 함수 각각에 대해 알아보도록 하자.
interface Map<K, V> {
clear(): void;
delete(key: K): boolean;
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
readonly size: number;
}
set 사용해 이미 생성된 Map에 값 추가하기
이미 생성된 Map에 값을 추가하기 위해서는 Map의 set 함수를 사용하면 된다. 예를 들어 Map의 name을 "World"로 author을 "Dev Cho"로 "total posts"를 350으로 하려면 아래와 같이 코드를 만들면 된다.
const blog = new Map();
blog.set("name", "World");
blog.set("author", "Dev Cho");
blog.set("total posts", 350);
console.log(blog.get("name")); // World
console.log(blog.get("author")); // Dev Cho
console.log(blog.get("total posts")); // 350
Map의 set 함수는 같은 Key를 가진 값이 있다면 Key에 대응하는 Value를 해당 Value로 대체한다. 위에서 이름을 잘못해서 World로 세팅한 했는데 이를 Dev World로 바꾸려면 다시 blog.set("name", "Dev World") 를 실행하면 "name에 대응하는 값이 Dev World로 치환된 것을 확인할 수 있다.
const blog = new Map();
blog.set("name", "World");
blog.set("author", "Dev Cho");
blog.set("total posts", 350);
blog.set("name", "Dev World");
console.log(blog.get("name")); // Dev World
console.log(blog.get("author")); // Dev Cho
console.log(blog.get("total posts")); // 350
get과 키를 사용해 Map의 값에 접근하기
이미 앞에서 다루었지만 Map의 값에 접근하기 위해서는 get 메서드를 사용해야 한다. 만약 get 메서드를 사용하지 않고 [Key]를 사용하게 되면 undefined가 뜨게 된다.
const blog = new Map([
["name", "Dev World"],
["author", "Dev Cho"],
["total posts", 350]
]);
console.log(blog.get("name")); // Dev World
console.log(blog["name"]); // undefined
이유는 [Key]는 Object를 위한 것이기 때문이다. Map도 Object의 일종이지만 Object와 저장 구조가 다르기 때문에 get을 사용해서만 접근해야 하고 [] 를 사용해서 접근할 수 없다.
has 사용해 Map에 해당 키가 있는지 확인하기
has를 사용하면 Map에 해당 Key가 있는지 확인할 수 있다. has는 Key가 있다면 true를 반환하고 없다면 false를 반환한다.
예를 들어 blog에는 name이 있고 createdDate는 없으므로 has("name")은 true를 반환하고 has("createdDate")는 false를 반환한다.
const blog = new Map([
["name", "Dev World"],
["author", "Dev Cho"],
["total posts", 350]
]);
console.log(blog.has("name")); // true
console.log(blog.has["createdDate"]); // false
get을 사용해 없는 값에 접근하면 undefined가 반환되어 undefined가 반환되었을 때 Key가 없는 상황에 대해 처리하기도 하지만 has를 사용해 Key가 있는지 확인한 후 사용하는 게 더욱 명확하다.
delete 사용해 Map에서 키-값 쌍 제거하기
delete을 사용하면 Key-Value 쌍을 제거할 수 있다. 예를 들어 위에서 만든 객체에서 "name"키에 해당하는 Key-Value 쌍을 제거하고 싶다면 아래와 같이 사용하면 된다. 제거된 Key-Value 쌍은 더 이상 접근할 수 없으므로 undefined가 출력된다.
const blog = new Map([
["name", "Dev World"],
["author", "Dev Cho"],
["total posts", 350]
]);
blog.delete("name")
console.log(blog.get("name")); // undefined
delete을 사용하면 하나씩 제거가 가능하지만 한 번에 모든 데이터를 제거하고 싶을 수 있다.
clear 사용해 Map의 모든 원소 제거하기
한 번에 모든 Key-Value 쌍을 제거하고 싶다면 clear을 사용하면 된다. map에 clear을 사용하면 모든 원소가 제거되어 크기가 0인 빈 값이 되어버린다.
const blog = new Map([
["name", "Dev World"],
["author", "Dev Cho"],
["total posts", 350]
]);
blog.clear()
console.log(blog) // Map(0) {}
정리
이번 시간에는 JavaScript Map의 다양한 사용법에 대해 살펴보았다. Map은 시간 복잡도가 낮아 현업에서도 매우 자주 사용되는 데이터 구조이다. Map을 다루는 것은 매우 중요하니 이 글에서 다룬 모든 내용들을 꼭 직접 쳐보면서 익히도록 하자.