πŸͺ„ Programming

[JS] μžλ°”μŠ€ν¬λ¦½νŠΈ reduce() λ©”μ„œλ“œ ν™œμš© μ˜ˆμ‹œ λͺ¨μŒ

ColorFilter 2024. 7. 7. 22:44
λ°˜μ‘ν˜•

Array.reduce() λ©”μ„œλ“œλŠ” 배열에 μžˆλŠ” 각 μš”μ†Œμ— 콜백 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜μ—¬ λˆ„μ λœ 계산 κ²°κ³Όλ₯Ό ν•˜λ‚˜μ˜ κ°’μœΌλ‘œ λ°˜ν™˜ν•œλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ μ œκ³΅ν•˜λŠ” filter(), map() λ“±μ˜ λ°°μ—΄ λ©”μ„œλ“œλŠ” λͺ¨λ‘ reduce()둜 κ΅¬ν˜„ν•  수 있고, 이 외에도 λ‹€μ–‘ν•œ ν™œμš© 방법이 있기 λ•Œλ¬Έμ— 개인적으둜 κ°€μž₯ 자주 μ‚¬μš©ν•˜λŠ” λ°°μ—΄ λ©”μ„œλ“œλ‹€. reduce() λ©”μ„œλ“œμ˜ ꡬ문은 μ•„λž˜μ™€ κ°™λ‹€.

reduce(callbackFn, initialValue?)

 

  1. callbackFn 콜백 νŒŒλΌλ―Έν„°
    • accumulator : 이전 callbackFn λ°˜ν™˜κ°’
      • μ΄ˆκΈ°κ°’ μ§€μ • μ‹œ μ½œλ°±μ„ 처음 ν˜ΈμΆœν–ˆμ„ λ•Œ κ°’ : initialValue
      • μ΄ˆκΈ°κ°’ λ―Έμ§€μ •μ‹œ μ½œλ°±μ„ 처음 ν˜ΈμΆœν–ˆμ„ λ•Œ κ°’ : array[0]
    • currentValue : ν˜„μž¬ μˆœνšŒν•˜κ³  μžˆλŠ” κ°’
      • μ΄ˆκΈ°κ°’ μ§€μ • μ‹œ μ½œλ°±μ„ 처음 ν˜ΈμΆœν–ˆμ„ λ•Œ κ°’ : array[0]
      • μ΄ˆκΈ°κ°’ λ―Έμ§€μ •μ‹œ μ½œλ°±μ„ 처음 ν˜ΈμΆœν–ˆμ„ λ•Œ κ°’ : array[1]
    • currentIndex : ν˜„μž¬ μˆœνšŒν•˜κ³  μžˆλŠ” κ°’μ˜ 인덱슀
    • array : reduceλ₯Ό ν˜ΈμΆœν•œ λ°°μ—΄
  2. initialValue (μ΄ˆκΈ°κ°’) : callbackFn μ½œλ°±μ„ 처음 ν˜ΈμΆœν•  λ•Œ accumulator에 μ‚¬μš©ν•  μ΄ˆκΈ°κ°’. λ―Έμ§€μ •μ‹œ λ°°μ—΄(array) 첫 번째 인자λ₯Ό μ΄ˆκΈ°κ°’μœΌλ‘œ μ‚¬μš©. μ΄ˆκΈ°κ°’ μ§€μ •μ‹œ λ°°μ—΄ 첫 번째 μš”μ†ŒλŠ” μˆœνšŒμ— 포함 μ•ˆ 함.

 

 

숫자 λ”ν•˜κΈ° | Summing Numbers


reduce() λ©”μ„œλ“œμ˜ κ°€μž₯ 기본적인 μ‚¬μš© μ˜ˆμ‹œ. 숫자둜 이뀄진 배열이 μ£Όμ–΄μ‘Œμ„ λ•Œ λͺ¨λ“  수λ₯Ό λ”ν•œ 값을 λ°˜ν™˜ν•œλ‹€.

const odds = [1, 3, 5, 7, 9, 11];
const sumOfOdds = odds.reduce((acc, cur) => acc + cur);
console.log(sumOfOdds); // 36

 

 

