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

JavaScript에서 특정 속성 값을 기준으로 객체 그룹화하는 방법

JavaScript로 개발을 하다 보면 여러 개의 하위 객체를 담고 있는 하나의 객체를, 특정 속성의 값이 같은 것끼리 묶어서 새로운 구조로 재구성해야 하는 경우가 자주 발생합니다. 이번 글에서는 reduce() 메서드를 활용해 이러한 그룹화 작업을 간결하게 처리하는 방법을 알아보겠습니다.

문제 상황

다음과 같은 객체가 있다고 가정해 보겠습니다.

const obj = {
    0: { "time": 1, "day": 1 },
    1: { "time": 2, "day": 1 },
    2: { "time": 3, "day": 1 },
    3: { "time": 1, "day": 2 },
    4: { "time": 2, "day": 2 },
    5: { "time": 3, "day": 2 }
};

여기서 요구되는 작업은, 이 객체를 받아서 day 키의 값이 동일한 항목들을 별도의 하위 객체로 묶어주는 함수를 작성하는 것입니다.

기대 결과

위 객체에 대한 출력 결과는 다음과 같은 형태가 되어야 합니다.

const output = {
    '1': {
        '1': { time: 1, day: 1 },
        '2': { time: 2, day: 1 },
        '3': { time: 3, day: 1 }
    },
    '2': {
        '1': { time: 1, day: 2 },
        '2': { time: 2, day: 2 },
        '3': { time: 3, day: 2 }
    }
};

해결 방법: reduce() 활용하기

이 문제는 배열의 reduce() 메서드와 Object.values()를 조합하면 깔끔하게 해결할 수 있습니다. 전체 코드는 다음과 같습니다.

const obj = {
    0: { "time": 1, "day": 1 },
    1: { "time": 2, "day": 1 },
    2: { "time": 3, "day": 1 },
    3: { "time": 1, "day": 2 },
    4: { "time": 2, "day": 2 },
    5: { "time": 3, "day": 2 }
};

const groupObject = obj => {
    let res = {};
    res = Object.values(obj).reduce((acc, val) => {
        if (acc[val['day']] === undefined) {
            acc[val['day']] = {};
        }
        acc[val['day']][val['time']] = val;
        return acc;
    }, {});
    return res;
};

console.log(groupObject(obj));

코드 동작 원리

코드가 어떻게 동작하는지 단계별로 살펴보겠습니다.

1. 객체를 배열로 변환
Object.values(obj)를 호출하면 객체의 값들만 추출하여 배열 형태로 반환합니다. 즉, { time: 1, day: 1 }부터 { time: 3, day: 2 }까지의 여섯 개 객체가 담긴 배열이 만들어집니다.

2. reduce()로 누적 객체 생성
reduce()는 초기값으로 빈 객체 {}를 받아 순회하면서 결과를 누적합니다. 콜백 함수의 첫 번째 인자 acc는 지금까지 누적된 결과 객체입니다.

3. 그룹 키 존재 여부 확인
현재 항목의 day 값에 해당하는 키가 누적 객체에 없다면, 해당 키로 빈 객체를 새로 생성합니다. 이렇게 하면 같은 day 값을 가진 항목들이 하나의 그룹으로 모이게 됩니다.

4. 항목 할당
각 항목은 해당 day 그룹 안에서 time 값을 키로 사용하여 저장됩니다. 최종적으로 daytime 구조의 중첩된 객체가 완성됩니다.

실행 결과

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

{
    '1': {
        '1': { time: 1, day: 1 },
        '2': { time: 2, day: 1 },
        '3': { time: 3, day: 1 }
    },
    '2': {
        '1': { time: 1, day: 2 },
        '2': { time: 2, day: 2 },
        '3': { time: 3, day: 2 }
    }
}

마무리

이처럼 reduce()를 사용하면 반복문 없이도 선언적인 방식으로 객체를 특정 속성 기준으로 그룹화할 수 있습니다. 이 패턴은 daytime 외에도 카테고리, 날짜, 사용자 ID 등 어떤 키 기준의 그룹화에도 응용할 수 있으므로, 데이터 가공 로직에서 매우 유용하게 활용됩니다.