๐Ÿฏ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(callback function)

Boriยท2022๋…„ 3์›” 19์ผ
4
post-thumbnail

์ฝœ๋ฐฑ ํ•จ์ˆ˜(callback function)๋ž€?

  • ๋‹ค๋ฅธ ์ฝ”๋“œ์˜ ์ธ์ž๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ํ•จ์ˆ˜
  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ : ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ•„์š”์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์‹œ์ ์— ์‹คํ–‰
    • ์ ์ ˆํ•œ ์‹œ์  = ํŠน์ • ์กฐ๊ฑด
    • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ๋Š” ํŠน์ • ์กฐ๊ฑด์ผ ๋•Œ, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰
    • ํ•ด๋‹น ์กฐ๊ฑด์ด ๊ฐ–์ถ”์–ด์กŒ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ๊ฐ€ ํŒ๋‹จํ•˜์—ฌ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ
    • ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ œ์–ด๊ถŒ์ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ์—๊ฒŒ ๋„˜์–ด๊ฐ

โ‡’ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ(ํ•จ์ˆ˜ ๋˜๋Š” ๋ฉ”์„œ๋“œ)์—๊ฒŒ ์ธ์ž๋กœ ๋„˜๊ฒจ์คŒ์œผ๋กœ์จ ๊ทธ ์ œ์–ด๊ถŒ๋„ ํ•จ๊ป˜ ์œ„์ž„ํ•œ ํ•จ์ˆ˜

์ œ์–ด๊ถŒ

ํ˜ธ์ถœ ์‹œ์ 

์˜ˆ์ œ 4-2) setInterval

var count = 0;

// ์ฝ˜์†”์ฐฝ์— 0.3์ดˆ์— ํ•œ ๋ฒˆ์”ฉ ์ˆซ์ž๊ฐ€ 0๋ถ€ํ„ฐ 1์”ฉ ์ฆ๊ฐ€ํ•˜๋ฉด์„œ ์ถœ๋ ฅ, 4๊ฐ€ ์ถœ๋ ฅ๋œ ์ดํ›„ ์ข…๋ฃŒ
var cbFunc = function() {
  console.log(count);
  if (++count > 4) clearInterval(timer);
};

var timer = serInterval(cbFunction, 300);

setInterval : ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ

cbFunc : ์ฝœ๋ฐฑ ํ•จ์ˆ˜

  • setInterval์— ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ cbFunc ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์คŒ
  • ์ œ์–ด๊ถŒ์„ ๋„˜๊ฒจ๋ฐ›์€ setInterval์ด ์Šค์Šค๋กœ์˜ ํŒ๋‹จ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์‹œ์ (0.3์ดˆ๋งˆ๋‹ค) ์— cbFunc ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰

ํ‘œ 4-1) ์ฝ”๋“œ ์‹คํ–‰ ๋ฐฉ์‹๊ณผ ์ œ์–ด๊ถŒ

codeํ˜ธ์ถœ ์ฃผ์ฒด์ œ์–ด๊ถŒ
cbFunc();์‚ฌ์šฉ์ž์‚ฌ์šฉ์ž
setInterval(cbFunc, 300);setIntervalsetInterval

โ‡’ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ œ์–ด๊ถŒ์„ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ์‹œ์ ์— ๋Œ€ํ•œ ์ œ์–ด๊ถŒ์„ ๊ฐ€์ง

์ธ์ž

Array์˜ prototype์— ๋‹ด๊ธด map ๋ฉ”์„œ๋“œ์˜ ๊ตฌ์กฐ

Array.prototype.map(callback[, thisArg])
callback: function(currentValue, index, array)
  • map ๋ฉ”์„œ๋“œ
    • ์ฒซ ๋ฒˆ์งธ ์ธ์ž: callback ํ•จ์ˆ˜๋ฅผ ๋ฐ›๊ณ 
    • ๋‘ ๋ฒˆ์งธ ์ธ์ž(์ƒ๋žต ๊ฐ€๋Šฅ): ์ฝœ๋ฐฑํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this๋กœ ์ธ์‹ํ•  ๋Œ€์ƒ์„ ํŠน์ •
    • thisArg ๋ฅผ ์ƒ๋žตํ•  ๊ฒฝ์šฐ, ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜๊ณผ ๊ฐ™์ด ์ „์—ญ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค.

