Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript에서 객체 배열을 반복하고 새 배열로 그룹화하는 방법

문제 소개

다음과 같이 고객(customer)과 프로젝트(project) 정보를 담은 객체 배열이 있다고 가정해 보겠습니다.

const arr = [
  {
    "customer": "Customer 1",
    "project": "1"
  },
  {
    "customer": "Customer 2",
    "project": "2"
  },
  {
    "customer": "Customer 2",
    "project": "3"
  }
]

우리가 작성해야 할 것은 이러한 배열을 입력받아 새로운 배열을 반환하는 JavaScript 함수입니다.

새 배열에서는 동일한 customer 값을 가진 항목들이 하나로 병합되어야 하며, 최종적으로 다음과 같은 형태의 결과를 얻는 것이 목표입니다.

const output = [
  {
    "Customer 1": {
      "projects": "1"
    }
  },
  {
    "Customer 2": {
      "projects": [
        "2",
        "3"
      ]
    }
  }
]

즉, 각 고객별로 프로젝트 목록을 묶어 주는 그룹화(grouping) 작업이라고 할 수 있습니다.

forEach를 활용한 해결 방법

먼저 forEach 메서드를 이용해 구현해 보겠습니다.

const arr = [
  {
    "customer": "Customer 1",
    "project": "1"
  },
  {
    "customer": "Customer 2",
    "project": "2"
  },
  {
    "customer": "Customer 2",
    "project": "3"
  }
];

const groupCustomer = data => {
  const res = [];
  data.forEach(el => {
    // 결과 배열에 이미 존재하는 고객인지 확인
    let customer = res.filter(custom => {
      return el.customer === custom.customer;
    })[0];
    if (customer) {
      // 기존 고객이면 프로젝트만 추가
      customer.projects.push(el.project);
    } else {
      // 새로운 고객이면 새 항목 생성
      res.push({ customer: el.customer, projects: [el.project] });
    }
  });
  return res;
};

console.log(groupCustomer(arr));

출력 결과

위 코드를 실행하면 콘솔에 다음과 같이 출력됩니다.

[
  { customer: 'Customer 1', projects: [ '1' ] },
  { customer: 'Customer 2', projects: [ '2', '3' ] }
]

실행 결과를 보면 Customer 2처럼 중복된 고객은 하나의 객체로 합쳐지고, 프로젝트 값들이 배열 형태로 누적되는 것을 확인할 수 있습니다.

코드 동작 원리

  1. 결과 배열 초기화: 빈 배열 res를 만들어 그룹화된 데이터를 담을 준비를 합니다.
  2. 배열 순회: forEach로 원본 배열의 각 객체를 하나씩 확인합니다.
  3. 중복 검사: filter를 사용해 res 안에 같은 customer 값을 가진 항목이 있는지 찾습니다.
  4. 분기 처리: 이미 존재하는 고객이면 해당 객체의 projects 배열에 프로젝트를 push하고, 없다면 새 객체를 만들어 추가합니다.

reduce를 활용한 대안

같은 로직을 reduce 메서드로 더 간결하게 표현할 수도 있습니다.

const groupByReduce = data =>
  data.reduce((acc, el) => {
    const existing = acc.find(item => item.customer === el.customer);
    if (existing) {
      existing.projects.push(el.project);
    } else {
      acc.push({ customer: el.customer, projects: [el.project] });
    }
    return acc;
  }, []);

console.log(groupByReduce(arr));

reduce는 누적값(acc)을 활용해 반복과 결과 생성을 한 번에 처리하기 때문에, 이런 그룹화 작업에서 특히 유용하게 사용됩니다.

마무리

이처럼 JavaScript에서는 forEach나 reduce 같은 배열 메서드를 활용하면 객체 배열을 손쉽게 반복하면서 조건에 맞게 재구성한 새 배열을 만들 수 있습니다. 참고로 위 방식은 매번 filter를 호출하기 때문에 데이터가 많아지면 O(n²)에 가깝게 느려질 수 있습니다. 이 경우 Map이나 일반 객체를 해시맵처럼 활용하면 O(n) 수준으로 성능을 개선할 수 있으니, 대량의 데이터를 다룰 때는 이 점을 함께 고려해 보시기 바랍니다.