λ°°μ—΄ 펼치기 | Flattening Arrays


Array.flat()은 μ€‘μ²©λœ 배열을 νŽΌμ³μ„œ 단일 λ°°μ—΄λ‘œ λ§Œλ“œλŠ” λ©”μ„œλ“œλ‹€. reduce()λ₯Ό μ΄μš©ν•˜λ©΄ flat() λ©”μ„œλ“œμ™€ λ™μΌν•˜κ²Œ κ΅¬ν˜„ν•  수 μžˆλ‹€.

const nestedArray = [[1, 2], [3, 4], [5, 6]];
const flattenedArray = nestedArray.reduce((acc, cur) => acc.concat(cur), []);
console.log(flattenedArray); // [1, 2, 3, 4, 5, 6]

 

μœ„ μ˜ˆμ‹œλŠ” 기본적으둜 1 depth만 펼칠 수 μžˆλ‹€. 2 depth 이상 μ€‘μ²©λœ 배열이라면 μž¬κ·€λ₯Ό μ΄μš©ν•˜λ©΄ λœλ‹€.

const nestedArray = [1, 2, [3, 4, [5, 6]]];

const deepFlat = (arr) => {
  return arr.reduce((acc, cur) => {
    return acc.concat(Array.isArray(cur) ? deepFlat(cur) : cur);
  }, []);
};

const flattenedArray = deepFlat(nestedArray);
console.log(flattenedArray); // [1, 2, 3, 4, 5, 6]

 

 

객체 κ·Έλ£Ήν•‘ | Grouping Objects


객체λ₯Ό μš”μ†Œλ‘œ κ°–λŠ” λ°°μ—΄μ—μ„œ, νŠΉμ • ν”„λ‘œνΌν‹°λ₯Ό κΈ°μ€€μœΌλ‘œ κ·Έλ£Ήν•‘(Grouping) ν•΄μ•Ό ν•˜λŠ” 상황을 자주 μ ‘ν•œλ‹€. 예λ₯Ό λ“€μ–΄ μ•„λž˜μ²˜λŸΌ age μ—°λ Ήλ³„λ‘œ 그룹을 λ‚˜λˆ„λŠ” 상황을 생각해 λ³Ό 수 μžˆλ‹€.

// 원본 λ°°μ—΄
[
  { name: 'A', age: 20 },
  { name: 'B', age: 30 },
  { name: 'C', age: 20 },
  { name: 'D', age: 30 },
];

// μ—°λ Ήλ³„λ‘œ κ·Έλ£Ήν•‘
{
  20: [
    { name: 'A', age: 20 },
    { name: 'C', age: 20 },
  ],
  30: [
    { name: 'B', age: 30 },
    { name: 'D', age: 30 },
  ],
};

 

μ΄ˆκΈ°κ°’μ„ 객체둜 μ§€μ •ν•œ reduce()λ₯Ό ν™œμš©ν•˜λ©΄ κ°„νŽΈν•˜κ²Œ κ·Έλ£Ήν•‘ν•  수 μžˆλ‹€. 각 age ν‚€λ§ˆλ‹€ 배열을 μƒμ„±ν•˜κ³ , ν˜„μž¬ μˆœνšŒν•˜λŠ” 객체의 age 속성에 ν•΄λ‹Ήν•˜λŠ” 배열에 push ν•˜λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•˜λ©΄ λœλ‹€.

const users = [
  { name: 'A', age: 20 },
  { name: 'B', age: 30 },
  { name: 'C', age: 20 },
  { name: 'D', age: 30 },
];

const groupByAge = users.reduce((acc, cur) => {
  const { age } = cur;
  if (!acc[age]) acc[age] = [];
  acc[age].push(cur);
  return acc;
}, {});

console.log(groupByAge);
/*
{
  20: [{ name: 'A', age: 20 }, { name: 'C', age: 20 }],
  30: [{ name: 'B', age: 30 }, { name: 'D', age: 30 }]
}
*/

 

