IT/언어

[JavaScript] Map 오브젝트와 map 메소드의 사용법

개발자 두더지 2023. 2. 6. 21:28
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

 JavaScript에 있어서 여러 개의 값을 다룰 때에 쓸 수 있는 것이 "배열"이다. 그러나 배열에서는 항목에 이름을 붙이고 싶은 경우가 있을 것이다. 그럴 때 사용할 수 있는 것이 "Map 오브젝트(연관 배열)"이다.

 또한, JavaScript의 배열을 다루기 위한 편리한 메소드로는 "map" 메소드가 있다. 양쪽 모두 이름에 "map"이 있으므로, 프로그래밍 초심자의 경우 혼동하기 쉽다.

 이번 포스트에서는 map메소드와 Map오브젝트의 차이나 사용법을 포함해 상세하게 해설하고자한다.

 

 

Map 오브젝트


 JavaScript에 있어서 Map 오브젝트는 키와 그에 대응하는 값을 보유한 오브젝트이다. 배열이나 JavaScript의 오브젝트와 달리 키가 되는 값에 대해서 문자열이나 숫자, Boolean등을 자유롭게 설정할 수 있는 장점이 있다. 

const mapObject= new Map([
  ['first', 1],
  [2, 'second'],
  [true, 'this is a true.'],
  [false, 'this is a false']
]);

console.log(`first: ${mapObject.get('first')}`);
// -> 「first: 1」라고 출력된다.
console.log(`true: ${mapObject.get(true)}`);
// -> 「true: this is a true.」라고 출력된다.

 Map 오브젝트는 ES2015(ES6)에서 등장한 비교적 새로운 기능이지만, JavaScript의 기본기능으로 정의되어 있다.

 

 

Set 오브젝트와의 차이


 Map 오브젝트와 동일하게 ES2015(ES6)에 동시에 채용된 기능으로 "Set 오브젝트"가 있다. Set도 Map과 값이 여러 개의 값을 다루는 편리한 기능이다.

 그러나 Set 오브젝트는 키를 가지지 않고 값의 목록만을 가지고 있으므로, JavaScript의 Array와 동일한 사용법으로 이용할 수 있다.

 Set 오브젝트와 Array의 커다란 차이는 "값의 중복을 허용하지 않는다"는 점이다. 예를 들어, Set 오브젝트의 경우에는 다음과 같은 배열은 허용되지 않는다.

const setArr = new Set(['val1', 'val2', 'val1', 'val3']);

console.log(setArr);
// -> 「{"val1","val2","val3"}」으로 출력된다.

 이 특징은 Map 오브젝트에 있어서 키의 특징과 비슷하다. Map 오브젝트의 키도 중복될 수 없다. 동일한 키를 설정한 경우에는 앞서 시정한 키가 덮어씌여진다.

const mapObject= new Map([
  ['first', 1],
  [2, 'second'],
  [true, 'this is a true.'],
  [false, 'this is a false'],
  ['first', 2] // <- 동일한 키와 다른 값을 지정
]);

console.log(`first: ${mapObject.get('first')}`);
// -> 「first: 2」가 출력됨

 이렇듯, Map 오브젝트와 Set 오브젝트는 다른 사용법이지만, 내부적으로의 동작은 공통된 부분이 많다는 것을 알 수 있다.

 

 

Map 오브젝트의 기본 사용법


 Map 오브젝트의 개요를 이해했을 것이므로, Map 오브젝트의 사용법을 마스터해보자.

 

오브젝트의 생성과 초기화

Map 오브젝트를 생성하기 위해서는 new 키워드를 사용한다.

const mapObj = new Map();

 또한, 값을 지정하여 초기값을 설정하는 경우에는 아래와 같이 코드를 쓰면 된다.

const mapObj = new Map([
  ['key1', 1],
  ['key2', 2]
]);

 이렇게 Map 오브젝트를 초기화하고 싶은 경우에는 키와 값을 가진 배열을 지정한다.

 

요소의 추가와 획득

// 오브젝트의 생성
const mapObj = new Map();

// set을 이용한 값의 설정
mapObj.set('key1', 'value1');

// get을 이용한 값의 획득
console.log(mapObj.get('key1'));
// -> 「value1」가 출력됨

 

