Javascript

reduce로 날짜별 정보 배열 만들기

드리프트2 2024. 11. 9. 12:08

reduce로 날짜별 정보 배열 만들기

 

안녕하세요!


이번 글에서는 reduce를 사용해 날짜별로 데이터를 그룹화하는 방법을 알아보려고 합니다.

 

개인적으로 reduce를 자주 사용하지 않았었는데, 최근 업무에서 이 기능을 활용할 일이 생겨서 그 경험을 정리해 보았습니다.

 

목표

이번 작업에서는 캘린더 UI에서 날짜별로 아코디언 방식으로 데이터를 펼치는 기능을 구현해야 했습니다.


API로부터 받은 데이터는 아래와 같이 날짜별 정보를 담고 있는 리스트 형식이었는데요:

// 기본 데이터
const baseData = [
  {
    startedAt: "2024-10-30T10:00:00+09:00",
    rooms: {
      id: "1",
    },
  },
  {
    startedAt: "2024-10-30T11:00:00+09:00",
    rooms: {
      id: "2",
    },
  },
  {
    startedAt: "2024-10-31T10:00:00+09:00",
    rooms: {
      id: "3",
    },
  },
  {
    startedAt: "2024-11-01T10:00:00+09:00",
    rooms: {
      id: "4",
    },
  },
  {
    startedAt: "2024-11-01T11:00:00+09:00",
    rooms: {
      id: "5",
    },
  },
];

 

위와 같은 데이터 구조로는 UI를 구현하기 어렵다고 판단하여, 각 날짜별로 데이터를 묶어서 배열을 만들기로 했습니다.

 

최종 목표 데이터

const expectData = [
  [
    { startedAt: "2024-10-30T10:00:00+09:00", rooms: { id: "1" } },
    { startedAt: "2024-10-30T11:00:00+09:00", rooms: { id: "2" } },
  ],
  [{ startedAt: "2024-10-31T10:00:00+09:00", rooms: { id: "3" } }],
  [
    { startedAt: "2024-11-01T10:00:00+09:00", rooms: { id: "4" } },
    { startedAt: "2024-11-01T11:00:00+09:00", rooms: { id: "5" } },
  ],
];

구현 코드 및 설명

바로 결과부터 보자면, 최종 코드는 다음과 같습니다:

const weeklyShifts = Object.values(
  (baseData || []).reduce((acc, record) => {
    const date = record?.startedAt.split("T")[0];
    return {
      ...acc,
      [date]: [...(acc?.[date] ?? []), record],
    };
  }, {})
);

 

이제 각 코드 부분을 하나씩 설명해 드리겠습니다.

1. reduce로 배열 순회하기

reduce는 배열에 대해 지정된 처리를 반복 수행하는 함수입니다.


map이나 filter와 달리, reduce는 배열에서 원하는 형태로 데이터를 유연하게 가공할 수 있는데요,

 

합계를 구하거나 새로운 데이터 구조를 만드는 데 자주 사용됩니다.

 

기본 문법은 다음과 같습니다:

array.reduce((accumulator, currentValue, index, array) => {
  // 여기서 처리
}, initialValue);
  • accumulator: 이전 처리 결과가 전달되는 변수입니다. 첫 번째 순회에서는 initialValue가 전달됩니다. 이를 생략하면 배열의 첫 번째 요소가 초기값으로 설정됩니다.
  • currentValue: 현재 처리 중인 배열 요소입니다.
  • index: 현재 처리 중인 요소의 인덱스입니다. (생략 가능)
  • array: 원본 배열입니다. (생략 가능)

 

reduce를 사용해 baseData 배열을 순회하게 됩니다. 이해를 돕기 위해 각 요소를 console.log로 출력해 보겠습니다:

const weeklyShifts = (baseData || []).reduce((acc, record) => {
  console.log("acc", acc);
  console.log("record", record);
}, {});

 

출력 결과:

{} // acc
{ startedAt: '2024-10-30T10:00:00+09:00', rooms: { id: '1' } } // record

 

초기값으로 빈 객체 {}를 설정했기 때문에, 첫 번째 순회에서는 acc에 빈 객체가 전달되고, record에는 배열의 첫 번째 객체가 전달됩니다.


2. 날짜 정보 생성 및 분기 처리

이제 startedAt에서 날짜 정보를 추출하고, 이를 기준으로 배열을 그룹화하는 로직을 추가합니다:

const weeklyShifts = (baseData || []).reduce((acc, record) => {
  const date = record?.startedAt.split("T")[0];
  return {
    ...acc,
    [date]: [...(acc?.[date] ?? []), record],
  };
}, {});

 

여기서는 record.startedAt에서 날짜만 추출한 후, 이 날짜를 객체의 key로 사용하고, 해당 날짜에 속하는 데이터를 배열로 묶어 value에 저장합니다.

 

첫 번째 순회 결과는 다음과 같습니다:

{
  '2024-10-30': [
    { startedAt: '2024-10-30T10:00:00+09:00', rooms: { id: '1' } }
  ]
}

 

같은 날짜가 있을 경우 해당 날짜의 배열에 데이터를 추가해 나갑니다.

 

두 번째 순회 결과:

{
  '2024-10-30': [
    { startedAt: '2024-10-30T10:00:00+09:00', rooms: { id: '1' } },
    { startedAt: '2024-10-30T11:00:00+09:00', rooms: { id: '2' } }
  ]
}

 

세 번째 데이터는 날짜가 다르기 때문에 새로운 keyvalue가 생성됩니다.

 

최종 결과:

{
  '2024-10-30': [
    { startedAt: '2024-10-30T10:00:00+09:00', rooms: { id: '1' } },
    { startedAt: '2024-10-30T11:00:00+09:00', rooms: { id: '2' } }
  ],
  '2024-10-31': [
    { startedAt: '2024-10-31T10:00:00+09:00', rooms: { id: '3' } }
  ],
  '2024-11-01': [
    { startedAt: '2024-11-01T10:00:00+09:00', rooms: { id: '4' } },
    { startedAt: '2024-11-01T11:00:00+09:00', rooms: { id: '5' } }
  ]
}

3. Object.values로 배열 만들기

마지막으로, 날짜별로 데이터를 배열로 묶어주기 위해 Object.values를 사용합니다.


이 함수는 객체의 값들을 배열로 반환해 줍니다.

const weeklyShifts = Object.values(
  (baseData || []).reduce((acc, record) => {
    const date = record?.startedAt.split("T")[0];
    return {
      ...acc,
      [date]: [...(acc?.[date] ?? []), record],
    };
  }, {})
);

 

최종 결과는 다음과 같이 날짜별로 그룹화된 배열이 됩니다:

[
  [
    { startedAt: "2024-10-30T10:00:00+09:00", rooms: { id: "1" } },
    { startedAt: "2024-10-30T11:00:00+09:00", rooms: { id: "2" } },
  ],
  [{ startedAt: "2024-10-31T10:00:00+09:00", rooms: { id: "3" } }],
  [
    { startedAt: "2024-11-01T10:00:00+09:00", rooms: { id: "4" } },
    { startedAt: "2024-11-01T11:00:00+09:00", rooms: { id: "5" } },
  ],
];

 

이렇게 해서 원하는 형태의 데이터를 얻을 수 있었습니다! 🥳


마무리

reduce를 활용해 데이터를 변환하는 방법을 알아보았는데요, 도움이 되셨나요?

 

저도 이번 기회를 통해 reduce를 더 잘 활용할 수 있게 된 것 같아서 기쁩니다! 🥳

 

이 글이 누군가에게 작은 도움이 되기를 바랍니다.