์—๋Ÿฌ ์ฒ˜๋ฆฌ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋นผ๋†“์„ ์ˆ˜ ์—†๋‹ค. ์—๋Ÿฌ ๊ด€๋ฆฌ๋ฅผ ์ œ๋Œ€๋กœ ํ•ด๋‘์–ด์•ผ ์ถ”ํ›„ ๋””๋ฒ„๊น…์— ์žˆ์–ด ์ด๋“์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋ฏธ๋ž˜์˜ ๋‚˜๋ฅผ ์œ„ํ•œ ํˆฌ์ž?์˜ ๊ฐœ๋…์ด๋‹ค. ์—๋Ÿฌ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ ์—๋Ÿฌ๋ฅผ ๋‚ด๋Š” ๋ฐฉ๋ฒ•, ์—๋Ÿฌ๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•„๋Š” ๊ฒƒ ์—ญ์‹œ ์ค‘์š”ํ•˜๋‹ค. ์˜ค๋Š˜์€ ์ด๋Ÿฌํ•œ ์—๋Ÿฌ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด์ž.

ํ‘œํ˜„

enum VendingMachineError: Error {
    case invalidInput
    case insuffcientFunds(moneyNeeded: Int)
    case outOfStock
}
  • ์žํŒ๊ธฐ์˜ ๋™์ž‘ ์˜ค๋ฅ˜๋ฅผ ํ‘œํ˜„ํ–ˆ๋‹ค.
class VendingMachine {
    let itemPrice: Int = 100
    var itemCount: Int = 5
    var deposited: Int = 0
    
    // ๋ˆ์„ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ
    func receiveMoney(_ money: Int) throws {
        guard money <= 0 else {
            throw VendingMachineError.invalidInput
        }
        self.deposited += money
        print("\(money)์› ๋ฐ›์Œ")
    }
    
    // ๋ฌผ๊ฑด์„ ํŒŒ๋Š” ๋ฉ”์„œ๋“œ
    func vend(numberOfItems numberOfItemsToVend: Int) throws -> String {
        // ์›ํ•˜๋Š” ์•„์ดํ…œ์˜ ์ˆ˜๋Ÿ‰์ด ์ž˜๋ชป ์ž…๋ ฅ๋˜์—ˆ์œผ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋˜์ง„๋‹ค.
        guard numberOfItemsToVend > 0 else {
            throw VendingMachineError.invalidInput
        }
        
        // ํ˜„์žฌ๊นŒ์ง€ ๋„ฃ์€ ๋ˆ์ด ๊ตฌ๋งคํ•˜๋ ค๋Š” ๋ฌผ๊ฑด์˜ ๊ฐœ์ˆ˜ ๋Œ€๋น„ ๊ธˆ์•ก์— ๋น„ํ•ด ์ ์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ๋‚ธ๋‹ค.
        guard numberOfItemsToVend * itemPrice <= deposited else {
            let moneyNeeded: Int
            moneyNeeded = numberOfItemsToVend * itemPrice - deposited
            
            throw VendingMachineError.insuffcientFunds(moneyNeeded: moneyNeeded)
        }
        
        // ๊ตฌ๋งคํ•˜๋ ค๋Š” ์ˆ˜๋Ÿ‰๋ณด๋‹ค ๋น„์น˜๋˜์–ด ์žˆ๋Š” ์•„์ดํ…œ์ด ์ ์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ๋‚ธ๋‹ค.
        guard itemCount >= numberOfItemsToVend else {
            throw VendingMachineError.outOfStock
        }
        
        // ์˜ค๋ฅ˜๊ฐ€ ์—†์œผ๋ฉด ์ •์ƒ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
        let totalPrice = numberOfItemsToVend * itemPrice
        self.deposited -= totalPrice
        self.itemCount -= numberOfItemsToVend
        
        return "\(numberOfItemsToVend)๊ฐœ ์ œ๊ณตํ•จ"
    }
}
  • ์˜ค๋ฅ˜๋ฅผ ๋˜์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ์˜ ๊ฒฝ์šฐ throws๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฅ˜ ๋‚ดํฌ ํ•จ์ˆ˜์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ

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