데이터의 삭제

Map 오브젝트에서 데이터를 삭제하는 경우에는 delete 메소드를 사용한다.

// 오브젝트의 생성
const mapObj = new Map([
  ['key1', 'value1'],
  ['key2', 'value2']
]);

// delete를 이용하여 값을 삭제
mapObj.delete('key1');

// get을 이용하여 값을 획득
console.log(mapObj.get('key1'));
// -> 내용이 삭제되었으므로「undefined」가 출력된다.

 

 

Map 오브젝트의 반복 처리


 Map 오브젝트는 여러 개의 값을 가지고 있으므로, 내용을 반복(루프)하는 프로그램을 작성하는 경우가 많다. 여기서는 Map 오브젝트를 이용한 반복 처리의 방법을 소개한다.

 

forEach 메소드

 Map 오브젝트의 내부 요소를 반복하여 처리를 실행하고 싶은 경우네느 forEach 메소드를 이용할 수 있다.

const objectMap = new Map([
  ['key1', 'value1'],
  ['key2', 'value2'],
  ['key3', 'value3']
]);

objectMap.forEach((value, key) => {
  console.log(`The value of ${key} is ${value}`);
});
The value of key1 is value1
The value of key2 is value2
The value of key3 is value3

 이처럼 forEach 메소드의 인수에 함수를 지정하는 것으로 반복처리를 구현할 수 있다. 이러한 개발자가 자유롭게 기재할 수 있는 함수를 "콜백함수"라고 부른다. forEach 메소드는 콜백 함수 안에 기재한 처리를 Map 오브젝트의 모든 요소에 대해서 실행한다.

 

keys 메소드

 Map 오브젝트의 keys 메소드 이용하는 것으로 키의 목록을 획득할 수 있다. 아까의 forEach 메소드를 이용한 코드는 아래와 같이 바꿔 쓸 수 있다.

for (let key of objectMap.keys()) {
  console.log(`The value of ${key} is ${objectMap.get(key)}`);
}

 

values 메소드

 keys 메소드가 키의 목록을 획득할 수 있는 것에 대해, 값의 목록을 획득하고 싶은 경우에는 values 메소드를 이용하면 된다.

for (let value of objectMap.values()) {
  console.log(`value is ${value}`);
}

 주의할 점은 values 메소드에서 획득한 값으로 부터 맵 되는 키를 획득하는 것은 어렵다는 것이다. Map 오브젝트에 저장되어 있는 키는 중복되지 않으므로, 키를 이용해서 값을 획득하는 것은 가능하지만, 여러개의 키에 대해 동일한 값을 대입할 수 있으므로 값을 이용해 키를 특정하는 경우가 불가능한 경우가 많다.

 

 

map 메소드란?


 JavaScript의 Map 오브젝트의 사용법은 마스터했으므로, 다음은 배열의 map 메소드에 대해서 알아보자. 둘 다 map이라는 단어가 붙어있지만, 목적은 다르다. 

 Map 오브젝트의 경우 키와 값의 정보를 저장하기 위해 이용하지만. map 메소드의 주요 목적은 "배열을 다른 형태로 변환하는 것"이다.

 

 

map 메소드의 사용법


 그럼 계속해서 map 메소드의 사용법에 대해서 알아보자.

 

배열을 반복 처리하는 방법

// 조작할 배열
const arr = ['value1', 'value2', 'value3'];

const converted = arr.map((value, idx) => {
  return `${idx} is ${value}`
});

console.log(converted);

 이 때 converted의 오브젝트는 아래와 같이 변환된다.

["0 is value1","1 is value2","2 is value3"]

 

 

배열 내용의 형태를 변환하기

 방금의 예는 문자열의 내용을 변경했지만. map메소드는 주로 배열의 형식을 변환하기 위해 이용한다.

const toMap = arr.map((value, idx) => {
  return {
    'key': idx, 
    'value': value
  };
});

console.log(toMap);

 이때의 toMap 내용을 확인하면 오브젝트의 배열이 되어 있음을 알 수 있다.

