Callback Pattern

Javascript Patterns(2011)

Javascript

2017-11-15


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋”ฉ ๊ธฐ๋ฒ•๊ณผ ํ•ต์‹ฌ ํŒจํ„ด(2011) ์ฑ…์„ ์ฝ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

๐Ÿ‘‰ 3์žฅ - Literals and Constructors


1. ์ฝœ๋ฐฑ์ด๋ž€?

ํ•จ์ˆ˜๋Š” ์ผ๊ธ‰ ๊ฐ์ฒด๋‹ค. ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋‹ค๋ฅธ ํ•จ์ˆ˜์— ์ธ์ž๋กœ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ธ์ž๊ฐ€ ๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ฝœ๋ฐฑํ•จ์ˆ˜, ๋˜๋Š” ์ฝœ๋ฐฑ ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ํ•จ์ˆ˜๋ฅผ ์ผ๋‹จ ๋“ฑ๋กํ•˜๊ณ , ํŠน์ • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์‹œ์ ์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ๋˜๋Š” ํŠน์ • ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜๊ฒจ์„œ ์ฝ”๋“œ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜๋„ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ผ๊ณ  ํ•œ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ event handler์ด๋‹ค. - ์ธ์‚ฌ์ด๋“œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ(2016)

function writeCode(callback) {
    // ...
    callback()
    // ...
}

function introduceBugs() {
    // ...
}

writeCode(introduceBugs)
  • ํ•จ์ˆ˜์˜ ()๋ฅผ ๋ถ™์ด๋ฉด ์ฆ‰์‹œ ์‹คํ–‰, ๋ถ™์ด์ง€ ์•Š์œผ๋ฉด ์ฐธ์กฐ๋งŒ ํ•˜๊ณ , ๋ฐ”๊นฅ ํ•จ์ˆ˜์—์„œ ์•Œ๋งž์€ ๋•Œ์— ์‹คํ–‰ํ•ด์ค€๋‹ค.

2. ์ฝœ๋ฐฑ ์˜ˆ์ œ

// ์ฝœ๋ฐฑ ์—†์ด ์‚ฌ์šฉ
// array์ธ nodes๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜์—์„œ nodes๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
let findNodes = function() {
    const i = 100000,
            nodes = [],
            found
    while (i) {
        // ๋…ธ๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋กœ์ง - ๋”ฐ๋กœ ๋‘”๋‹ค.
        nodes.push(found)
    }
    return nodes    // nodes ๋ฆฌํ„ด
}

let hide = function(nodes) {    // nodes๋ฅผ ์ธ์ž๋กœ ๋ฐ›์Œ
    let i = 0,
    max = nodes.length
    for (i < max; i += 1) {
        nodes[i].style.display = 'none'
    }
}

// ํ•จ์ˆ˜ ์‹คํ–‰
hide(findNodes())
//  ์ฝœ๋ฐฑ์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง
let findNodes = function (callback) {
    const i = 100000,
    nodes = [],
    found

    if (typeof callback !== "function") {
        callback = false
    }

    while (i) {
        i -= 1
        // ๋…ธ๋“œ ์ˆ˜์ • ๋กœ์ง

        if (callback) {
            callback(found)
        }

        nodes.push(found)
    }
    return nodes
}

// ์ฝœ๋ฐฑ ํ•จ์ˆ˜
let hide = function(node) {
    node.style.display = 'none'
}
findNodes(hide)
// hide()๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ณ  ์ด๋ ‡๊ฒŒ ์ต๋ช…ํ•จ์ˆ˜๋กœ ํ‘œํ˜„ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
findNodes(function(node) {
    node.style.display = 'none'
})

3. ์ฝœ๋ฐฑ๊ณผ ์œ ํšจ๋ฒ”์œ„

๋งŒ์•ฝ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ์ธ ๊ฒฝ์šฐ, ์ฝœ๋ฐฑ์ด ์†ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” this๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค.

let myapp = {}
myapp.color = 'green'
myapp.paint = function(node) {
    node.style.color = this.color
}

findNodes(myapp.paint)  // ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ฝœ๋ฐฑํ•จ์ˆ˜๋กœ ๊ฐ€์ง„๋‹ค. myapp.paint ๋‚ด this๋Š” findNodes์—์„œ ๋ฐ”๋ผ๋ณด๋Š” ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๊ฒƒ์ด๋‹ค.
  1. ์ด๋Ÿด ๊ฒฝ์šฐ, ์•„๋ž˜์ฒ˜๋Ÿผ ์ฝœ๋ฐฑ์ด ์†ํ•ด์žˆ๋Š” ๊ฐ์ฒด๋„ ์ธ์ž๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก findNodes()๋ฅผ ์ˆ˜์ •ํ•ด์ค€๋‹ค.
findNodes(myapp.paint, myapp)

let findNodes = function(cbMethod, cbObject) {
    if (typeof cbMethod === "function") {
        cbMethod.call(cbObject, found)
    }
}
  1. ๋ฉ”์„œ๋“œ๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
findNodes("paint", myapp)

let findNodes = function(cbMethod, cbObject) {
    if (typeof cbMethod === "string") {
        cbMethod = cbObject[cbMethod]
    }
    //
    if (typeof cbMethod === "function") {
        cbMethod.call(cbObject, found)
    }
 }

4. ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ

ํŽ˜์ด์ง€ element์— ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค, ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ํ˜ธ์ถœ๋  ์ฝœ๋ฐฑํ•จ์ˆ˜์˜ ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

document.addEventListener("click", console.log, false)

๋Œ€๋ถ€๋ถ„์˜ ํด๋ผ์ด์–ธํŠธ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ event-driven ๋ฐฉ์‹์ด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ event-driven ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์ ํ•ฉํ•œ ์ด์œ ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์ฝœ๋ฐฑ ํŒจํ„ด ๋•๋ถ„์ด๋‹ค.


5. ํƒ€์ž„์•„์›ƒ

setTimeout๊ณผ setInterval๋„ ๋Œ€ํ‘œ์ ์ธ ์ฝœ๋ฐฑ ํŒจํ„ด์ด๋‹ค.

let thePlotThickens = function() {
    console.log('500ms later...');
}
setTimeout(thePlotThickens, 500)

์—ฌ๊ธฐ์„œ thePlotThickens๊ฐ€ ()์—†์ด ์ „๋‹ฌ๋˜์—ˆ๋‹ค. ์ฆ‰์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  500ms๊ฐ€ ์ง€๋‚œ ํ›„์— ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ ๋งŒ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ "thePlotThickens()"์™€ ๊ฐ™์ด ๋ฌธ์ž์—ด์„ ์ „๋‹ฌํ•˜๋Š” ๊ฑด eval()๊ณผ ๊ฐ™์€ ์•ˆํ‹ฐํŒจํ„ด์ด๋‹ค.


6. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ์˜ ์ฝœ๋ฐฑ

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