โ‡’ map ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์š”์†Œ๋“ค์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์–ด ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜๋ณต ํ˜ธ์ถœํ•˜๊ณ , ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋“ค์„ ๋ชจ์•„ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑ

  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜
    • ์ฒซ ๋ฒˆ์งธ ์ธ์ž: ๋ฐฐ์—ด์˜ ์š”์†Œ ์ค‘ ํ˜„์žฌ์˜ ๊ฐ’
    • ๋‘ ๋ฒˆ์งธ ์ธ์ž: ํ˜„์žฌ๊ฐ’์˜ ์ธ๋ฑ์Šค
    • ์„ธ ๋ฒˆ์งธ ์ธ์ž: map ๋ฉ”์„œ๋“œ์˜ ๋Œ€์ƒ์ด ๋˜๋Š” ๋ฐฐ์—ด ์ž์ฒด

์˜ˆ์ œ 4-3) Array.prototype.map

var newArr = [10, 20, 30].map(function (currentValue, index) {
  console.log(currentValue, index);
  return currentValue + 5;
});

console.log(newArr);

// ์‹คํ–‰ ๊ฒฐ๊ณผ
// 10 0
// 20 1
// 30 2
// [15, 25, 35]

์˜ˆ์ œ 4-4) Array.prototype.map - ์ธ์ž์˜ ์ˆœ์„œ๋ฅผ ์ž„์˜๋กœ ๋ฐ”๊พธ์–ด ์‚ฌ์šฉ

var newArr = [10, 20, 30].map(function (index, currentValue) {
  console.log(index, currentValue);
  return currentValue + 5;
});

console.log(newArr);

// ์‹คํ–‰ ๊ฒฐ๊ณผ
// 10 0
// 20 1
// 30 2
// [5, 6, 7]
  • index, currentValue : ์‚ฌ์šฉ์ž๊ฐ€ ์ž„์˜๋กœ ๋ช…๋ช…
  • ์ปดํ“จํ„ฐ๋Š” ์ฒซ ๋ฒˆ์งธ, ๋‘ ๋ฒˆ์งธ์˜ ์ˆœ์„œ์— ์˜ํ•ด์„œ๋งŒ ๊ฐ๊ฐ์„ ๊ตฌ๋ถ„ํ•˜๊ณ  ์ธ์‹
  • currentValue๋ผ๊ณ  ๋ช…๋ช…ํ•œ ์ธ์ž์˜ ์œ„์น˜๊ฐ€ ๋‘ ๋ฒˆ์งธ๋ผ์„œ ์ปดํ“จํ„ฐ๊ฐ€ ์—ฌ๊ธฐ์— ์ธ๋ฑ์Šค ๊ฐ’์„ ๋ถ€์—ฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ˆ์ œ 4-3๊ณผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ด
  • map ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์›ํ•˜๋Š” ๋ฐฐ์—ด์„ ์–ป์œผ๋ ค๋ฉด map ๋ฉ”์„œ๋“œ์— ์ •์˜๋œ ๊ทœ์น™์— ๋”ฐ๋ผ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.
  • map ๋ฉ”์„œ๋“œ์— ์ •์˜๋œ ๊ทœ์น™์—๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜์–ด์˜ฌ ๊ฐ’๋“ค ๋ฐ ๊ทธ ์ˆœ์„œ๋„ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.
  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฃผ์ฒด : map ๋ฉ”์„œ๋“œ
    • map ๋ฉ”์„œ๋“œ๊ฐ€ ์ด๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ธ์ž์— ์–ด๋–ค ๊ฐ’๋“ค์„ ์–ด๋–ค ์ˆœ์„œ๋กœ ๋„˜๊ธธ ๊ฒƒ์ธ์ง€๊ฒŒ ์ „์ ์œผ๋กœ map ๋ฉ”์„œ๋“œ์—๊ฒŒ ๋‹ฌ๋ฆผ

