실무에서 객체 배열로 이루어진 데이터를 다루다 보면, 배열 안의 여러 객체가 공통으로 가지고 있는 숫자 속성의 평균값을 구해야 하는 경우가 자주 있습니다. 예를 들어 사용자 목록에서 평균 나이를 계산하거나, 상품 목록에서 평균 가격을 구하는 작업이 대표적입니다.
문제 상황
다음과 같이 사람 정보를 담은 객체 배열이 있다고 가정해 보겠습니다. 각 객체는 name과 age라는 속성을 가지고 있습니다.
const people = [
{
name: 'Anna',
age: 22
}, {
name: 'Tom',
age: 34
}, {
name: 'John',
age: 12
}, {
name: 'Kallis',
age: 22
}, {
name: 'Josh',
age: 19
}
]우리가 만들 함수는 이런 배열을 인자로 받아서, 배열에 포함된 모든 age 값의 평균을 반환해야 합니다.
reduce()를 활용한 해결 방법
배열의 합계나 평균을 구할 때 가장 널리 쓰이는 방식은 Array.prototype.reduce() 메서드를 활용하는 것입니다. reduce()는 배열을 순회하면서 누적값(acc)을 하나씩 더해 최종 결과를 단일 값으로 반환합니다.
const people = [
{
name: 'Anna',
age: 22
}, {
name: 'Tom',
age: 34
}, {
name: 'John',
age: 12
}, {
name: 'Kallis',
age: 22
}, {
name: 'Josh',
age: 19
}
]
const findAverageAge = (arr) => {
const { length } = arr;
return arr.reduce((acc, val) => {
return acc + (val.age / length);
}, 0);
};
console.log(findAverageAge(people));코드 설명
동작 원리를 단계별로 살펴보면 다음과 같습니다.
- 배열 길이 추출: 구조 분해 할당(
const { length } = arr;)으로 배열의 요소 개수를 미리 구해 둡니다. - 누적 계산:
reduce()의 초기값을0으로 설정하고, 순회할 때마다 현재 객체의age를 배열 길이로 나눈 값을 누적합니다. - 결과 반환: 모든 요소를 순회하면 각 나이를 개수로 나눈 값들의 합, 즉 평균이 완성됩니다.
실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
21.8
(22 + 34 + 12 + 22 + 19) ÷ 5 = 21.8로, 정상적으로 평균 나이가 계산된 것을 확인할 수 있습니다.
다른 접근 방식: 합계를 먼저 구한 뒤 나누기
매번 나눗셈을 수행하는 대신, 합계를 먼저 구하고 마지막에 한 번만 나누는 방식도 가능합니다.
const findAverageAge = (arr) => {
const total = arr.reduce((acc, val) => acc + val.age, 0);
return total / arr.length;
};두 방식 모두 결과는 동일하지만, 합계를 먼저 구하는 방식이 의도를 더 명확하게 드러내므로 가독성 측면에서 선호되기도 합니다. 또한 빈 배열이 전달될 가능성이 있다면 0으로 나누는 오류를 방지하기 위해 길이가 0인 경우를 별도로 처리해 주는 것이 안전합니다.