본문 바로가기

개발 기록/개발 로그

[JS] 성능 최적화를 위한 데이터 구조 선택 (with reduce, find)

프론트엔드 개발을 하다 보면 종종 대량의 데이터를 탐색하거나 필터링할 때 성능 저하를 경험할 수 있습니다. 특히, React 애플리케이션에서 비동기 API로 받아온 데이터를 탐색할 때 이러한 문제가 더욱 두드러지는데요. 오늘은 배열 탐색과 객체 접근 방식의 차이를 이해하고, 성능을 최적화하는 데이터 구조 선택 방법을 알아보겠습니다.

 


1.  문제 상황

const prices = [
  { address: '토큰1', priceInUsd: 10 },
  { address: '토큰2', priceInUsd: 20 },
  { address: '토큰3', priceInUsd: 15 },
];

const tokensWithBalance = [
  { address: '토큰1', amount: 5 },
  { address: '토큰2', amount: 10 },
  { address: '토큰3', amount: 3 },
];

const totalUsdValue = tokensWithBalance.reduce((sum, token) => {
  const priceData = prices.find((price) => price.address === token.address);
  return sum + (priceData?.priceInUsd || 0) * token.amount;
}, 0);

console.log(`Total USD Value: $${totalUsdValue}`);

위 코드에서 tokensWithBalance 배열의 각 요소를 순회하면서 prices 배열에서 해당 주소의 가격을 find로 찾아옵니다. 하지만 배열 탐색(find)은 시간 복잡도가 O(n)이기 때문에, 데이터가 많아질수록 성능이 급격히 저하될 수 있습니다.


2. 성능 최적화를 위한 접근 방법

객체 접근 방식으로 최적화

배열 대신 객체를 사용하면 특정 주소에 대한 가격 정보를 빠르게 탐색할 수 있습니다. reduce를 사용해 배열을 객체로 변환한 후 탐색하면 시간 복잡도를 O(1)로 줄일 수 있습니다.

최적화된 코드

// 배열을 객체로 변환 (해시 맵 형태)
const priceMap = prices.reduce((acc, { address, priceInUsd }) => {
  acc[address] = priceInUsd;
  return acc;
}, {} as Record<string, number>);

// 객체를 사용해 빠르게 접근
const totalUsdValueOptimized = tokensWithBalance.reduce((sum, token) => {
  const priceInUsd = priceMap[token.address] || 0;
  return sum + priceInUsd * token.amount;
}, 0);

console.log(`Optimized Total USD Value: $${totalUsdValueOptimized}`);
  1. reduce를 사용해 prices 배열을 priceMap 객체로 변환합니다.
  2. priceMap 객체는 address를 키로 사용하여 가격 정보를 저장하므로, O(1) 시간 복잡도로 데이터를 조회할 수 있습니다.
  3. tokensWithBalance 배열을 reduce로 순회하면서 해당 주소의 가격을 바로 가져와 계산합니다.

3. 성능 비교

시간 복잡도 분석

접근 방식시간 복잡도설명

배열 탐색 (find) O(n²) 배열 내 각 요소에 대해 find로 다시 탐색하므로 비효율적
객체 탐색 (priceMap) O(n) reduce로 한 번 변환 후, 각 요소를 O(1)로 탐색

예제 상황

  • 토큰 개수: 1,000개
  • 가격 데이터 개수: 1,000개
방식 예상 연산 횟수
배열 탐색 1,000,000번 (최악의 경우)
객체 탐색 1,000번

결과: 배열 탐색 방식보다 객체 접근 방식이 훨씬 빠릅니다.


4. 언제 객체로 변환할 필요가 없을까?

객체 변환이 항상 효율적인 것은 아닙니다. 다음과 같은 경우에는 find 메서드를 사용하는 배열 탐색이 충분할 수 있습니다:

  • 탐색할 데이터 개수가 적을 때 (예: 10개 이하)
  • 탐색 작업이 한두 번만 필요할 때

하지만, 탐색 작업이 반복적으로 이루어지거나 데이터가 많을 때는 객체 접근 방식이 유리합니다.


배열 탐색과 객체 탐색은 작은 차이 같아 보이지만, 대량의 데이터를 처리할 때는 큰 성능 차이를 만들어냅니다. 특히, React와 같은 UI 프레임워크에서는 불필요한 렌더링을 방지하고 성능을 최적화하기 위해 이러한 데이터 구조를 잘 선택하는 것이 중요합니다.

객체 접근 방식을 사용하기 전에 데이터를 변환하는 과정이 추가되므로, 데이터의 양과 탐색 빈도를 고려하여 최적화 전략을 선택하세요.