โ‡’ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ œ์–ด๊ถŒ์„ ๋„˜๊ฒจ๋ฐ›์€ ์ฝ”๋“œ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ธ์ž์— ์–ด๋–ค ๊ฐ’๋“ค์„ ์–ด๋–ค ์ˆœ์„œ๋กœ ๋„˜๊ธธ ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ์ œ์–ด๊ถŒ์„ ๊ฐ€์ง„๋‹ค.

this

์˜ˆ์ œ 4-6) ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this

// (1) setTimeout
setTimeout(function () { console.log(this); }, 300); // Window{ ... }

// (2) forEach
[1, 2, 3, 4, 5].forEach(function (x) { 
  console.log(this); // Window{ ... }
});

// (3) addEventListener
document.body.innerHTML += '<button id="a">Click</button>';
document.body.querySelector('#a').addEventListener('Click', function (e) {
    console.log(this, e);  // <button id="a">Click</button> MouseEvent { isTrusted: true, ... }
  }
);
  • setTimeout ํ•จ์ˆ˜๋Š” 0.3์ดˆ ๋งŒํผ ์‹œ๊ฐ„ ์ง€์—ฐ์„ ํ•œ ๋’ค ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰, 0.3์ดˆ ๋’ค ์ „์—ญ๊ฐ์ฒด๊ฐ€ ์ถœ๋ ฅ
    โ‡’ setTimeout์€ ๋‚ด๋ถ€์—์„œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, call ๋ฉ”์„œ๋“œ์˜ ์ฒซ ๋ฒˆ์žฌ ์ธ์ž์— ์ „์—ญ๊ฐ์ฒด๋ฅผ ๋„˜๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this๊ฐ€ ์ „์—ญ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

  • forEach ๋ฉ”์„œ๋“œ๋Š” ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋ฅผ ์•ž์—์„œ๋ถ€ํ„ฐ ์ฐจ๋ก€๋กœ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์–ด ๊ทธ ๊ฐ’์„ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ์‚ผ์•„ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰, ์ „์—ญ๊ฐ์ฒด์™€ ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๊ฐ€ ์ด 5ํšŒ ์ถœ๋ ฅ
    โ‡’ ์—ฌ๊ธฐ์—์„œ forEach๋Š” 4-2-5์ ˆ์˜ '๋ณ„๋„์˜ ์ธ์ž๋กœ this๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ'์— ํ•ด๋‹นํ•˜์ง€๋งŒ ๋ณ„๋„์˜ ์ธ์ž๋กœ this๋ฅผ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ „์—ญ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

  • addEventListener๋Š” ์ง€์ •ํ•œ HTML ์—˜๋ฆฌ๋จผํŠธ์— 'click' ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๊ทธ ์ด๋ฒคํŠธ ์ •๋ณด๋ฅผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ์‚ผ์•„ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰, ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์•ž์„œ ์ง€์ •ํ•œ ์—˜๋ฆฌ๋จผํŠธ์™€ ํด๋ฆญ ์ด๋ฒคํŠธ์— ๊ด€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด ์ถœ๋ ฅ
    โ‡’ addEventListener๋Š” ๋‚ด๋ถ€์—์„œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ call ๋ฉ”์„œ๋“œ์˜ ์ฒซ ๋ฒˆ์žฌ ์ธ์ž์— addEventListener ๋ฉ”์„œ๋“œ์˜ this๋ฅผ ๊ทธ๋Œ€๋กœ ๋„˜๊ธฐ๋„๋ก ์ •์˜๋ผ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this๊ฐ€ addEventListener๋ฅผ ํ˜ธ์ถœํ•œ ์ฃผ์ฒด์ธ HTML ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ค.

  • setTimeout ํ•จ์ˆ˜์™€ forEach ๋ฉ”์„œ๋“œ๋Š” ๊ทธ ๋‚ด๋ถ€์—์„œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๋Œ€์ƒ์ด ๋  this๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this๋Š” ์ „์—ญ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ

  • addEventListener ๋ฉ”์„œ๋“œ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ž์‹ ์˜ this๋ฅผ ์ƒ์†ํ•˜๋„๋ก ์ •์˜
    โ‡’ ๋ฉ”์„œ๋“œ๋ช…์˜ ์ (.) ์•ž๋ถ€๋ถ„์ด this๊ฐ€ ๋œ๋‹ค.

