swift 기본문법 - 오류처리(error handling)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
인프런, 야곰의 스위프트 기본문법 강좌를 듣고 정리하였습니다.


오류처리(error handling)

Error 프로토콜과 (주로) 열거형을 통해서 오류를 표현한다.

enum 오류종류이름: Error {
  case 종류1
  case 종류2
  case 종류3
  case 종류4
  ...
}

예시는 아래와 같다.

enum VendingMachineError: Error {
  case invalidInput
  case insufficientFunds(moneyNeeded: Int)
  case outOfStock
}

함수에서 발생한 오류 던지기

이러한 오류들은 특정 함수안에서 오류가 발생했다고 (자신을 호출한 곳에) 오류를 던져준다.

오류 발생의 여지가 있는 메서드는 throws를 사용해 오류를 내포하는 함수임을 표시한다.

class VendingMachine {
  let itemPrice: Int = 100
  var itemCount: Int = 5
  var deposited: Int = 0

  // 돈 받기 메서드
  func receiveMoney(_ money: Int) throws {

    // 입력한 돈이 0이하면 오류를 던진다
    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.insufficientFunds(moneyNeeded: money)
    }
  }
}

오류 처리(try, do-catch)

  • 오류발생의 여지가 있는 throws 함수는 try를 사용해 호출해야한다. > try, try?, try!
  • 오류 발생의 여지가 있는 throws 함수는 do-catch 구문을 활용해 오류발생에 대비한다.
do {
  try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
  print("입력이 잘못됐습니다")
} catch VendingMachine.insufficientFunds {
  print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
  print("수량이 부족합니다")
}

반복된 catch가 별로라면 아래처럼 해도 된다.

do {
  try machine.receiveMoney(300)
} catch // let error 는 생략 가능하다
  switch error {
    case VendingMachineError.invalidInput:
      print("입력이 잘못되었습니다")
    case ....
    default:
    print("알수없는 오류 \(error)")
  }
}

그런데 이마저도 귀찮다.

do {
  result = tru machine.vend(numberOfItems: 4)
} catch {
  print(error)
}

혹은 아래로 한다

do {
  result = try machine.vend(numberOfItems: 4)
}

이 깔끔하지 않은 구문을 좀 더 명확히 해주기 위해 try? try!가 있다!

try?

  • 별도의 오류처리 결과를 통보받지 않는다.
  • 오류가 발생했으면 결과값을 nil로 돌려받는다.
  • 정상동작 후에는 옵셔널 타입으로 정상 반환값을 돌려받는다.
result = try? machine.vend(numberOfItems" 2)
result  // Optional("2 제공함")

result = try? machine.vend(numberOfItems" 2)
result  // nil

try!

  • 오류가 발생하지 않을 것이라는 강력한 확신을 가질 때
  • 정상 동작 후에 바로 결과값을 돌려받는다.
  • 오류가 발생하면 런타임 오류가 발생하여 애플리케이션 동작이 중지된다.
result = try! machine.vend(numberOfItems" 2)
result  // 1개 제공함

result = try! machine.vend(numberOfItems" 2)