참고둜 객체 그룹핑은 ES15(ECMAScript 2024)λΆ€ν„° μ œκ³΅ν•˜λŠ” groupBy() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•  μˆ˜λ„ μžˆλ‹€. 이 λ©”μ„œλ“œλŠ” Chrome 117 버전, Node.js 21 버전 이후뢀터 μ‚¬μš©ν•  수 μžˆλ‹€(Baseline 2024).

const groupByAge = Object.groupBy(users, ({ age }) => age);
console.log(groupbyAge); // {20: Array(2), 30: Array(2)}

 

Browser compatibility via MDN

 

쑰회용 맡 | Lookup Maps


λ°°μ—΄ 각 μš”μ†Œκ°€ 객체이고, 각 κ°μ²΄λŠ” κ³ μœ ν•œ id ν”„λ‘œνΌν‹°λ₯Ό κ°€μ§ˆ λ•Œ, id둜 λΉ λ₯΄κ²Œ μ‘°νšŒν•  수 μžˆλŠ” Lookup 맡을 생성 해두면, νŠΉμ • idλ₯Ό κ°€μ§„ μš”μ†Œμ— O(1) μ‹œκ°„ λ³΅μž‘λ„λ‘œ λΉ λ₯΄κ²Œ μ ‘κ·Όν•  수 μžˆλ‹€. 맀번 find() 같은 λ©”μ„œλ“œλ‘œ μˆœνšŒν•  ν•„μš”κ°€ μ—†κΈ° λ•Œλ¬Έμ— μ„±λŠ₯ λ©΄μ—μ„œ 더 μœ λ¦¬ν•˜λ‹€.

const products = [
  { id: 1, name: 'iPhone' },
  { id: 2, name: 'iPad' },
  { id: 3, name: 'iMac' },
];

const productMap = products.reduce((acc, cur) => {
  acc[cur.id] = cur;
  return acc;
}, {});

console.log(productMap);
/*
{
  1: { id: 1, name: 'iPhone' },
  2: { id: 2, name: 'iPad' },
  3: { id: 3, name: 'iMac' }
}
*/
console.log(productMap[3]); // { id: 3, name: 'iMac' }

 

 

횟수 계산 | Counting Occurrences


λ°°μ—΄ λ‚΄ νŠΉμ • μš”μ†Œκ°€ λͺ‡ 개 μžˆλŠ”μ§€ 계산할 λ•Œλ„ reduce() λ©”μ„œλ“œλ₯Ό ν™œμš©ν•  수 μžˆλ‹€. 빈 객체λ₯Ό μ΄ˆκΈ°κ°’μœΌλ‘œ μ§€μ •ν•˜κ³ , 각 μš”μ†Œλ₯Ό 객체 ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ μˆœνšŒν•  λ•Œλ§ˆλ‹€ 킀에 ν•΄λ‹Ήν•˜λŠ” 카운트λ₯Ό 1μ”© μ¦κ°€ν•˜λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•œλ‹€.

const products = ['iPhone', 'iMac', 'MacBook', 'iPhone', 'iMac', 'iPhone'];

const productCounts = products.reduce((acc, cur) => {
  acc[cur] = (acc[cur] ?? 0) + 1;
  return acc;
}, {});

console.log(productCounts); // { iPhone: 3, iMac: 2, MacBook: 1 }

 

 

ν•¨μˆ˜ ν•©μ„± | Composing Functions


ν•¨μˆ˜ 합성은 μ—¬λŸ¬ ν•¨μˆ˜λ₯Ό ν•˜λ‚˜μ˜ ν•¨μˆ˜λ‘œ κ²°ν•©ν•˜μ—¬, 각 ν•¨μˆ˜μ˜ 좜λ ₯을 λ‹€μŒ ν•¨μˆ˜μ˜ μž…λ ₯으둜 μ‚¬μš©ν•˜λŠ” λ°©μ‹μœΌλ‘œ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 자주 μ‚¬μš©ν•˜λŠ” νŒ¨ν„΄μ΄λ‹€. ν•¨μˆ˜ 합성은 f(g(x)) 와 같이 λ‚΄λΆ€ ν•¨μˆ˜λΆ€ν„° μ™ΈλΆ€ ν•¨μˆ˜ 순으둜 μ‹€ν–‰λ˜λŠ”λ° reduce() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄μ„œ κ΅¬ν˜„ν•  수 μžˆλ‹€.