์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜๋‹ค

  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์–ด๋–ค ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ „๋‹ฌํ•˜๋”๋ผ๋„ ๊ทธ ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜๋กœ์„œ ํ˜ธ์ถœ๋œ๋‹ค.

์˜ˆ์ œ 4-7) ๋ฉ”์„œ๋“œ๋ฅผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ๊ฒฝ์šฐ

var obj = {
  vals: [1, 2, 3],
  // obj ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋กœ ์ •์˜๋œ logValues
  logValues: function(v, i) {
    console.log(this, v, i);
  }
};

// this๋Š” obj๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ , ์ธ์ž๋กœ ๋„˜์–ด์˜จ 1, 2๊ฐ€ ์ถœ๋ ฅ
obj.logValues(1, 2); // {vals: Array(3), logValues: ฦ’} 1 2

// logValues ๋ฉ”์„œ๋“œ๋ฅผ forEach ํ•จ์ˆ˜์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ์„œ ์ „๋‹ฌ
// obj๋ฅผ this๋กœ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ,
// obj.logValues๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ•จ์ˆ˜๋งŒ ์ „๋‹ฌ, obj์™€ ์ง์ ‘์ ์ธ ์—ฐ๊ด€์ด ์—†์–ด์ง
// ๋ณ„๋„๋กœ this๋ฅผ ์ง€์ •ํ•˜๋Š” ์ธ์ž๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this๋Š” ์ „์—ญ๊ฐ์ฒด๋ฅผ ๋ฐ”๋ผ๋ณด๊ฒŒ ๋œ๋‹ค.
[4, 5, 6].forEach(obj.logValues); 
// Window { ... } 4 0
// Window { ... } 5 1
// Window { ... } 6 2

โ‡’ ์–ด๋–ค ํ•จ์ˆ˜์˜ ์ธ์ž์— ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ „๋‹ฌํ•˜๋”๋ผ๋„ ์ด๋Š” ๊ฒฐ๊ตญ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜์ด๋‹ค.

์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์— ๋‹ค๋ฅธ ๊ฐ’ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ

  • ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ this๋กœ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.
    ๊ทธ๋Ÿผ์—๋„ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this๊ฐ€ ๊ฐ์ฒด๋ฅผ ๋ฐ”๋ผ๋ณด๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?
  • this๋ฅผ ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ๋‹ด์•„, ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ํ™œ์šฉํ•  ํ•จ์ˆ˜์—์„œ this ๋Œ€์‹  ๊ทธ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉ
    โ‡’ ์ „ํ†ต์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹
    โ‡’ ์ด๋ฅผ ํด๋กœ์ €๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ

์˜ˆ์ œ 4-8) ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์— ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฐฉ๋ฒ• - ์ „ํ†ต์ ์ธ ๋ฐฉ์‹

var obj1 = {
  name: 'obj1',
  func: function () {
    // func ๋‚ด๋ถ€์—์„œ self ๋ณ€์ˆ˜์— this ๋‹ด๊ณ , ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์„ ์–ธ๊ณผ ๋™์‹œ์— ๋ฐ˜ํ™˜
    var self = this;
    return function () {
      console.log(self.name);
    };
  }
};

var callback = obj1.func();
setTimeout(callback, 1000);
  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ฐ„๊ฒฐํ•˜๊ณ  ์ง๊ด€์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์žฌํ™œ์šฉ ํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.

์˜ˆ์ œ 4-10) ์˜ˆ์ œ 4-8์˜ func ํ•จ์ˆ˜ ์žฌํ™œ์šฉ

...
var obj2 = {
  name: 'obj2',
  func: obj1.func
};

// obj1์˜ func๋ฅผ ๋ณต์‚ฌํ•œ obj2์˜ func๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์•„ ์ฝœ๋ฐฑ์œผ๋กœ ์‚ฌ์šฉ
var callback2 = obj2.func();
setTimeout(callback2, 1500);

