๐ŸŽฏ ์ปค๋ง ๊ธฐ๋ฒ•์œผ๋กœ ํ•จ์ˆ˜ ์žฌ์‚ฌ์šฉ์„ฑ ๋†’์ด๊ธฐ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐ŸŽฏ ์ปค๋ง ๊ธฐ๋ฒ•์œผ๋กœ ํ•จ์ˆ˜ ์žฌ์‚ฌ์šฉ์„ฑ ๋†’์ด๊ธฐ ๐Ÿš€

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ JavaScript์˜ ๊ฟ€ํŒ ์ค‘ ํ•˜๋‚˜์ธ '์ปค๋ง(Currying)' ๊ธฐ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ด ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•˜๋ฉด ํ•จ์ˆ˜์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ์—„์ฒญ๋‚˜๊ฒŒ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ˜Ž ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด ๊ฐœ๋…์„ ๋“ค์–ด๋ณด์…จ์„ ์ˆ˜๋„ ์žˆ๊ฒ ๋„ค์š”.

๊ทธ๋Ÿผ ์ง€๊ธˆ๋ถ€ํ„ฐ ์ปค๋ง์˜ ์„ธ๊ณ„๋กœ ๋น ์ ธ๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? 3, 2, 1... ์ถœ๋ฐœ! ๐Ÿ

๐Ÿ’ก Tip: ์ปค๋ง์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜๋กœ, ๋ณต์žกํ•œ ํ•จ์ˆ˜๋ฅผ ๊ฐ„๋‹จํ•œ ํ•จ์ˆ˜๋“ค์˜ ์กฐํ•ฉ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ธฐ๋ฒ•์ด์—์š”. ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ฐจ๊ทผ์ฐจ๊ทผ ์„ค๋ช…๋“œ๋ฆด ํ…Œ๋‹ˆ ๊ฑฑ์ • ๋งˆ์„ธ์š”!

๐Ÿค” ์ปค๋ง์ด ๋ญ๊ธธ๋ž˜?

์ปค๋ง์ด๋ผ... ๋ญ”๊ฐ€ ๋ง›์žˆ๋Š” ์Œ์‹ ์ด๋ฆ„ ๊ฐ™์ง€ ์•Š๋‚˜์š”? ใ…‹ใ…‹ใ…‹ ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์ปค๋ง์€ ๋จน๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์ฝ”๋”ฉํ•˜๋Š” ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜„

์ปค๋ง์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธ์ž๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜๋ฅผ ๋‹จ์ผ ์ธ์ž๋ฅผ ๊ฐ€์ง„ ํ•จ์ˆ˜๋“ค์˜ ์ฒด์ธ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋ฐฉ๋ฒ•์ด์—์š”. ์Œ... ๋ญ” ์†Œ๋ฆฌ๋ƒ๊ณ ์š”? ๊ฑฑ์ • ๋งˆ์„ธ์š”, ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”!

๐Ÿ› ์Œ์‹์œผ๋กœ ๋น„์œ ํ•ด๋ณด์ž๋ฉด: ์ปค๋ง์€ ๋งˆ์น˜ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žฌ๋ฃŒ๋ฅผ ํ•œ ๋ฒˆ์— ๋„ฃ๊ณ  ์š”๋ฆฌํ•˜๋Š” ๋Œ€์‹ , ๊ฐ ์žฌ๋ฃŒ๋ฅผ ์ฐจ๋ก€๋Œ€๋กœ ๋„ฃ์–ด๊ฐ€๋ฉฐ ์š”๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ค‘๊ฐ„ ๊ณผ์ •์—์„œ ๋‹ค์–‘ํ•œ ๋ง›์„ ๋งŒ๋“ค์–ด๋‚ผ ์ˆ˜ ์žˆ์ฃ !

๐ŸŒŸ ์ปค๋ง์˜ ๊ธฐ๋ณธ ๊ฐœ๋…

์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜๋Š” ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ์–ด์š”:

function add(a, b, c) {
  return a + b + c;
}

console.log(add(1, 2, 3)); // 6

์ด๊ฑธ ์ปค๋ง์œผ๋กœ ๋ฐ”๊พธ๋ฉด ์ด๋ ‡๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:

function curryAdd(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    }
  }
}

console.log(curryAdd(1)(2)(3)); // 6