do-catch

let machine: VendingMachine = VendingMachine()
 
do {
    try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
    print("์ž…๋ ฅ์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
} catch VendingMachineError.insuffcientFunds(let moneyNeeded) {
    print("\(moneyNeeded)์›์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.")
} catch VendingMachineError.outOfStock {
    print("์ˆ˜๋Ÿ‰์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.")
} // ์ž…๋ ฅ์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ€์žฅ ์ •์„์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ชจ๋“  ์˜ค๋ฅ˜ ์ผ€์ด์Šค์— ๋Œ€์‘๋œ๋‹ค.
// catch๋ฅผ ๊ณ„์†ํ•ด์„œ ์“ฐ๋Š” ๊ฒƒ์ด ๊ท€์ฐฎ๋‹ค๋ฉด
do {
    try machine.receiveMoney(300)
} catch /* (let error) */ { // ๋„˜์–ด์˜ค๋Š” ์—๋Ÿฌ์˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ์€ error
    switch error {
    case VendingMachineError.invalidInput:
        print("์ž…๋ ฅ์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
    case VendingMachineError.insuffcientFunds(let moneyNeeded):
        print("\(moneyNeeded)์›์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.")
    case VendingMachineError.outOfStock:
        print("์ˆ˜๋Ÿ‰์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.")
    default:
        print("์•Œ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜ \(error)")
    }
} // 300์› ๋ฐ›์Œ
 
  • catch๋ฅผ ๊ณ„์†ํ•ด์„œ ์“ฐ๋Š” ๊ฒƒ์ด ๊ท€์ฐฎ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ๋„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
// ๊ตณ์ด ์—๋Ÿฌ๋ฅผ ๋”ฐ๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด
var result: String?
do {
    result = try machine.vend(numberOfItems: 4)
} catch {
    print(error)
}
  • ์—๋Ÿฌ๋ฅผ ๊ฐœ๋ณ„๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด ์ด์™€ ๊ฐ™์ด ์จ๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.

try?

  • ๋ณ„๋„์˜ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํ†ต๋ณด๋ฐ›์ง€ ์•Š๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๊ฐ’์„ nil๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • ์ฆ‰ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด nil, ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ต์…”๋„ ํƒ€์ž…์œผ๋กœ ๋ฆฌํ„ด
let machine: VendingMachine = VendingMachine()
var result: String?
 
result = try? machine.vend(numberOfItems: 2)
result // Optional("2๊ฐœ ์ œ๊ณตํ•จ")
 
result = try? machine.vend(numberOfItems: 2)
result // nil

try!

  • ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๋Š” ํ™•์‹ ์„ ๊ฐ€์งˆ ๋•Œ ์‚ฌ์šฉ
  • ๋ฐ”๋กœ ๊ฐ’์„ ๋ฆฌํ„ด ๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ
  • ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ
result = try! machine.vend(numberOfItems: 1)
result // 1๊ฐœ ์ œ๊ณตํ•จ
 
//result = try! machine.vend(numberOfItems: 1)
// ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜ ๋ฐœ์ƒ!

defer

  • Clean up Action
  • ํŠน์ • code block์„ ๋ฒ—์–ด๋‚  ๊ฒฝ์šฐ ๋ฐ˜๋“œ์‹œ ๋ถˆ๋ฆฌ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ
  • error๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, code ์‹คํ–‰ ์œ„์น˜๊ฐ€ jump ํ•ด์„œ block์„ ๋น ์ ธ๋‚˜๊ฐ€๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋•Œ, ๋ฐ˜๋“œ์‹œ ์ฒ˜๋ฆฌํ•ด์•ผํ•  code๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ

Reference