Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

joyful

TIP 13: 맵으로 명확하게 키-값 데이터를 갱신하라 본문

자바스크립트 코딩의 기술

TIP 13: 맵으로 명확하게 키-값 데이터를 갱신하라

조이풀한 개발자 2023. 11. 17. 17:42

 

데이터 변경이 잦은 키-값 컬렉션에 맵 객체를 사용할 수 있다. 

 

 

 

맵(Map) : 특정 작업을 매우 쉽게 처리하는 특별한 종류의 컬렉션

 

맵은 다음 두 가지 상황에서 사용 할 수 있다. 

 

  1. 키-값 쌍이 자주 추가되거나 삭제되는 경우
  2. 키가 문자열이 아닌 경우

 

 


 

예제코드

1.키-값 쌍이 자주 추가되거나 삭제되는 경우

  const dogs = [
    {
      이름: '맥스',
      크기: '소형견',
      견종: '보스턴테리어',
      색상: '검정색',
    },
    {
      이름: '도니',
      크기: '대형견',
      견종: '래브라도레트리버',
      색상: '검정색',
    },
    {
      이름: '섀도',
      크기: '중형견',
      견종: '래브라도레트리버',
      색상: '갈색',
    },
  ];

반려견 입양을 도와주는 웹사이트를 예로 들어보자.

강아지의 컬렉션들이 배열로 담겨져있다. 

이때 키(색상)와 값(검정색)을 가진 컬렉션을 검색하는 필터링 조건을 둔다고 가정하자. 

강아지 두 마리가 있는 배열이 반환될 것이다. 

 

 

객체의 정보를 갱신하려면 세 가지 동작이 필요하다. 

 

  1. 필터링 조건 추가
  2. 필터링 조건 삭제
  3. 모든 조건 제거
function addFilters(filters, key, value) {
  filters[key] = value;
}

function deleteFilters(filters, key) {
  delete filters[key];
}

function clearFilters(filters) {
  filters = {}; // =  filters = new Object();
  return filters;
}

 

문제점:

단 세 가지 기본적인 동작을 수행하는 것인데도 불구하고 

서로 다른 세 가지 패러다임을 적용해야 한다. ..?

 

 


해결

 

  • 먼저 새로운 맵 인스턴스를 생성하고 몇 가지 데이터를 추가한다. 
let filters = new Map();

 

  • set() 메서드를 이용해서 데이터를 추가한다. 
filters.set('견종', '래브라도레트리버');

//'래브라도레트리버'를 필터링 조건에 추가하기 위해 키 이름인 '견종'을 첫 번째 인수로 하고, 
//값 '래브라도레트리버'를 두 번째 인수로 넘겨준다.

 

  • get() 메서드를 이용해 데이터를 가져온다.
filters.get('견종');
// '래브라도레트리버'

 

  • ※체이닝

:메서드를 차례로 연결해서 여러 값을 쉽게 추가할 때는, 새로운 인스턴스를 생성하고 바로 메서드를 연결할 수도 있다.

  let filters = new Map()
    .set('견종', '래브라도레트리버')
    .set('크기', '대형견')
    .set('색상', '갈색');
  filters.get('크기');
  // '대형견'

 

  • 배열을 이용해서도 데이터를 추가할 수 있다. 
  let filters = new Map(
    [
      ['견종', '래브라도레트리버'],
      ['크기', '대형견'],
      ['색상', '갈색'],
    ]
  )
  filters.get('색상');
  //갈색

 

  • 맵에서 값을 제거할 때는 연산자 대신 delete() 메서드를 사용하면 된다. 
filters.delete('색상');
filters.get('색상');
//undefined

 

  • 모든 키-값 쌍을 제거할 때는 clear() 메서드를 사용하면 된다.
filters.clear();
filter.get('색상');
//undefined

 

 


 

 

위에서 살펴본 맵의 메서드를 이용하면 객체 대신 맵을 사용하도록 함수를 생성할 수 있다. 

const petFilters = new Map();
function addFilters(filters, key, value) {
  filters.set(key, value);
}

function deleteFilters(filters, key) {
  filters.delete(key);
}

function clearFilters(filters) {
  filters.clear();
}

 

이 함수에서는 몇 가지 특징이 있다. 

  • 맵 인스턴스에 항상 메서드를 사용한다.
  • delete() 메서드를 사용할 수 있기 때문에 인스턴스를 생성한 후에는 연산자를 섞지 않는다.
  • clear() 메서드를 사용할 수 있기 때문에 새로운 인스턴스를 생성할 필요가 없다. 

 

따라서 정보를 자주 변경하는 경우에는 객체보다 맵을 사용하는 것이 훨씬 편리하다. 

모든 동작과 의도가 매우 명료하게 보이기 때문에!

 

 


 

예제코드

2. 키가 문자열이 아닌 경우

객체는 사용할 수 있는 자료형에 제약이 있다.

 

다음과 같이 오류 코드를 담은 객체를 예로 들어보자. 

그리고 숫자를 이용해서 오류 텍스트를 가져올 수 있다고 하자. 

  const errors = {
    100: '이름이 잘못되었습니다.',
    110: '이름에는 문자만 입력할 수 있습니다.',
    200: '색상이 잘못되었습니다.'
  };
  function isDataValid(data) {
    if(data.length < 10) {
      return errors.100
    }
    return true;
  }

위 코드를 실행하면 오류가 발생한다. 

키 목록을 확인해보면 문자열이 담긴 배열로 반환된다. 

Object.keys(errors);
//['100', '110', '200']

 


 

하지만 맵을 사용하면 위와 같은 문제를 해결할 수 있다. 

맵은 여러 가지 자료형을 키로 받을 수 있기 때문이다. 

let errors = new Map([
  [100, '이름이 잘못되었습니다.'],
  [110, '이름에는 문자만 입력할 수 있습니다.'],
  [200, '색상이 잘못되었습니다.']
]);
errors.get(100);

객체와 마찬가지로 키만 모아서 확인하면 다음과 같다.

errors.keys();
// MapIterator{100, 110, 200}

객체에 Object.keys()를 적용한 것과 다르게 배열이 반환되지 않는다.

그렇다고 다른 맵이 반환된 것도 아니다. 

맵이터레이터(MapIterator)라는 것으로 반환됐다.