์–ด๋–ค๊ฐ€์š”? ๋ญ”๊ฐ€ ๋ณต์žกํ•ด ๋ณด์ด์ฃ ? ใ…‹ใ…‹ใ…‹ ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—„์ฒญ๋‚œ ์žฅ์ ์ด ์žˆ๋‹ต๋‹ˆ๋‹ค!

๐ŸŽญ ์ปค๋ง์˜ ์žฅ์ 

  • ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์›Œ์ ธ์š”.
  • ๋ถ€๋ถ„ ์ ์šฉ(Partial Application)์ด ๊ฐ€๋Šฅํ•ด์ ธ์š”.
  • ์ฝ”๋“œ๊ฐ€ ๋” ์œ ์—ฐํ•ด์ง€๊ณ  ์กฐํ•ฉํ•˜๊ธฐ ์‰ฌ์›Œ์ ธ์š”.

์ด๊ฒŒ ๋Œ€์ฒด ๋ฌด์Šจ ๋ง์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค๊ณ ์š”? ๊ฑฑ์ • ๋งˆ์„ธ์š”! ์ง€๊ธˆ๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ์ž์„ธํžˆ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”. ๐Ÿ˜‰

์ปค๋ง์˜ ๊ฐœ๋… ๋„์‹ํ™” ์ปค๋ง์˜ ๋งˆ๋ฒ• โœจ ์ผ๋ฐ˜ ํ•จ์ˆ˜ ์ปค๋ง ํ•จ์ˆ˜ ์žฌ์‚ฌ์šฉ์„ฑ โฌ†๏ธ

๐Ÿ” ์ปค๋ง์˜ ์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์‹œ

์ž, ์ด์ œ ์ปค๋ง์„ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ๊นŒ์š”? ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด๋Ÿฐ ์˜ˆ์‹œ๊ฐ€ ๋„์›€์ด ๋  ๊ฑฐ์˜ˆ์š”!

1. ๐Ÿ›  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

๋จผ์ €, ๊ฐ„๋‹จํ•œ ๊ณฑํ•˜๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”.

function multiply(a, b) {
  return a * b;
}

console.log(multiply(2, 3)); // 6
console.log(multiply(2, 4)); // 8
console.log(multiply(2, 5)); // 10

์ด ํ•จ์ˆ˜๋ฅผ ์ปค๋ง์œผ๋กœ ๋ฐ”๊ฟ”๋ณผ๊นŒ์š”?

function curryMultiply(a) {
  return function(b) {
    return a * b;
  }
}

const multiplyByTwo = curryMultiply(2);
console.log(multiplyByTwo(3)); // 6
console.log(multiplyByTwo(4)); // 8
console.log(multiplyByTwo(5)); // 10

์–ด๋–ค๊ฐ€์š”? multiplyByTwo๋ผ๋Š” ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋์–ด์š”! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค. ๐Ÿ‘

2. ๐ŸŽจ ์Šคํƒ€์ผ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด ์Šคํƒ€์ผ์„ ์ž์ฃผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์ฃ . ์ปค๋ง์„ ์ด์šฉํ•˜๋ฉด ์ด๋Ÿฐ ์ž‘์—…์„ ํ›จ์”ฌ ํŽธํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”!

function setStyle(property) {
  return function(value) {
    return function(element) {
      element.style[property] = value;
      return element;
    }
  }
}

const setColor = setStyle('color');
const setBackgroundColor = setStyle('backgroundColor');

const setRedColor = setColor('red');
const setBlueBackground = setBackgroundColor('blue');

// ์‚ฌ์šฉ ์˜ˆ์‹œ
const div = document.createElement('div');
setRedColor(div);
setBlueBackground(div);

์™€์šฐ! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํƒ€์ผ ํ•จ์ˆ˜๋ฅผ ์—„์ฒญ ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์›น ๋””์ž์ธ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด ๊ธฐ๋ฒ•์˜ ์œ ์šฉํ•จ์„ ๋ฐ”๋กœ ์•Œ์•„์ฐจ๋ฆฌ์‹ค ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜Ž

3. ๐Ÿ” ์ธ์ฆ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ธ์ฆ์€ ์ •๋ง ์ค‘์š”ํ•˜์ฃ . ์ปค๋ง์„ ์ด์šฉํ•˜๋ฉด ์ธ์ฆ ๋กœ์ง์„ ๋” ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”.

