๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“‹Technical interview(Front)

์ฝœ๋ฐฑ ํ•จ์ˆ˜(Callback)

by ๋…น์ฐจ๋ง›๊ฐœ๊ตฌ๋ฆฌ 2022. 11. 3.
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋น„๋™๊ธฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ callback๊ณผ promise๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.
๋จผ์ € callback ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž

 

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ?

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ž€ ํŠน์ • ์ฝ”๋“œ์˜ ์—ฐ์‚ฐ์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ์ฝ”๋“œ์˜ ์‹คํ–‰์„ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ 

๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์‹คํ–‰ํ•˜๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํŠน์„ฑ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

ํ”„๋กœ์ ํŠธ ์ˆ˜ํ–‰์‹œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.

์ด๋ฅผ ์œ„ํ•ด HTTP ํ†ต์‹ ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋•Œ ๋น„๋™๊ธฐ์ฒ˜๋ฆฌ์˜ ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

 

์•„๋ž˜์˜ ajax ํ†ต์‹  ์‚ฌ๋ก€๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด์ž

function getData() {
	var tableData;
	$.get('https://domain.com/products/1', function(response) {
		tableData = response;
	});
	return tableData;
}

console.log(getData()); // undefined

 

์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์™€ ๊ฐ™์ด 'https://domain.com/products/1' ์— HTTP GET์š”์ฒญ์„ ๋‚ ๋ ค

1๋ฒˆ์งธ ์ƒํ’ˆ(products)์ •๋ณด๋ฅผ ์š”์ฒญํ•˜๋Š” ์ฝ”๋“œ๊ฐ€์žˆ๋‹ค.

 

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋Š” tableData๋ผ๋Š” ๋ณ€์ˆ˜์— ์ €์žฅํ•œ๋‹ค.

์ดํ›„  getData()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ console.log()๋ฅผ ํ†ตํ•ด ์ฐ์–ด๋ณด๋ฉด ๋ฐ์ดํ„ฐ๋Š” ์—†๊ณ  undefined๊ฐ€ ์ฐํžˆ๋Š”๊ฒƒ์„

ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๊ทธ ์ด์œ ๋Š” $.get()๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  ๋ฐ›์•„์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์ฃผ์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ฝ”๋“œ์ธ 

return tableData;๋ฅผ ์‹คํ–‰ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋”ฐ๋ผ์„œ, getData()์˜ ๊ฒฐ๊ณผ ๊ฐ’์€ ์ดˆ๊ธฐ ๊ฐ’์„ ์„ค์ •ํ•˜์ง€ ์•Š์€ tableData์˜ ๊ฐ’ undefined๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํŠน์ • ๋กœ์ง์˜ ์‹คํ–‰์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์ฃผ์ง€ ์•Š๊ณ  ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์ด๋‹ค. 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ๋Š”, ํ™”๋ฉด์—์„œ ์„œ๋ฒ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ–ˆ์„ ๋•Œ
์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‘๋‹ต์ด ๋Œ์•„์˜ฌ ์‹œ๊ฐ„์„ ์ž์„ธํžˆ ์•Œ ์ˆ˜ ์—†๊ธฐ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ํ•˜์ง€ ์•Š๊ณ  ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์—†๊ธฐ๋•Œ๋ฌธ์ด๋‹ค.
์œ„์—์„  ๊ฐ„๋‹จํ•œ ์š”์ฒญ 1๊ฐœ๋งŒ ๋ณด๋ƒˆ์ง€๋งŒ ์š”์ฒญ์ด ๋ฌด์ˆ˜ํžˆ ๋Š˜์–ด๋‚œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด.

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์•„๋‹ˆ๊ณ  ๋™๊ธฐ ์ฒ˜๋ฆฌ๋ผ๋ฉด ์ฝ”๋“œ ์‹คํ–‰ํ•˜๊ณ  ์‘๋‹ต์ด ์˜ฌ๋•Œ๊ฐ€์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ๋ฅผ ๋ฐ˜๋ณตํ•  ๊ฒƒ์ด๋‹ค.

 


 

callback์„ ์‚ฌ์šฉํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์˜ˆ์‹œ #1

์•„๋ž˜๋Š” web API์ธ setTimeout() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์•ˆ์—์žˆ๋Š” callback ํ•จ์ˆ˜๋ฅผ

1์ดˆ๋’ค์— ์‹คํ–‰ํ•˜๊ฒŒ ํ•จ( ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ํ†ต์‹ ์ด 1์ดˆ๋’ค์— ์˜จ ๊ฒƒ์„ ๊ฐ€์ • )์œผ๋กœ์จ

์œ„์—์„œ $.getํ•จ์ˆ˜์™€ ๊ฐ™์ด HTTP ํ†ต์‹ ํ•œ ํšจ๊ณผ๋ฅผ ๋‚ด์—ˆ๋‹ค.

 

setTimeout() - Web API | MDN

