자바스크립트 Reduce 메서드 뽀개기
September 02, 2020프론트엔드 개발을 시작한지 1년이 지났지만 아직도 reduce 메서드를 떠올리면 어떻게 활용해야 할 지 조금은 막막한 기분을 지울 수 없다. 정말 유용한 메서드임을 익히 들어서 알고 있는데도, 정작 활용은 어레이의 숫자들을 더하는 용도로 써본 적이 대부분이다ㅠ. 더이상 리듀스 메서드를 이해하는 것을 미루면 안될 것 같아 포스팅으로 정리하며 여러 예제와 함께 리듀스가 어떤 상황에서 유용하게 쓰일 수 있을지 고민해보았다
Reduce() 메서드
어레이를 구성하는 각각 요소들에 대해 reducer 함수를 실행하고 하나의 결과(output)를 도출한다. reduce 메서드는 reducer함수를 필수 인자로 받고 옵셔널한 값으로 초깃값을 받는다.
reducer 함수는 네 개의 아규먼트를 받을 수 있다.
첫째, Accumulator(축적값): 콜백함수가 리턴하는 값을 축적한다. 초깃값이 주어졌다면 초깃값부터 시작하고, 그렇지 않다면 어레이의 첫번째 요소를 사용한다.
둘째, Current Value(현재값): 어레이에서 현재 사용되는 현재값이다. 초깃값이 주어지지 않았다면 현재값은 두번째 요소부터 사용된다.
셋째(옵셔널), Current Index(현재 인덱스): 초깃값이 주어지면 인덱스 0부터 시작하고, 주어지지 않았다면 1부터 시작한다. 따라서 어레이의 요소가 하나 뿐이고 초깃값이 주어지지 않은 상태이면 콜백 함수 호출 없이 하나의 값만 리턴된다.
넷째(옵셔널), Source Array: reduce()가 호출되는 어레이이다.
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
const array2 = [10];
console.log(array2.reduce(reducer));
// expected output: 10
물론 리듀스는 어레이에 담겨진 숫자를 더할때도 많이 쓰이지만 이 밖에도 대표적으로 리듀서를 응용할 수 있는 예제들을 살펴보겠다.
- 어레이의 최대/최솟값 구하기
const array1 = [100, 22, 3, -4];
const minReducer = (acc, cur) => Math.min(acc, cur);
const maxReducer = (acc, cur) => Math.max(acc, cur);
array1.reduce(minReducer); // -4
array1.reduce(maxReducer); // 100
- 어레이 플래트닝(Flattening)
const numArray = [1, 2, [3, 10, [11, 12]], [1, 2, [3, 4]], 5, 6];
function flattenArr(data) {
const initialVal = [];
return data.reduce(
(acc, cur) => acc.concat(Array.isArray(cur) ? flattenArr(cur) : cur),
initialVal
);
}
flattenArr(numArray);
- 자료 구조 바꾸기
// 원래 데이터셋
const company = [
{ name: "facebook", type: "sns" },
{ name: "hyundai", type: "automobile" },
{ name: "medium", type: "blog" },
];
// 바뀔 데이터셋
const companyModified = {
facebook: { type: "sns" },
hyundai: { type: "automobile" },
medium: { type: "blog" },
};
function modifier(arr) {
return arr.reduce((acc, cur) => {
acc[cur.name] = { type: cur.type };
return acc;
}, {});
}
modifier(company);
// 원래 데이터셋
const movies = [
{ director: "Ridley Scott", name: "Blade Runner" },
{ director: "Ridley Scott", name: "Gladiator" },
{ director: "Cuentin Tarantino", name: "Pulp Fiction" },
{ director: "Alfonso Cuaron", name: "Gravity" },
];
// 바뀔 데이터셋 (이렇게 바꾸기)
const directors = {
"Ridly Scott": ["Blade Runner", "Gladiator"],
"Cuentin Tarantino": ["Pulp Fiction"],
"Alfonso Cuaron": ["Gravity"],
};
function modifier(arr) {
return arr.reduce((acc, cur) => {
if (acc[cur.director]) {
acc[cur.director] = [...acc[cur.director], cur.name];
} else {
acc[cur.director] = [cur.name];
}
return acc;
}, {});
}
modifier(movies);
여러 예제들을 작성해보고 나니 백에서 오는 데이터를 클라이언트 상에 나타내기 위해 데이터를 가공하는 과정에서 reduce 메서드가 아주 유용하게 쓰일 수 있을 것 같다는 기대감이 든다. 기존에는 데이터를 가공하기 위해 거의 map, for loop등을 활용했는데 리듀스 메서드를 활용해서 로직을 더욱 깔끔하고 가독성 있게 작성하도록 시도해 보아야겠다. 화이팅!