function authenticate(username) {
  return function(password) {
    return function(role) {
      // ์‹ค์ œ๋กœ๋Š” ์—ฌ๊ธฐ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฒดํฌ ๋“ฑ์˜ ๋กœ์ง์ด ๋“ค์–ด๊ฐˆ ๊ฑฐ์˜ˆ์š”
      console.log(`Authenticating ${username} with role ${role}`);
      return username === 'admin' && password === '1234' && role === 'admin';
    }
  }
}

const authenticateAdmin = authenticate('admin')('1234')('admin');
console.log(authenticateAdmin); // true

const authenticateUser = authenticate('user')('5678')('user');
console.log(authenticateUser); // false

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ธ์ฆ ๋กœ์ง์„ ๋‹จ๊ณ„๋ณ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์–ด์„œ ์ฝ”๋“œ ๊ด€๋ฆฌ๊ฐ€ ํ›จ์”ฌ ์‰ฌ์›Œ์ ธ์š”. ๐Ÿ‘จโ€๐Ÿ’ป

๐Ÿ’ก Tip: ์ปค๋ง์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜์˜ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์•„์ง€๊ณ , ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๋„ ์ข‹์•„์งˆ ์ˆ˜ ์žˆ์–ด์š”. ํ•˜์ง€๋งŒ ๋„ˆ๋ฌด ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด์š”!

๐Ÿš€ ์ปค๋ง์˜ ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•

์ž, ์ด์ œ ๊ธฐ๋ณธ์ ์ธ ์ปค๋ง์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์œผ๋‹ˆ ์กฐ๊ธˆ ๋” ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•์œผ๋กœ ๋“ค์–ด๊ฐ€๋ณผ๊นŒ์š”? ๐Ÿ˜Ž

1. ๐Ÿ”„ ๋ถ€๋ถ„ ์ ์šฉ (Partial Application)

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

function partial(fn, ...args) {
  return function(...moreArgs) {
    return fn(...args, ...moreArgs);
  }
}

function add(a, b, c) {
  return a + b + c;
}

const add5 = partial(add, 5);
console.log(add5(10, 15)); // 30

const add5and10 = partial(add, 5, 10);
console.log(add5and10(15)); // 30

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•จ์ˆ˜์˜ ์ผ๋ถ€ ์ธ์ž๋ฅผ ๋ฏธ๋ฆฌ "๊ณ ์ •"์‹œ์ผœ๋†“๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์—„์ฒญ ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ˜ƒ

2. ๐Ÿ”€ ํ•จ์ˆ˜ ์กฐํ•ฉ (Function Composition)

์ปค๋ง์„ ์ด์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์กฐํ•ฉํ•ด์„œ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์ด๊ฑธ ํ•จ์ˆ˜ ์กฐํ•ฉ์ด๋ผ๊ณ  ํ•ด์š”.

function compose(...fns) {
  return function(x) {
    return fns.reduceRight((v, f) => f(v), x);
  }
}

const double = x => x * 2;
const increment = x => x + 1;
const square = x => x * x;

const doubleIncrementAndSquare = compose(square, increment, double);

console.log(doubleIncrementAndSquare(3)); // (3 * 2 + 1)^2 = 49

์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์ฒ˜๋Ÿผ ์กฐ๋ฆฝํ•ด์„œ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด ๊ธฐ๋ฒ•์˜ ๊ฐ•๋ ฅํ•จ์„ ๋Š๋ผ์‹ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿงฑ

3. ๐ŸŽญ ์ปค๋ง๊ณผ ํด๋กœ์ €

์ปค๋ง์€ ํด๋กœ์ €์™€ ๋ฐ€์ ‘ํ•œ ๊ด€๋ จ์ด ์žˆ์–ด์š”. ํด๋กœ์ €๋ฅผ ์ด์šฉํ•ด ์ปค๋ง ํ•จ์ˆ˜์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์ฃ .

function counter() {
  let count = 0;
  return function(increment = 1) {
    count += increment;
    return count;
  }
}

const myCounter = counter();
console.log(myCounter()); // 1
console.log(myCounter(2)); // 3
console.log(myCounter(5)); // 8