[
  {
    "key": 0,
    "value":"value1"
  }, {
    "key": 1,
    "value": "value2"
  }, {
    "key": 2,
    "value": "value3"
  }
]

 이처럼, map 메소드를 이용하는 것으로 배열의 내용을 다른 형태로 변환하거나, 오브젝트의 배열에서 특정 내용만을 추출하는 것이 가능하다.

 

 

다른 메소드와의 차이점과 분리 사용


 Map 오브젝트와 동일하게 배열에는 편리한 메소드가 준비되어 있다. 따라서 경우에 따라 적절하게 사용하자.

 

forEach 메소드

forEach 메소드는 배열을 단순히 반복처리하고 싶은 경우에 이용한다.

const objectMap = new Map([
  ['key1', 'value1'],
  ['key2', 'value2'],
  ['key3', 'value3']
]);

objectMap.forEach((value, key) => {
  console.log(`The value of ${key} is ${value}`);
});

 map 메소드도 forEach 메소드도 배열의 반복처리가 가능하므로 동일한 처리를 할 수 있으나, forEach 메소드는 map 메소드와 달리 콜백 함수는 반환값을 박지 않는다.

  • 배열의 변환이 필요하면 map 메소드를 사용
  • 배열의 변환이 불필요하면 forEach 메소드를 사용

 

filter 메소드

 filter 메소드는 배열에서 특정 조건을 가진 요소를 획득하기 위해 이용한다. 배열에 대해서 검색과 같은 처리를 구현할 수 있으므로 기억해두자.

// 대상 배열
const target = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// filter함수를 이용해서 짝수를 추출
const evens = target.filter((value) => {
  return value % 2 === 0
});

console.log(evens);
// -> [2,4,6,8,10] 가 출력된다.

 

reduce 메소드

 reduce 메소드는 배열의 모든 내용을 이용하여 단일의 계산 결과를 구하고 싶은 경우에 이용한다. 총합이나 행렬 계산과 같은 수치 계산에 기억할 수 있음을 기억해두자.

// 대상 배열
const target = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const sum = target.reduce((prev, current, idx) => {
  
  console.log(`${idx}: prev is ${prev}, current is ${current}`);
  
   return prev + current;
});

console.log(sum);
//55가 출력된다.

reduce 메소드는 배열의 0번째가 아닌 1번째의 값에서 처리가 시작됨을 주의하자.  만약 배열의 모든 요소에 대해서 처리를 실행하고 싶은 경우에는 다음과 같이 코드를 바꿔쓰자.

const sum = target.reduce((prev, current, idx) => {
  
  console.log(`${idx}: prev is ${prev}, current is ${current}`);
  
  return prev + current;
}, 0); // <- 초기값으로 0을 지정한다.

 

flat 메소드

map 메소드와 동일하게 사용할 수 있는 것이 flat 메소드이다 flat 메소드는 map메소드의 처리중에 다차원 배열이 되어버린 배열을 플랫으로 변경해준다.

 예를 들어, 여러 개의 문장을 단어마다 잘라 저장하는 프로그램을 생각해보자.

const messages = ['This is a pen', 'Golden', 'Silver Moon'];

const words = messages.map((value, idx) => {
    // 공백으로 구분하여 리스트화
    return value.split(" ")
});

console.log(words);

 실행하면, words에는 아래와 같이 다차원 배열로 저장되어 버린다.

[
  ['This', 'is', 'a', 'pen'],
  ['Golden'],
  ['Silver', 'Moon']
]

 위 코드를 다음과 같이 바꿔쓰면 1차원 배열로 변환된다.

const words = messages.map((value, idx) => {
    // 공백으로 구분해서 리스트화
    return value.split(" ")
}).flat(); // <- flat()를 호출

 다시 words의 내용을 확인해보면 아래와 같이 플랫한 배열로 변환된 것을 알 수 있다.

["This","is","a","pen","Golden","Silver","Moon"]

 

flatMap 메소드

 flatMap 메소드는 더욱 새로운 규격인 ES2019에서 제정됐다. map + flat의 조합을 한 번 해주는 편리한 메소드이다.

const words = messages.flatMap((value, idx) => {
  return value.split(" ");
});

참고자료

https://camp.trainocate.co.jp/magazine/javascript-map/

728x90