const compose = (...funcs) => {
  return (x) => funcs.reduce((acc, fn) => fn(acc), x);
};

const increment = (x) => x + 1;
const square = (x) => x * x;
const decrement = (x) => x - 1;

// (x) => func.reduce((acc, f) => f(acc), x)
const composedFunc = compose(increment, square, decrement);
console.log(composedFunc(5)); // 35

 

μœ„ μ˜ˆμ‹œλŠ” μ•„λž˜μ²˜λŸΌ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•œ 것과 λ™μΌν•˜λ‹€.

// imcrement -> square -> decrement
decrement(square(increment(5)));

 

λ§Œμ•½ ν•¨μˆ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό λ°˜λŒ€λ‘œ ν•˜κ³  μ‹Άλ‹€λ©΄ 였λ₯Έμͺ½ μš”μ†ŒλΆ€ν„° μˆœνšŒν•˜λŠ” reduceRight() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.

 

 

쀑볡 제거 | Deduplication


λ°°μ—΄μ˜ 쀑볡 μ œκ±°λŠ” Set() 객체λ₯Ό μ΄μš©ν•˜λ©΄ κ°„λ‹¨ν•˜κ²Œ μˆ˜ν–‰ν•  수 μžˆλ‹€. ν•˜μ§€λ§Œ νŠΉμ • μš”μ†Œμ— λŒ€ν•΄μ„  쀑볡을 ν—ˆμš©ν•˜λŠ” λ“± 좔가적인 λ‘œμ§μ„ μ μš©ν•  수 μ—†λ‹€. 이런 μž‘μ—… μ—­μ‹œ reduce() λ©”μ„œλ“œλ₯Ό ν™œμš©ν•  수 μžˆλ‹€.

const numbers = [1, 1, 2, 3, 2, 2, 6, 8, 8, 11, 12];
const allowList = new Set([8]); // 8은 쀑볡 ν—ˆμš©

const uniqueNumbers = numbers.reduce((res, num) => {
  if (!res.includes(num) || allowList.has(num)) res.push(num);
  return res;
}, []);

console.log(uniqueNumbers); // [ 1, 2, 3, 6, 8, 8, 11, 12 ]

 

 

평균 계산 | Calculating Average


reduce() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄μ„œ 숫자둜 이뀄진 λ°°μ—΄μ˜ 평균값을 계산할 μˆ˜λ„ μžˆλ‹€. 각 μš”μ†Œλ₯Ό μˆœνšŒν•˜λ©΄μ„œ λͺ¨λ“  값을 λ”ν•œ ν›„, λ§ˆμ§€λ§‰ μš”μ†Œλ₯Ό μˆœνšŒν•  땐 총합을 μš”μ†Œ 개수둜 λ‚˜λˆˆ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λ©΄ λœλ‹€.

const rates = [3, 2, 1, 5, 4, 3];

const average = rates.reduce((total, rate, idx, { length }) => {
  const sum = total + rate;
  if (idx === length - 1) return sum / length;
  return sum;
}, 0);

console.log(average); // 3

 

 

ν”„λ‘œλ―ΈμŠ€ 체이닝 | Promise Chaining


자주 μ‚¬μš©ν•˜λŠ” νŒ¨ν„΄μ€ μ•„λ‹ˆμ§€λ§Œ reduce() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄μ„œ ν”„λ‘œλ―ΈμŠ€ 체인을 ꡬ성할 μˆ˜λ„ μžˆλ‹€. λ”œλ ˆμ΄ μ‹œκ°„μ„ λ‚˜νƒ€λ‚΄λŠ” 각 μš”μ†Œλ₯Ό μˆœνšŒν•  λ•Œλ§ˆλ‹€ prevPromise.then(...) ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κ³ , μ΄λ ‡κ²Œ λ°˜ν™˜λœ ν”„λ‘œλ―ΈμŠ€λŠ” λ‹€μŒ 순회의 prevPromiseκ°€ λΌμ„œ 비동기 μž‘μ—…μ„ 순차적으둜 μ‹€ν–‰ν•˜λ„λ‘ λ§Œλ“ λ‹€.