์ด ์˜ˆ์ œ์—์„œ myCounter ํ•จ์ˆ˜๋Š” ๋‚ด๋ถ€ ์ƒํƒœ(count)๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผœ์š”. ์ด๋Ÿฐ ์‹์œผ๋กœ ์ปค๋ง๊ณผ ํด๋กœ์ €๋ฅผ ์กฐํ•ฉํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿ’ช

์ปค๋ง๊ณผ ํด๋กœ์ €์˜ ๊ด€๊ณ„ ์ปค๋ง๊ณผ ํด๋กœ์ €์˜ ๋งˆ๋ฒ• โœจ ์ปค๋ง ํด๋กœ์ € ์ƒํ˜ธ์ž‘์šฉ ํ•จ์ˆ˜์˜ ์ƒํƒœ ์œ ์ง€์™€ ์žฌ์‚ฌ์šฉ์„ฑ ์ฆ๊ฐ€

๐Ÿค” ์ปค๋ง, ์–ธ์ œ ์จ์•ผ ํ• ๊นŒ?

์ž, ์ด์ œ ์ปค๋ง์— ๋Œ€ํ•ด ๋งŽ์ด ์•Œ๊ฒŒ ๋์ฃ ? ๊ทธ๋Ÿฐ๋ฐ ์ด๊ฑธ ์–ธ์ œ ์จ์•ผ ํ• ์ง€ ๊ถ๊ธˆํ•˜์‹ค ๊ฑฐ์˜ˆ์š”. ๊ฑฑ์ • ๋งˆ์„ธ์š”! ์ œ๊ฐ€ ์•Œ๋ ค๋“œ๋ฆด๊ฒŒ์š”. ๐Ÿ˜‰

1. ๐Ÿ“š ์„ค์ • ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃฐ ๋•Œ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์„ค์ • ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์ปค๋ง์ด ์œ ์šฉํ•ด์š”.

function createConfig(baseConfig) {
  return function(userConfig) {
    return {...baseConfig, ...userConfig};
  }
}

const createServerConfig = createConfig({host: 'localhost', port: 8080});

const devConfig = createServerConfig({env: 'development'});
console.log(devConfig); // {host: 'localhost', port: 8080, env: 'development'}

const prodConfig = createServerConfig({env: 'production', port: 80});
console.log(prodConfig); // {host: 'localhost', port: 80, env: 'production'}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ธฐ๋ณธ ์„ค์ •์„ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ๋ณ„ ์„ค์ •์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์„œ๋ฒ„ ๊ฐœ๋ฐœ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด ๊ธฐ๋ฒ•์˜ ์œ ์šฉํ•จ์„ ๋ฐ”๋กœ ์•Œ์•„์ฐจ๋ฆฌ์‹ค ๊ฑฐ์˜ˆ์š”! ๐Ÿ–ฅ๏ธ

2. ๐ŸŽจ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋งŒ๋“ค๊ธฐ

์›น ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋งŒ๋“ค ๋•Œ๋„ ์ปค๋ง์ด ์œ ์šฉํ•ด์š”.

function handleEvent(eventType) {
  return function(className) {
    return function(callback) {
      document.querySelector(className).addEventListener(eventType, callback);
    }
  }
}

const handleClick = handleEvent('click');
const handleHover = handleEvent('mouseover');

const handleButtonClick = handleClick('.button');
const handleLinkHover = handleHover('.link');

handleButtonClick(() => console.log('Button clicked!'));
handleLinkHover(() => console.log('Link hovered!'));

์™€์šฐ! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ •๋ง ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ‘จโ€๐Ÿ’ป

3. ๐Ÿ” ๊ฒ€์ƒ‰ ๋ฐ ํ•„ํ„ฐ๋ง ํ•จ์ˆ˜

๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ฑฐ๋‚˜ ํ•„ํ„ฐ๋งํ•  ๋•Œ๋„ ์ปค๋ง์ด ํฐ ๋„์›€์ด ๋ผ์š”.

function filter(property) {
  return function(value) {
    return function(array) {
      return array.filter(item => item[property] === value);
    }
  }
}

const filterByColor = filter('color');
const filterRed = filterByColor('red');

const items = [
  {name: 'apple', color: 'red'},
  {name: 'banana', color: 'yellow'},
  {name: 'cherry', color: 'red'}
];

