에러 처리는 프로그래밍에서 빼놓을 수 없다. 에러 관리를 제대로 해두어야 추후 디버깅에 있어 이득을 볼 수 있다. 미래의 나를 위한 투자?의 개념이다. 에러를 관리하는 것도 중요하지만 에러를 내는 방법, 에러를 감지하여 처리하는 방법을 아는 것 역시 중요하다. 오늘은 이러한 에러에 대해 알아보고 관리하는 방법을 배워보자.
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
를 사용하여 호출한다.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원 받음
// 굳이 에러를 따로 처리할 필요가 없다면
var result: String?
do {
result = try machine.vend(numberOfItems: 4)
} catch {
print(error)
}
let machine: VendingMachine = VendingMachine()
var result: String?
result = try? machine.vend(numberOfItems: 2)
result // Optional("2개 제공함")
result = try? machine.vend(numberOfItems: 2)
result // nil
result = try! machine.vend(numberOfItems: 1)
result // 1개 제공함
//result = try! machine.vend(numberOfItems: 1)
// 런타임 오류 발생!