const wait = (delay) => {
  return new Promise((resolve, _reject) => {
    console.log('[wait]', delay);
    setTimeout(() => resolve(delay), delay);
  });
};

const delayList = [1000, 2000, 3000, 4000];

delayList.reduce((prevPromise, curDelay) => {
  console.log('[reduce]', prevPromise, curDelay);
  // μˆœνšŒλ§ˆλ‹€ prevPromise.then(...) ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κ³ , λ‹€μŒ 순회의 prevPromiseκ°€ λœλ‹€
  return prevPromise.then((res) => {
    console.log('[then]', res);
    return wait(curDelay);
  });
}, Promise.resolve('start'));

/*
μœ„ μ½”λ“œλŠ” μ•„λž˜ ν”„λ‘œλ―ΈμŠ€ 체인과 λ™μΌν•˜λ‹€: 
Promise.resolve('start')
  .then(() => wait(1000))
  .then(() => wait(2000))
  .then(() => wait(3000))
  .then(() => wait(4000))
*/

 

μ½˜μ†” 좜λ ₯ κ²°κ³ΌλŠ” μ•„λž˜μ™€ κ°™λ‹€.

 

λͺ¨λ“  λ°°μ—΄ λ©”μ„œλ“œλŠ” λ™κΈ°μ μœΌλ‘œ μž‘λ™ν•˜κΈ° λ•Œλ¬Έμ— 콜백 λ‚΄μ—μ„œ 비동기 μž‘μ—…μ„ μˆ˜ν–‰ν•΄λ„ reduceλŠ” ν”„λ‘œλ―ΈμŠ€κ°€ 처리될 λ•ŒκΉŒμ§€ 기닀리지 μ•Šκ³  λ‹€μŒ μ½œλ°±μ„ μ‹€ν–‰μ‹œν‚¨λ‹€. 즉, 콜백 λ‚΄μ—μ„œ μˆ˜ν–‰ν•œ 비동기 μž‘μ—…μ€ reduce λ©”μ„œλ“œμ˜ μ œμ–΄λ₯Ό λ²—μ–΄λ‚˜ λ³„λ„λ‘œ μ²˜λ¦¬λœλ‹€.

 

λΉ„λ™κΈ°λ‘œ 호좜된 ν•¨μˆ˜λŠ” νƒœμŠ€ν¬ 큐둜 λ“€μ–΄κ°€λŠ”λ°, 큐에 μžˆλŠ” ν•¨μˆ˜λ“€μ€ μ½œμŠ€νƒμ΄ λΉ„μ–΄μžˆμ–΄μ•Όλ§Œ 싀행될 수 μžˆλ‹€. λ”°λΌμ„œ reduce λ©”μ„œλ“œμ˜ λͺ¨λ“  순회λ₯Ό μ™„λ£Œν•œ 후에 비동기 μž‘μ—…λ“€μ΄ μ°¨λ‘€λŒ€λ‘œ μ‹€ν–‰λœλ‹€.

 

πŸ’‘then, catch, finally 같은 후속 처리 λ©”μ„œλ“œλŠ” 항상 ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•œλ‹€. 후속 처리 λ©”μ„œλ“œ μΈμžμ— μ „λ‹¬ν•œ 콜백 ν•¨μˆ˜κ°€ ν”„λ‘œλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜λ©΄ κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜κ³ , ν”„λ‘œλ―ΈμŠ€κ°€ μ•„λ‹Œ 값을 λ°˜ν™˜ν•˜λ©΄ ν•΄λ‹Ή 값을 μ•”λ¬΅μ μœΌλ‘œ resolve ν˜Ήμ€ reject ν•΄μ„œ ν”„λ‘œλ―ΈμŠ€λ₯Ό μƒμ„±ν•œ ν›„ λ°˜ν™˜ν•œλ‹€. ν”„λ‘œλ―ΈμŠ€κ°€ λŒ€κΈ°(pending) μƒνƒœμ΄λ©΄ 후속 처리 λ©”μ„œλ“œλŠ” ν”„λ‘œλ―ΈμŠ€κ°€ 처리되길 기닀리고, 이미 처리(settled) μƒνƒœλΌλ©΄ ν•Έλ“€λŸ¬λŠ” 즉각 μ‹€ν–‰λœλ‹€.

 

 

