๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Frontend Dev/JavaScript

๊ณ ์ฐจ ํ•จ์ˆ˜(higher order function)๋ž€ ๋ฌด์—‡์ผ๊นŒ?

๋ฐ˜์‘ํ˜•

๐Ÿ‘พ ๊ณ ์ฐจํ•จ์ˆ˜(higher order function)๋ž€?

 ๊ณ ์ฐจ ํ•จ์ˆ˜๋Š” โ‘  ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ์ธ์ž(argument)๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ , โ‘ก ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜์ด๋‹ค.

 

โœ”๏ธ 1. ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ๊ฒฝ์šฐ

 ๋‹ค๋ฅธ ํ•จ์ˆ˜(caller)์˜ ์ „๋‹ฌ์ธ์ž(argument)๋กœ ์ „๋‹ฌ๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ผ๊ณ  ํ•œ๋‹ค. ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” ์ฃผ๋กœ ์–ด๋–ค ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

 ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ๋ฐ›์€ ๊ณ ์ฐจ ํ•จ์ˆ˜(caller)๋Š”, ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ(invoke)ํ•  ์ˆ˜ ์žˆ๊ณ , ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์‹คํ–‰ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์•„์˜ˆ ํ˜ธ์ถœํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๊ณ , ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

function double(num) {
  return num * 2;
}

// doubleNum์€ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ๊ณ ์ฐจ ํ•จ์ˆ˜
// doubleNum์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž func์— ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ ํ•จ์ˆ˜ func๋Š” ํ•จ์ˆ˜ doubleNum์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜
function doubleNum(func, num) {
  return func(num);
}

// ํ•จ์ˆ˜ double์€ ํ•จ์ˆ˜ doubleNum์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜
console.log( doubleNum(double, 4) )

 

โœ”๏ธ 2. ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜

 ‘ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜'๋Š” ์ด๋ฅผ ๊ณ ์•ˆํ•ด ๋‚ธ ๋…ผ๋ฆฌํ•™์ž ํ•˜์Šค์ผˆ ์ปค๋ฆฌ(Haskell Curry)์˜ ์ด๋ฆ„์„ ๋”ฐ ์ปค๋ง ํ•จ์ˆ˜๋ผ๊ณ  ํ•œ๋‹ค. ๋”ฐ๋กœ ์ปค๋ง ํ•จ์ˆ˜๋ผ๋Š” ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š”, ๊ณ ์ฐจ ํ•จ์ˆ˜๋ผ๋Š” ์šฉ์–ด๋ฅผ 'ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜'์—๋งŒ ํ•œ์ •ํ•ด ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ •ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•˜์ž๋ฉด, ๊ณ ์ฐจ ํ•จ์ˆ˜๊ฐ€ ์ปค๋ง ํ•จ์ˆ˜๋ฅผ ํฌํ•จํ•œ๋‹ค.

 

// adder๋Š” ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ณ ์ฐจ ํ•จ์ˆ˜
/* adder๋Š” ์ธ์ž ํ•œ ๊ฐœ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„์„œ ํ•จ์ˆ˜(์ต๋ช… ํ•จ์ˆ˜)๋ฅผ ๋ฆฌํ„ดํ•˜๊ณ ,
๋ฆฌํ„ด๋˜๋Š” ์ต๋ช… ํ•จ์ˆ˜๋Š” ์ธ์ž ํ•œ ๊ฐœ๋ฅผ ๋ฐ›์•„์„œ added์™€ ๋”ํ•œ ๊ฐ’์„ ๋ฆฌํ„ด */
function adder(added) {
  return function (num) {
    return num + added;
  };
}

console.log( adder(5)(3) ); // 8

const add3 = adder(3);
console.log( add3(2) ); // 5

 

โœ”๏ธ 3. ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ณ , ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜

// double์€ ํ•จ์ˆ˜ doubleAdder์˜ ์ฝœ๋ฐฑ์œผ๋กœ ์ „๋‹ฌ
function double(num) {
  return num * 2;
}

// doubleAdder๋Š” ๊ณ ์ฐจ ํ•จ์ˆ˜
// doubleAdder์˜ ํ•จ์ˆ˜ func๋Š” doubleAdder์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜
function doubleAdder(added, func) {
  const doubled = func(added);
  return function (num) {
    return num + doubled;
  };
}

// doubleAdder(5, double)๋Š” ํ•จ์ˆ˜์ด๋ฏ€๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ธฐํ˜ธ '()'๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
console.log( doubleAdder(5, double)(3) ) // 13

// doubleAdder๊ฐ€ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ณ€์ˆ˜์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. (์ผ๊ธ‰ ๊ฐ์ฒด)
const addTwice3 = doubleAdder(3, double);
console.log( addTwice3(2) ) // 8

 

๐Ÿ‘พ ๋‚ด์žฅ๊ณ ์ฐจํ•จ์ˆ˜

 ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—๋Š” ๋‹ค์–‘ํ•œ ๋‚ด์žฅ ๊ณ ์ฐจ ํ•จ์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉฐ, ๋‚ด์žฅ ๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ๊ณ ์ฐจ ํ•จ์ˆ˜ ์ค‘์—๋Š” ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๋“ค ์ค‘ ์ผ๋ถ€๊ฐ€ ์žˆ๋‹ค.

 ex. mapfilterreduceforEachsort ...

 

 

๐Ÿ‘พ ๊ณ ์ฐจํ•จ์ˆ˜์™€ ์ถ”์ƒํ™”

• ์ถ”์ƒํ™”(abstraction) : ๋ณต์žกํ•œ ์–ด๋–ค ๊ฒƒ์„ ์••์ถ•ํ•ด์„œ ํ•ต์‹ฌ๋งŒ ์ถ”์ถœํ•œ ์ƒํƒœ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ.

 

 ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ๋•Œ, ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋กœ์ง์€ ๋ณ„๋„์˜ ํ•จ์ˆ˜๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋„ ์ถ”์ƒํ™”์˜ ์‚ฌ๋ก€์ด๋‹ค. ์ถ”์ƒํ™”์˜ ๊ด€์ ์—์„œ ํ•จ์ˆ˜๋ฅผ ๋ฐ”๋ผ๋ณด๋ฉด, ํ•จ์ˆ˜๋Š” ์‚ฌ๊ณ (thought)๋˜๋Š” ๋…ผ๋ฆฌ(logic)์˜ ๋ฌถ์Œ์ด๋‹ค. ์ถ”์ƒํ™”๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ๋กœ์ง์„ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ํšจ์œจ์ ์œผ๋กœ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

 ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์–ป์€ ์ถ”์ƒํ™”๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋” ๋†’์ธ ๊ฒƒ์ด ๊ณ ์ฐจ ํ•จ์ˆ˜์ด๋ฉฐ, ๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ณด๋‹ค ๋†’์€ ์ˆ˜์ค€(higher order)์—์„œ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 


 

โœ๏ธ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์ž˜๋ชป๋œ ์ •๋ณด๋‚˜ ๋” ๊ณต์œ ํ•  ๋‚ด์šฉ์ด ์žˆ์œผ๋ฉด ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”!

์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜Š

๋ฐ˜์‘ํ˜•