var obj3 = { name: 'obj3' };
// obj1์˜ func๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ this๋ฅผ obj3๊ฐ€ ๋˜๋„๋ก ์ง€์ •ํ•ด์„œ ์ฝœ๋ฐฑ์œผ๋กœ ์‚ฌ์šฉ
var callback3 = obj1.func.call(obj3);
setTimeout(callback3, 2000);

์˜ˆ์ œ 4-11) ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์— ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฐฉ๋ฒ• - bind ๋ฉ”์„œ๋“œ ํ™œ์šฉ

var obj1 = {
  name: 'obj1',
  func: function () {
    console.log(this.name);
  }
};

setTimeout(obj1.func.bind(obj1), 1000);

var obj2 = { name: obj1};
setTimeout(obj1.func.bind(obj2), 1500);

์ฝœ๋ฐฑ ์ง€์˜ฅ๊ณผ ๋น„๋™๊ธฐ ์ œ์–ด

์ฝœ๋ฐฑ ์ง€์˜ฅ(callback hell)

  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ต๋ช… ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด ๋ฐ˜๋ณต๋˜์–ด ์ฝ”๋“œ์˜ ๋“ค์—ฌ์“ฐ๊ธฐ ์ˆ˜์ค€์ด ๊ฐ๋‹นํ•˜๊ธฐ ํž˜๋“ค ์ •๋„๋กœ ๊นŠ์–ด์ง€๋Š” ํ˜„์ƒ
  • ์ฃผ๋กœ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋‚˜ ์„œ๋ฒ„ ํ†ต์‹ ๊ณผ ๊ฐ™์ด ๋น„๋™๊ธฐ์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋Ÿฐ ํ˜•ํƒœ๊ฐ€ ์ž์ฃผ ๋“ฑ์žฅ
    โ‡’ ๊ฐ€๋…์„ฑ ๋–จ์–ด์ง€๊ณ  ์ฝ”๋“œ ์ˆ˜์ •์ด ์–ด๋ ค์›Œ์ง
  • ๋™๊ธฐ(synchronous)์ ์ธ ์ฝ”๋“œ : ํ˜„์žฌ ์‹คํ–‰ ์ฃผ์ธ ์ฝ”๋“œ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„์—์•ผ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹
    • CPU์˜ ๊ณ„์‚ฐ์— ์˜ํ•ด ์ฆ‰์‹œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์ฝ”๋“œ
  • ๋น„๋™๊ธฐ(asynchronous)์ ์ธ ์ฝ”๋“œ : ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์ฝ”๋“œ์˜ ์™„๋ฃŒ ์—ฌ๋ถ€์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ฆ‰์‹œ ๋‹ค์Œ ์ฝ”๋“œ๋กœ ๋„˜์–ด๊ฐ
    • ๋ณ„๋„์˜ ์š”์ฒญ, ์‹คํ–‰ ๋Œ€๊ธฐ, ๋ณด๋ฅ˜ ๋“ฑ๊ณผ ๊ด€๋ จ๋œ ์ฝ”๋“œ
    • ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์— ์˜ํ•ด ํŠน์ • ์‹œ๊ฐ„์ด ๊ฒฝ๊ณผ๋˜์ง€ ์ „๊นŒ์ง€ ์–ด๋–ค ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ ๋ณด๋ฅ˜(setTimeout)
    • ์‚ฌ์šฉ์ž์˜ ์ง์ ‘์ ์ธ ๊ฐœ์ž…์ด ์žˆ์„ ๋•Œ ๋น„๋กœ์†Œ ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋Œ€๊ธฐ(addEventListener)
    • ์›น๋ธŒ๋ผ์šฐ์ € ์ž์ฒด๊ฐ€ ์•„๋‹Œ ๋ณ„๋„์˜ ๋Œ€์ƒ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ์š”์ฒญํ•˜๊ณ  ๊ทธ์— ๋Œ€ํ•œ ์‘๋‹ต์ด ์™”์„ ๋•Œ ๋น„๋กœ์†Œ ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋Œ€๊ธฐ(XMLHttpRequest) ๋“ฑ

์˜ˆ์‹œ 4-12) ์ฝœ๋ฐฑ ์ง€์˜ฅ ์˜ˆ์‹œ