Immutable vs Mutable


reduce λ©”μ„œλ“œλŠ” 크게 λΆˆλ³€(Immutable)κ³Ό κ°€λ³€(Mutable) 2κ°€μ§€ μ‚¬μš© λ°©μ‹μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. λΆˆλ³€μ€ 이름 κ·ΈλŒ€λ‘œ ν•œ 번 μƒμ„±ν•œ ν›„ λ³€κ²½ν•  수 μ—†λŠ” 값을, 가변은 μƒμ„±ν•œ 후에도 λ³€κ²½ν•  수 μžˆλŠ” 값을 μ˜λ―Έν•œλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„  μ›μ‹œν˜• 데이터 νƒ€μž…μ΄ λΆˆλ³€μ„±μ„ κ°€μ§€λ©°, μ°Έμ‘°ν˜•μ€ 기본적으둜 가변성을 κ°€μ§„λ‹€.

 

λΆˆλ³€μ μΈ μ‚¬μš© 방식은 μš”μ†Œλ₯Ό μˆœνšŒν•  λ•Œλ§ˆλ‹€ κΈ°μ‘΄ λˆ„μ  값을 λ³€κ²½ν•˜μ§€ μ•Šκ³  항상 μƒˆλ‘œμš΄ κ°μ²΄λ‚˜ 배열을 μƒμ„±ν•˜λŠ” 방식을 가리킨닀. κΈ°μ‘΄ μƒνƒœλ₯Ό λ³€κ²½ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ‚¬μ΄λ“œ μ΄νŽ™νŠΈλ₯Ό λ°©μ§€ν•  수 있고 가독성이 쒋은 λŒ€μ‹ , λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ 증가할 수 μžˆλŠ” 단점이 μžˆλ‹€.

// Immutable
const doubledNumbers = [1, 2, 3].reduce((acc, cur) => {
  return [...acc, cur * 2];
}, []);

 

가변적인 μ‚¬μš© 방식은 κΈ°μ‘΄ λˆ„μ  값을 직접 λ³€κ²½ν•˜μ—¬ κ²°κ³Όλ₯Ό λ§Œλ“œλŠ” 방식을 가리킨닀. κΈ°μ‘΄ κ°μ²΄λ‚˜ 배열을 직접 μˆ˜μ •ν•˜κΈ° λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ 적은 λŒ€μ‹ , μ½”λ“œ 가독성이 λ–¨μ–΄μ§€κ³  μ‚¬μ΄λ“œ μ΄νŽ™νŠΈκ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆλ‹€.

// Mutable
const doubledNumbers = [1, 2, 3].reduce((acc, cur) => {
  acc.push(cur * 2);
  return acc;
}, []);

 

λΆˆλ³€μ„±κ³Ό κ°€λ³€μ„± 각각 μž₯단점이 있기 λ•Œλ¬Έμ— μ–΄λ–€ 방식이 항상 μ˜³λ‹€κ³  단정할 μˆ˜λŠ” μ—†λ‹€. 데이터 양이 많고 μ„±λŠ₯이 μ€‘μš”ν•œ κ²½μš°μ—” 가변성을 μ‚¬μš©ν•˜λŠ” 게 μœ λ¦¬ν•  수 μžˆλ‹€. 반면, μ½”λ“œ κ°€λ…μ„±μ΄λ‚˜ μœ μ§€λ³΄μˆ˜μ„±μ΄ μ€‘μš”ν•˜λ‹€λ©΄ λΆˆλ³€μ„±μ„ κ³ λ €ν•  수 μžˆλ‹€.

 

 

레퍼런슀


 


κΈ€ μˆ˜μ •μ‚¬ν•­μ€ λ…Έμ…˜ νŽ˜μ΄μ§€μ— κ°€μž₯ λΉ λ₯΄κ²Œ λ°˜μ˜λ©λ‹ˆλ‹€. 링크λ₯Ό μ°Έκ³ ν•΄ μ£Όμ„Έμš”
λ°˜μ‘ν˜•