[JavaScript] 중첩된 배열을 출력: map()과 flatMap() 함수

민준·2025년 1월 12일
post-thumbnail

1. map()

Array 인스턴스의 map() 메서드는 순회 메서드입니다,
이 메서드는 주어진 callbackFn함수를 배열의 각각의 요소당 한번씩 호출하여 그 결과로 새로운 배열을 생성

const array1 = [1, 4, 9, 16];

// 각 요소마다 2를 곱해줌
const map1 = array1.map((x) => x * 2);

// Array형식으로 [2, 8, 18, 32]가 출력됨
console.log(map1);

2. flatMap()

Array인스턴스의 flatMap() 메서드는 배열의 각 요소에 주어진 콜백 함수를 적용한 다음 그 결과를 한단계씩 평탄화하여 형성된 새 배열을 반환

const arr1 = [1, 2, 1];

const result = arr1.flatMap((num) => (num === 2 ? [2, 2] : 1));

// Array형식으로 평탄화되어 [1, 2, 2, 1] 출력됨
console.log(result);

map()함수는 알고있었다....
간단한 예시와 함께 설명이 있지만 응용문제가 나오는 순간 멘탈이 무너진다.

문제

const detail_products = [
  {
    product_id: 1,
    name: "GeForce RTX 4090",
    category: {
      category_id: 23,
      name: "Graphic Card",
    },
    option: [
      {
        option_id: 12,
        name: "256GB",
        additional_price: 0,
      },
      {
        option_id: 13,
        name: "512GB",
        additional_price: 100000,
      },
    ],
    price: 400000,
  },
  {
    product_id: 2,
    name: "Nike Air Max 97",
    category: {
      category_id: 108,
      name: "Shoes",
    },
    option: [
      {
        option_id: 201,
        name: "Triple White",
        additional_price: 20000,
      },
      {
        option_id: 202,
        name: "Triple Black",
        additional_price: 40000,
      },
    ],
    price: 200000,
  },
];

코드 요약:

상품의 상세정보와 함께 상품의 추가 옵션과 그에따른 추가 가격이 명시되어있다.

내가 원하는것:

각 상품별로 해당 옵션을 각각 붙여서 출력하기를 원했다.
그래서 짠 코드가 아래와 같다.

// 함수선언
function productList(products) {
  // 함수의 결과를 배열값으로 넘겨주기위해 변수를 선언해서 함
  // (사실 지속적으로 consloe.log()를 하기위해서 생성한 이유도 있음...)
  const result = products.map(
    // 객체 비구조화
    ({ product_id, name, category: { name: categoryName }, option, price }) =>
    
    // 상품에 option의 갯수만큼 추가 후 map의 결과를 객체로 반환
      option.map(({ name: optionName, additional_price }) => ({
        product_id,
        name,
        category: categoryName,
        option: { name: optionName, additional_price },
        totalPrice: price + additional_price,
      }))
  );
  return result;
}

해당문제는 복잡해 보이지만 이중for문이라고 생각해보니 접근이 조금 용이했었다

출력결과 : [Object]

[
  [
    {
      product_id: 1,
      name: 'GeForce RTX 4090',
      category: 'Graphic Card',
      option: [Object],
      totalPrice: 400000
    },
    {
      product_id: 1,
      name: 'GeForce RTX 4090',
      category: 'Graphic Card',
      option: [Object],
      totalPrice: 500000
    }
  ],
  [
    {
      product_id: 2,
      name: 'Nike Air Max 97',
      category: 'Shoes',
      option: [Object],
      totalPrice: 220000
    },
    {
      product_id: 2,
      name: 'Nike Air Max 97',
      category: 'Shoes',
      option: [Object],
      totalPrice: 240000
    }
  ],
]

option: [Object]에 [Object]부분이 있다는 것이다!!
이를 어떻게 해결할까?

해결방법(1) - JSON.stringfy()

option: '{"name":"256GB","additional_price":0}',

출력은 된다 그리고 option의 타입도 object이다.
하지만 출력결과 string이 아닌 객체로 깔끔하게 나오게 하고싶었다.

해결방법(2) - JSON.parse(JSON.stringify())

option: JSON.parse(JSON.stringify({ name: optionName, additional_price }))

option부분만 위 코드를 수정했다. 정상적으로 출력이 된다
하지만 코드가 너무 복잡해서 가독성이 떨어진다.

해결방법(3) - flatMap()

flatMap() 활용

// 함수선언
function productList(products) {
  // products.map()에서 products.flatMap()으로 바꿨다
  const result = products.flatMap(
    ({ product_id, name, category: { name: categoryName }, option, price }) =>
      option.map(({ name: optionName, additional_price }) => ({
        product_id,
        name,
        category: categoryName,
        option: { name: optionName, additional_price },
        totalPrice: price + additional_price,
      }))
  );
  return result;
}

출력결과

[
  {
    product_id: 1,
    name: 'GeForce RTX 4090',
    category: 'Graphic Card',
    option: { name: '256GB', additional_price: 0 },
    totalPrice: 400000,
    optype: 'object'
  },
  {
    product_id: 1,
    name: 'GeForce RTX 4090',
    category: 'Graphic Card',
    option: { name: '512GB', additional_price: 100000 },
    totalPrice: 500000,
    optype: 'object'
  },
  {
    product_id: 2,
    name: 'Nike Air Max 97',
    category: 'Shoes',
    option: { name: 'Triple White', additional_price: 20000 },
    totalPrice: 220000,
    optype: 'object'
  },
  {
    product_id: 2,
    name: 'Nike Air Max 97',
    category: 'Shoes',
    option: { name: 'Triple Black', additional_price: 40000 },
    totalPrice: 240000,
    optype: 'object'
  },
]

하핫!! 원하던 결과가 나왔다!

이유

map()만 사용하면 결과가 중첩된 배열이 된다.
중첩 배열 상태에서 출력하면 객체들이 [Object]로 보일수 있음.

flatMap()을 사용하면 중첩된 배열을 평탄화하므로, 내부 객체들이 배열 최상위에 위치(한마디로 객체를 풀어준다는 의미)

따라서 데이터가 중첩된 형태로 변환되는 상황에서는 flatMap()이 더 적합함.

0개의 댓글