์ „์—ญ setTimeout() ๋ฉ”์„œ๋“œ๋Š” ๋งŒ๋ฃŒ๋œ ํ›„ ํ•จ์ˆ˜๋‚˜ ์ง€์ •ํ•œ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์‹คํ–‰ํ•˜๋Š” ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

developer.mozilla.org

function check(callback) {
  setTimeout(() => {
    callback("i'm here!!");
  }, 1000);
}

check(function (msg) {
  console.log(msg);
});

check ํ•จ์ˆ˜๋Š” ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ callback์„ ๋ฐ›๊ณ , callback์ด ์‹คํ–‰ ๋  ๋•Œ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋ฅผ console์— ์ถœ๋ ฅํ•œ๋‹ค.

callback์ด ์‹คํ–‰๋˜๋Š” ์‹œ์ ์€ checkํ•จ์ˆ˜ ์•ˆ์— ์žˆ๋Š” setTimeout์œผ๋กœ ์ธํ•ด์„œ 1์ดˆ ํ›„์— ์‹คํ–‰์ด ๋œ๋‹ค.

callback์ด ์‹คํ–‰์ด ๋˜๋ฉด์„œ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ "i'm here!!"์ด ๋“ค์–ด๊ฐ€๊ณ , ์ฝ˜์†”์— "i'm here!!"์ด ๋‚˜ํƒ€๋‚œ๋‹ค.

 

์ด๋ ‡๊ฒŒ callback์„ ํ†ตํ•ด์„œ ์–ด๋– ํ•œ ๋น„๋™๊ธฐ ๋กœ์ง์ด ๋๋‚ฌ์„ ๋•Œ callback ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ด์œผ๋กœ์จ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ ๋˜์—ˆ์„ ๋•Œ callback์—์„œ ์ž‘์„ฑํ•œ ์–ด๋– ํ•œ ํ–‰๋™์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 


callback์„ ์‚ฌ์šฉํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์˜ˆ์‹œ #2

์•„๋ž˜๋Š” html ํŒŒ์ผ์˜ head ๋ถ€๋ถ„์—

1. script ํƒœ๊ทธ๋ฅผ ๋งŒ๋“ค๊ณ  ( let script = document.createElement('script');

2. script ํƒœ๊ทธ์˜ src ์†์„ฑ์œผ๋กœ path๋ฅผ ์ถ”๊ฐ€ ํ•˜์—ฌ

3. head์— ์ถ”๊ฐ€ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

function loadScript(path) {
  1. let script = document.createElement('script');
  2. script.src = path;
  3. document.head.append(script);
}

4. loadScript('/my/script.js');

newFunction(); // ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค!

4. ์œ„์—์„œ ์ƒ์„ฑํ•œ loadScript ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ( ๋ถˆ๋Ÿฌ์˜จ '/my/script.js' ์—” "function newFunction() {…}"ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฐ€์ •. )

5. loadScript ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ newFunctionํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ–ˆ์ง€๋งŒ ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ ๋ฐœ์ƒ 

 

์—๋Ÿฌ๋Š” ์˜ˆ์‹œ#1์—์„œ ๋ณด์•˜๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์„ ์•Œ์ง€๋ชปํ•˜๋ฉฐ, ์‹œ๊ฐ„์„ ์ถฉ๋ถ„ํžˆ ํ™•๋ณดํ•˜์ง€

๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค. 

 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์ฝœ๋ฐฑํ•จ์ˆ˜๋กœ ํ•ด๊ฒฐํ•œ๋‹ค.

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(script);
  document.head.append(script);
}

loadScript('/my/script.js', function() {
  // ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์Šคํฌ๋ฆฝํŠธ ๋กœ๋“œ๊ฐ€ ๋๋‚˜๋ฉด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  newFunction(); // ์ด์ œ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  ...
});

์ด๋ ‡๊ฒŒ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ํ•จ์ˆ˜(๋Œ€๊ฐœ ์ต๋ช… ํ•จ์ˆ˜, ์˜ˆ์‹œ์—์„œ๋Š” callback์ด๋ผ๋Š” ์ด๋ฆ„์˜ ํ•จ์ˆ˜)๋Š”

์›ํ•˜๋Š” ๋™์ž‘(์œ„ ์˜ˆ์ œ์—์„  ์™ธ๋ถ€ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ )์ด ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

 

์ด๋Ÿฐ ๋ฐฉ์‹์„ ‘์ฝœ๋ฐฑ ๊ธฐ๋ฐ˜(callback-based)’ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
๋ฌด์–ธ๊ฐ€๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜ ๋‚ด ๋™์ž‘์ด ๋ชจ๋‘ ์ฒ˜๋ฆฌ๋œ ํ›„ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐˆ ์ฝœ๋ฐฑ์„
์ธ์ˆ˜๋กœ ๋ฐ˜๋“œ์‹œ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์œ„ ์˜ˆ์‹œ์—์„ 
 loadScript์˜ ์ธ์ˆ˜๋กœ callback์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•ด ์ฃผ์—ˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•œ ๋ฐฉ์‹์€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

๐Ÿ“š์ถœ์ฒ˜


https://ko.javascript.info/callbacks

https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation

 

728x90