setTimeout(function (name) {
  var coffeeList = name;
  console.log(coffeeList);
  
  setTimeout(function (name) {
    coffeeList += ', ' + name;
    console.log(coffeeList);
  
    setTimeout(function (name) {
      coffeeList += ', ' + name;
      console.log(coffeeList);
      
      setTimeout(function (name) {
        coffeeList += ', ' + name;
        console.log(coffeeList);
      }, 500, '์นดํŽ˜๋ชจ์นด');
    }, 500, '์นดํŽ˜๋ผ๋–ผ');
  }, 500, '์•„๋ฉ”๋ฆฌ์นด๋…ธ');
}, 500, '์—์Šคํ”„๋ ˆ์†Œ');
  • ๊ฐ ์ฝœ๋ฐฑ์€ ์ปคํ”ผ ์ด๋ฆ„์„ ์ „๋‹ฌํ•˜๊ณ  ๋ชฉ๋ก์— ์ด๋ฆ„ ์ถ”๊ฐ€
  • ๋ชฉ์  ๋‹ฌ์„ฑ์—๋Š” ์ง€์žฅ์ด ์—†์œผ๋‚˜ ๋“ค์—ฌ์“ฐ๊ธฐ์˜ ์ˆ˜์ค€์ด ๊นŠ์–ด์กŒ๊ณ , ๊ฐ’์ด ์ „๋‹ฌ๋˜๋Š” ์ˆœ์„œ๊ฐ€ '์•„๋ž˜์—์„œ ์œ„๋กœ' ํ–ฅํ•˜๊ณ  ์žˆ๋‹ค.
  • ์ฝœ๋ฐฑ ์ง€์˜ฅ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•
    • ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜
    • Promise
    • Generator
    • Promise + Async/await

์ฝœ๋ฐฑ ์ง€์˜ฅ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• - ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜

์˜ˆ์‹œ 4-13) ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜

var coffeeList = '';

var addEspresso = function (name) {
  coffeeList = name;
  console.log(coffeeList);
  setTimeout(addAmericano, 500, '์•„๋ฉ”๋ฆฌ์นด๋…ธ');
};

var addAmericano = function (name) {
  coffeeList += ', ' + name;
  console.log(coffeeList);
  setTimeout(addLatte, 500, '์นดํŽ˜๋ผ๋–ผ');
};

var addLatte = function (name) {
  coffeeList += ', ' + name;
  console.log(coffeeList);
  setTimeout(addMocha, 500, '์นดํŽ˜๋ชจ์นด');
};

var addMocha = function (name) {
  coffeeList += ', ' + name;
  console.log(coffeeList);
};

setTimeout(addEspresso, 500, '์—์Šคํ”„๋ ˆ์†Œ');
  • ๊ฐ€๋…์„ฑ์ด ๋†’์•„์กŒ๋‹ค.
  • ํ•จ์ˆ˜ ์„ ์–ธ๊ณผ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋งŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์œ„์—์„œ ์•„๋ž˜๋กœ ์ˆœ์„œ๋Œ€๋กœ ์ฝ๋Š”๋ฐ ์–ด๋ ค์›€์ด ์—†๋‹ค.
  • ๋ณ€์ˆ˜๋ฅผ ์ตœ์ƒ๋‹จ์œผ๋กœ ๋Œ์–ด์˜ฌ๋ ค ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๊ฒŒ ๋์ง€๋งŒ ์ „์ฒด๋ฅผ ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜ ๋“ฑ์œผ๋กœ ๊ฐ์‹ธ๋ฉด ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

โ‡’ ์ผํšŒ์„ฑ ํ•จ์ˆ˜๋ฅผ ์ „๋ถ€ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ, ์ฝ”๋“œ๋ช…์„ ์ผ์ผ์ด ๋”ฐ๋ผ๋‹ค๋…€์•ผ ํ•˜๋ฏ€๋กœ ์˜คํžˆ๋ ค ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

์ฝœ๋ฐฑ ์ง€์˜ฅ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• - Promise

