[Swift] 오류처리

선주·2022년 4월 11일
0

Swift

목록 보기
14/20

📌 오류처리

Swift에서 오류는 주로 Error 프로토콜열거형을 통해 처리한다.

오류가 발생하면 throw를 이용해 자신을 호출한 지점에 오류를 던져준다. 오류 발생의 여지가 있는 메서드는 throws를 사용하여 오류를 내포하는 함수임을 표시한다.

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

예를 들면 위의 VendingMachineError는 자판기를 사용하면서 발생하는 오류를 정의해둔 것이다.

오류 던지기

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
            // vend 메서드는 리턴값이 String으로 정해져 있지만
            // 오류가 던지는 경우는 리턴값을 만들지 않아도 된다
        }
        
        // 구매하려는 수량보다 미리 넣어둔 돈이 적으면 오류를 던진다
        guard numberOfItemsToVend * itemPrice <= deposited else {
            let moneyNeeded: Int
            moneyNeeded = numberOfItemsToVend * itemPrice - deposited
            
            throw VendingMachineError.insufficientFunds(moneyNeeded: moneyNeeded)
        }
        
        // 구매하려는 수량보다 요구하는 수량이 많으면 오류를 던진다
        guard itemCount >= numberOfItemsToVend else {
            throw VendingMachineError.outOfStock
        }
        
        // 오류가 없으면 정상처리를 한다
        let totalPrice = numberOfItemsToVend * itemPrice
        
        self.deposited -= totalPrice
        self.itemCount -= numberOfItemsToVend
        
        return "\(numberOfItemsToVend)개 제공함"
    }
}


// 판매 결과를 전달받을 변수
var result: String?

오류 받기

오류를 던질 수도 있지만 오류가 던져지는 것에 대비하여 던져진 오류를 처리하기 위한 코드도 필요하다.

오류발생의 여지가 있는 throws 함수(메서드)는 try를 사용하여 호출해야 한다.

// 자판기 인스턴스
let machine: VendingMachine = VendingMachine()

do {
    try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
    print("입력이 잘못되었습니다")
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {
    print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
    print("수량이 부족합니다")
} // 입력이 잘못되었습니다

만약 machine.receiveMoney(0)에서 오류가 발생해서 오류를 던지면 catch문에서 오류를 받는다.


✔️ 간략화

하지만 이렇게 경우 하나하나 핸들링할 필요가 없다면 굳이 이렇게 하는 게 더 복잡하다.

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

요런 식으로 간략화해서 사용하자.


✔️ try?

별도의 오류처리 결과를 통보받지 않고 오류가 발생했으면 결과값을 nil로 돌려받을 수 있다. 정상동작한다면 옵셔널 타입의 정상 반환값을 돌려 받는다.

result = try? machine.vend(numberOfItems: 2)
result // Optional("2개 제공함") 또는 nil

위의 경우 정상동작하면 Optional("2개 제공함")이 반환되고, 오류가 발생하면 nil이 반환된다.


✔️ try!

오류가 발생하지 않을 것이라는 강력한 확신을 가질 때 try!를 사용하면 정상동작 후에 바로 일반 타입의 정상 반환값을 돌려받는다. 하지만 만약 오류가 발생하면 런타임 오류로 애플리케이션 동작이 중지된다.

result = try! machine.vend(numberOfItems: 1)
result // 1개 제공함


야곰의 스위프트 기본 문법 강좌를 수강하며 작성한 내용입니다.

profile
기록하는 개발자 👀

0개의 댓글