console.log(filterRed(items)); // [{name: 'apple', color: 'red'}, {name: 'cherry', color: 'red'}]

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค์–‘ํ•œ ์†์„ฑ๊ณผ ๊ฐ’์œผ๋กœ ๋ฐฐ์—ด์„ ์‰ฝ๊ฒŒ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋งŽ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ •๋ง ์œ ์šฉํ•˜๋‹ต๋‹ˆ๋‹ค! ๐Ÿ“Š

๐Ÿš€ Pro Tip: ์ปค๋ง์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์˜ˆ์š”. ์žฌ๋Šฅ๋„ท์—์„œ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณด์‹œ๋ฉด ์ด๋Ÿฐ ๊ฐœ๋…๋“ค์„ ๋” ๊นŠ์ด ์ดํ•ดํ•˜์‹ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”!

๐Ÿงช ์ปค๋ง์˜ ์‹ค์ „ ์‘์šฉ

์ž, ์ด์ œ ์ปค๋ง์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์œผ๋‹ˆ, ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿ•ต๏ธโ€โ™‚๏ธ

1. ๐ŸŒ API ํ˜ธ์ถœ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋‹ค ๋ณด๋ฉด API๋ฅผ ์ž์ฃผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜์ฃ . ์ปค๋ง์„ ์ด์šฉํ•˜๋ฉด API ํ˜ธ์ถœ ํ•จ์ˆ˜๋ฅผ ์ •๋ง ์šฐ์•„ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”!

function createAPI(baseURL) {
  return function(endpoint) {
    return function(method) {
      return function(data) {
        return fetch(`${baseURL}${endpoint}`, {
          method: method,
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        }).then(response => response.json());
      }
    }
  }
}

const api = createAPI('https://api.example.com');
const usersAPI = api('/users');
const createUser = usersAPI('POST');
const updateUser = usersAPI('PUT');

// ์‚ฌ์šฉ ์˜ˆ์‹œ
createUser({name: 'John', age: 30}).then(user => console.log(user));
updateUser({id: 1, name: 'John Doe'}).then(user => console.log(user));

์–ด๋–ค๊ฐ€์š”? ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด API ํ˜ธ์ถœ ํ•จ์ˆ˜๋ฅผ ์ •๋ง ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด ๊ธฐ๋ฒ•์˜ ๊ฐ•๋ ฅํ•จ์„ ๋ฐ”๋กœ ๋Š๋ผ์‹ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ’ช

2. ๐ŸŽญ ๋ฏธ๋“ค์›จ์–ด ์ฒด์ธ ๋งŒ๋“ค๊ธฐ

์„œ๋ฒ„ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์ฃ . ์ปค๋ง์„ ์ด์šฉํ•˜๋ฉด ๋ฏธ๋“ค์›จ์–ด ์ฒด์ธ์„ ์•„์ฃผ ์šฐ์•„ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”.

function compose(...middlewares) {
  return function(ctx, next) {
    function dispatch(i) {
      let fn = middlewares[i];
      if (i === middlewares.length) fn = next;
      if (!fn) return Promise.resolve();
      try {
        return Promise.resolve(fn(ctx, function next() {
          return dispatch(i + 1);
        }));
      } catch (err) {
        return Promise.reject(err);
      }
    }
    return dispatch(0);
  }
}

const logger = (ctx, next) => {
  console.log(`${ctx.method} ${ctx.url}`);
  return next();
};

const errorHandler = (ctx, next) => {
  return next().catch(err => {
    console.error(err);
    ctx.status = err.status || 500;
    ctx.body = {error: err.message};
  });
};

const app = compose(errorHandler, logger);

// ์‚ฌ์šฉ ์˜ˆ์‹œ
app({method: 'GET', url: '/users'}, () => {
  throw new Error('Something went wrong');
}).then(() => console.log('Done'));

์™€์šฐ! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ •๋ง ์œ ์—ฐํ•˜๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์„œ๋ฒ„ ๊ฐœ๋ฐœ์ด ํ•œ์ธต ๋” ์žฌ๋ฏธ์žˆ์–ด์งˆ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜Ž

3. ๐ŸŽจ ์Šคํƒ€์ผ ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ

ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ์Šคํƒ€์ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜์ฃ ? ์ปค๋ง์„ ์ด์šฉํ•˜๋ฉด ์ •๋ง ๋ฉ‹์ง„ ์Šคํƒ€์ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”!

function styled(element) {
  return function(strings, ...values) {
    return function(props) {
      const style = strings.reduce((acc, str, i) => {
        return acc + str + (values[i] ? values[i](props) : '');
      }, '');
      
      const el = document.createElement(element);
      el.style.cssText = style;
      return el;
    }
  }
}

const Button = styled('button')`
  background-color: ${props => props.primary ? 'blue' : 'gray'};
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
`;

// ์‚ฌ์šฉ ์˜ˆ์‹œ
const primaryButton = Button({primary: true});
document.body.appendChild(primaryButton);

const secondaryButton = Button({primary: false});
document.body.appendChild(secondaryButton);

์–ด๋–ค๊ฐ€์š”? ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํƒ€์ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ •๋ง ์šฐ์•„ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ ๊ฐ•์˜๋ฅผ ๋“ค์–ด๋ณธ ๋ถ„๋“ค์ด๋ผ๋ฉด ์ด ๊ธฐ๋ฒ•์˜ ๋งค๋ ฅ์— ํ‘น ๋น ์ง€์‹ค ๊ฑฐ์˜ˆ์š”! ๐ŸŽจ

๐Ÿ’ก Tip: ์ปค๋ง์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•จ์ˆ˜์˜ ์ธ์ž ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•ด์š”. ๊ฐ€์žฅ ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ์ธ์ž๋ฅผ ๋งˆ์ง€๋ง‰์— ๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ต๋‹ˆ๋‹ค!

๐Ÿง  ์ปค๋ง์˜ ์‹ฌํ™” ๊ฐœ๋…

์ž, ์ด์ œ ์ปค๋ง์˜ ๊ธฐ๋ณธ๊ณผ ์‘์šฉ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์œผ๋‹ˆ, ์กฐ๊ธˆ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๋ณผ๊นŒ์š”? ๐Ÿ•ต๏ธโ€โ™€๏ธ

1. ๐Ÿ”„ ์ž๋™ ์ปค๋ง (Auto-currying)

์ง€๊ธˆ๊นŒ์ง€๋Š” ์ˆ˜๋™์œผ๋กœ ์ปค๋ง์„ ๋งŒ๋“ค์–ด์™”์ง€๋งŒ, ํ•จ์ˆ˜๋ฅผ ์ž๋™์œผ๋กœ ์ปค๋งํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์–ด์š”!

function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };
}

function add(a, b, c) {
  return a + b + c;
}

const curriedAdd = curry(add);

console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1, 2, 3)); // 6

์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์–ด๋–ค ํ•จ์ˆ˜๋“  ์ž๋™์œผ๋กœ ์ปค๋งํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ •๋ง ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ˜Ž

2. ๐Ÿ”€ ์ปค๋ง๊ณผ ํ•จ์ˆ˜ ํ•ฉ์„ฑ (Function Composition)

์ปค๋ง์€ ํ•จ์ˆ˜ ํ•ฉ์„ฑ๊ณผ ๊ถํ•ฉ์ด ์ •๋ง ์ข‹์•„์š”. ๋‘ ๊ฐœ๋…์„ ์กฐํ•ฉํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ฃ !

const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);

const add = x  => y => x + y;
const multiply = x => y => x * y;
const divide = x => y => y / x;

const calculate = compose(
  add(5),
  multiply(2),
  divide(4)
);

console.log(calculate(20)); // ((20 / 4) * 2) + 5 = 15

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ณต์žกํ•œ ์ˆ˜ํ•™ ์—ฐ์‚ฐ๋„ ์•„์ฃผ ์šฐ์•„ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ์ˆ˜ํ•™ ๊ณต์‹์„ ์“ฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ ! ๐Ÿงฎ

3. ๐Ÿญ ์ปค๋ง ํŒฉํ† ๋ฆฌ (Currying Factory)

์ปค๋ง์„ ์ด์šฉํ•ด ํ•จ์ˆ˜ ํŒฉํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์–ด์š”. ์ด๋ฅผ ํ†ตํ•ด ๋น„์Šทํ•œ ํŒจํ„ด์˜ ํ•จ์ˆ˜๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์ฃ .