new Promise(function (resolve) {
  setTimeout(function () {
    var name = '์—์Šคํ”„๋ ˆ์†Œ';
    console.log(name);
    resolve(name);
  }, 500)
}).then(function (prevName) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      var name = prevName + ', ์•„๋ฉ”๋ฆฌ์นด๋…ธ';
      console.log(name);
      resolve(name);
    }, 500)
  })
}).then(function (prevName) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      var name = prevName + ', ์นดํŽ˜๋ผ๋–ผ';
      console.log(name);
      resolve(name);
    }, 500)
  })
}).then(function (prevName) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      var name = prevName + ', ์นดํŽ˜๋ชจ์นด';
      console.log(name);
      resolve(name);
    }, 500)
  });
});

// ์œ„์˜ ์ฝ”๋“œ์—์„œ ๋ฐ˜๋ณต์ ์ธ ๋‚ด์šฉ์„ ํ•จ์ˆ˜ํ™”ํ•ด์„œ ์งง๊ฒŒ ํ‘œํ˜„
var addCoffee = function (name) {
  return function (prevName) {
    return new Promise(function (resolve) {
      setTimeout(function () {
        var newName = prevName ? (prevName + ', ' + name) : name;
        console.log(newName);
        resolve(newName);
      }, 500);
    });
  };
};

addCoffee('์—์Šคํ”„๋ ˆ์†Œ')()
  .then(addCoffee('์•„๋ฉ”๋ฆฌ์นด๋…ธ'))
  .then(addCoffee('์นดํŽ˜๋ผ๋–ผ'))
  .then(addCoffee('์นดํŽ˜๋ชจ์นด'));
  • new ์—ฐ์‚ฐ์ž๋กœ Promise ํ˜ธ์ถœ
  • Promise์˜ ์ธ์ž๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ํ˜ธ์ถœํ•  ๋•Œ ๋ฐ”๋กœ ์‹คํ–‰๋˜์ง€๋งŒ
  • ๋‚ด๋ถ€์— resolve/reject ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ตฌ๋ถ„์ด ์žˆ์„ ๊ฒฝ์šฐ ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋‹ค์Œ(then)/์˜ค๋ฅ˜ ๊ตฌ๋ฌธ(catch)์œผ๋กœ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋Š”๋‹ค.

โ‡’ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ resolve/reject๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๋™๊ธฐ์  ํ‘œํ˜„์ด ๊ฐ€๋Šฅ

์ฝœ๋ฐฑ ์ง€์˜ฅ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• - Generator

var addcoffee = function (prevName, name) {
  setTimeout(function () {
    coffeeMaker.next(prevName ? prevName + ', ' + name: name);
  }, 500);
};

var coffeeGenerator = function* () {
  var espresso = yield addCoffee('', '์—์Šคํ”„๋ ˆ์†Œ');
  console.log(espresso);
  var americano = yield addCoffee(espresso, '์•„๋ฉ”๋ฆฌ์นด๋…ธ');
  console.log(americano);
  var latte = yield addCoffee(americano, '์นดํŽ˜๋ผ๋–ผ');
  console.log(latte);
  var mocha = yield addCoffee(mocha, '์นดํŽ˜๋ชจ์นด');
  console.log(mocha);
};

var coffeeMaker = coffeeGenerater();
coffeeMaker.next()
  • *๊ฐ€ ๋ถ™์€ ํ•จ์ˆ˜ : Generator ํ•จ์ˆ˜
  • Generator ํ•จ์ˆ˜ ์‹คํ–‰ํ•˜๋ฉด, Iterator ๋ฅผ ๋ฐ˜ํ™˜
  • Iterator : next ๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
    • next ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
    • Generator ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๊ฐ€์žฅ ๋จผ์ € ๋“ฑ์žฅ ํ•˜๋Š” yield์—์„œ ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ ๋ฉˆ์ถค
    • ๋‹ค์‹œ next ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
    • ์•ž์„œ ๋ฉˆ์ท„๋˜ ๋ถ€๋ถ„๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๊ทธ ๋‹ค์Œ์— ๋“ฑ์žฅ ํ•˜๋Š” yield์—์„œ ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ ๋ฉˆ์ถค

โ‡’ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋Š” ์‹œ์ ๋งˆ๋‹ค next ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด Generator ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์†Œ์Šค๊ฐ€ ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ์ง„ํ–‰๋จ

