[야곰] Swift 개념정리 - 오류처리

Judy·2022년 4월 13일
0

Swift 공부

목록 보기
11/11

오류처리

오류처리는 오류 상황에 대응하고 복구하는 과정을 말한다.

Swfit에서 오류는 Error 라는 프로토콜을 준수하는 타입의 값으로 표현이 된다.

Error 프로토콜은 빈 프로토콜이지만 해당 타입이 오류처리로 이용됨을 알려준다.

오류 표현

enum을 이용한 오류 표현

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

특히 열거형(enum)이 오류처리에 적합하고 자주 쓰이는데 연관 값을 통해 오류에 관한 부가적인 정보를 표현할 수 있다.

예시) 자판기 동작에 관한 오류처리

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

오류 처리


오류가 발생하면 던지는 것에서 끝이 아닌 처리를 해줘야 한다.

문제 수정하기, 다른 접근 방식을 시도하기, 사용자에게 오류를 알리기 등과 같은 처리를 통해 다음 진행을 유도해야 한다.

오류처리의 네 가지 방식

  1. 해당 함수를 호출한 코드로 오류 전파
  2. do-catch 문으로 처리
  3. optional을 이용한 처리
  4. 오류가 발생 부정

오류를 던지면 코드의 흐름이 바뀌기 때문에 어디서 오류가 발생하는지를 빠르게 아는 것이 중요하다.

이러한 위치는 try를 통해 쉽게 알 수 있다.

1. 오류 전파 - throw

오류는 throw 키워드로 던질 수 있는데 오류를 던질 수 있는 함수에는 throws를 붙이고 throwing function 라고 부른다.

만약 함수에 특정 리턴값이 있다면 throws 뒤에 써주면 된다.

func canThrowErrors() throws -> String

throwing function 안에서 오류가 throw 되면 자신이 호출 된 위치(함수나 메서드, 이니셜라이저 등)으로 오류를 전파한다.

throwing function만 오류를 전파할 수 있고 아니라면 함수 내부에서 오류를 처리해줘야 한다.

func receiveMoney(_ money: Int) throws {
	// 입력한 돈이 0이하면 오류를 던집니다
    guard money > 0 else {
        throw VendingMachineError.invalidInput
    }
    // 오류가 없으면 정상처리를 합니다
    self.deposited += money
    print("\(money)원 받음")
}

메서드가 오류를 전파하면 이 메서드를 호출한 코드는 오류를 처리하거나(do-catch) 오류를 다시 전파해야(try) 한다.

try - 오류를 다시 전파

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    try vendingMachine.vend(itemNamed: snackName)
}

buyFavoriteSnack 역시 throwing function으로 vend에서 오류가 발생하면 try로 오류를 전파하도록 처리했다.


2. do-catch로 오류 처리

기본형식

do {
    try expression
    statements
} catch pattern 1 {
    statements
} catch pattern 2 where condition {
    statements
} catch pattern 3, pattern 4 where condition {
    statements
} catch {
    statements
}
do {
    try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
    print("입력이 잘못되었습니다")
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {
    print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
    print("수량이 부족합니다")
} catch {
    print("Unexpected error: \(error).")
}

do에서 오류가 발생할 수 있는 코드를 실행하고 만약 receiveMoney가 오류를 던지면 일치하는 catch문을 따라 오류를 처리한다.

만약 일치하는 catch 절이 없으면 마지막 catch에서 처리하게 된다.

catch로 모든 오류를 처리할 필요는 없지만 오류는 다른 구문에서라도 반드시 처리되어야 한다.

func eat(item: String) throws {
    do {
        try vendingMachine.vend(itemNamed: item)
    } catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
        print("Invalid selection, out of stock, or not enough money.")
    }
}

,(컴마)를 이용해 여러 오류를 한 catch에서 처리할 수도 있다.

3. Optional로 전환 - try?

try?를 이용해 오류를 Otional 값으로 전환해서 오류를 처리할 수 있다.

별도의 결과로 처리하지 않고 오류가 발생하면 nil을 돌려받고 정상 동작 시엔 Optional 타입으로 결과를 반환한다.

result = try? machine.vend(numberOfItems: 2) // 정상 작동
result // Optional("2개 제공함")
result = try? machine.vend(numberOfItems: 2) // 오류 발생
result // nil

4. 오류 전파 비활성화 - try!

오류가 발생하지 않는다는 확신이 있을 때는 try!를 사용해 정상 동작 후 바로 결과 값을 돌려받을 수 있다.

하지만 만약 오류가 발생하면 런타임 오류가 발생해 실행 종료된다.

result = try! machine.vend(numberOfItems: 1)
result // 1개 제공함
//result = try! machine.vend(numberOfItems: 1)
// 런타임 오류 발생!




Swift - Error Handling

profile
iOS Developer

0개의 댓글