์ฝœ๋ฐฑ ์ง€์˜ฅ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• - Promise + Async/await

var addCoffee = function (name) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(name);
    }, 500)
  });
};

var coffeeMaker = async function () {
  var coffeeList = '';
  var _addCoffee = async function (name) {
    coffeeList += (coffeeList ? ',' : '') + await addCoffee(name);
  };
  await _addCoffee('์—์Šคํ”„๋ ˆ์†Œ');
  console.log(CoffeeList);
  await _addCoffee('์•„๋ฉ”๋ฆฌ์นด๋…ธ');
  console.log(CoffeeList);
  await _addCoffee('์นดํŽ˜๋ผ๋–ผ');
  console.log(CoffeeList);
  await _addCoffee('์นดํŽ˜๋ชจ์นด');
  console.log(CoffeeList);
  • ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ ์ž ํ•˜๋Š” ํ•จ์ˆ˜ ์•ž์— async๋ฅผ ํ‘œ๊ธฐ
  • ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์‹ค์งˆ์ ์ธ ๋น„๋™๊ธฐ ์ž‘์—…์ด ํ•„์š”ํ•œ ์œ„์น˜๋งˆ๋‹ค await๋ฅผ ํ‘œ๊ธฐํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋’ค์˜ ๋‚ด์šฉ์ผ Promise๋กœ ์ž๋™ ์ „ํ™˜
  • ํ•ด๋‹น ๋‚ด์šฉ์ด resolve๋œ ์ดํ›„์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ง„ํ–‰ ํ•˜๋ฏ€๋กœ Primise์˜ then๊ณผ ๋น„์Šทํ•œ ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

์ฐธ๊ณ 

  • ์ฝ”์–ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ - 04 ์ฝœ๋ฐฑ ํ•จ์ˆ˜

๋งˆ๋ฌด๋ฆฌ

  • ์Šคํ„ฐ๋””์—์„œ '์ฝ”์–ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ' ์ฑ…์„ 1ํšŒ๋… ํ•˜๊ธฐ๋กœ ํ•˜๊ณ  ๊ฐ์ž ํ•œ ์ฑ•ํ„ฐ์”ฉ ๋ฐœํ‘œํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.
    โ‡’ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‹น์ฒจ ๐ŸŽ‰
  • ์ด ์ „์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ๋ฐฐ์› ์ง€๋งŒ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ๋ถ€๋ถ„์ด ๋งŽ์•˜๋Š”๋ฐ ์ด๋ฒˆ์— ๋ฐœํ‘œ ์ค€๋น„ํ•˜๋ฉด์„œ ๋‹ค์‹œ ๊ณต๋ถ€ํ•œ ๋•์— ์กฐ๊ธˆ ๋” ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.
    โ‡’ ์ด ๋‚ด์šฉ๋งŒ ๋ณด๊ณ  ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ๊ฒƒ์ธ์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‚˜๋ฆ„ ์—ด์‹ฌํžˆ ์ž‘์„ฑํ•ด๋ณด์•˜๋‹ค
    โ‡’ ์‹ค์€ ์ฑ… ์ž์ฒด์— ์„ค๋ช…์ด ์ž˜ ๋˜์–ด ์žˆ์—ˆ๋‹ค! ํ—ฟ
  • ๋‹ค๋ฅธ ์ฑ•ํ„ฐ๋Š” ๋‚ด๊ฐ€ ๋ฐœํ‘œํ•˜๋Š” ๋ถ€๋ถ„์ด ์•„๋‹ˆ์ง€๋งŒ ๋ธ”๋กœ๊ทธ์— ๊ธ€ ์ž‘์„ฑํ•ด์„œ ์˜ฌ๋ ค์•ผ์ง€~

4๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2022๋…„ 3์›” 19์ผ

์—ฌ๊ธฐ๊ฐ€ ๊ทธ ์†Œ๋ฌธ๋‚œ ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ชฝ์ง‘๊ฒŒ ๊ฐ•์˜ํ•ด์ฃผ๋Š” ๊ณณ์ธ๊ฐ€์š”~??

2๊ฐœ์˜ ๋‹ต๊ธ€