본문 바로가기
⌨️ Language/swift

[Swift] 에러 처리

by hyebin (Helia) 2023. 2. 7.

에러 처리 (ErrorHandling)

  • 프로그램 실행 시 에러가 발생하면 그 상황에 대해 대응하고, 이를 복구하는 과정
  • Swift에서는 런타임 에러가 발생한 경우 처리를 위해 에러의 발생(throw ing), 감지(catching), 전파(propagating), 조작(manipulating)을 지원하는 일급 클래스를 제공

 

에러의 표시와 발생 (Representing and Throwing Errors)

  • Swift에서 에러는 Error 프로토콜을 따르는 타입의 값으로 표현
  • Error 프로토콜은 비어있으며 에러 처리에 타입을 사용할 수 있음을 나타냄
enum ServerError: Error {
    case forbidden
    case notFound 
    case internalError
    case unauthorized
    // ...
}

 

에러 처리 방법

  • 에러가 발생했을 때, 특정 코드 영역은 에러를 처리해야 하는 책임이 있음
  • 문제를 수정하거나, 다른 대안을 시도하거나, 사용자에게 실패를 알려야 함
  1. 에러가 발생한 함수에서 반환 값으로 에러를 반환하여, 해당 함수를 호출한 코드에서 에러를 처리
  2. do-catch 구문을 사용
  3. 옵셔널 값을 반환
  4. assert를 이용하여 강제로 크래쉬를 발생

 

함수를 사용해 에러 전파하기

  • 어떤 함수, 메서드 혹은 Initializer가 에러를 발생시킬 수 있다는 것을 알리기 위해서 throw 키워
    드를 함수 선언부의 파라미터 뒤에 작성
  • throw 키워드로 표시된 함수를 ‘throwing function’이라고 부름
  • 만약 함수가 리턴 값을 명시했다면 throw 키워드는 리턴 값 표시 기호인 화살표(->) 전에 작성
  • throwing function 은 그 함수를 호출한 곳으로 에러를 전파
func canThrowErrors() throws -> String
func cannotThrowErrors() -> String

 

do-catch 구문 사용한 에러 처리

  • 코드 블록에서 에러를 처리하기 위해 do-catch 구문을 사용
  • 만약 do 구문에서 에러가 발생한다면 에러의 종류를 catch 구문으로 구분해 처리 가능
  • 어떤 에러를 이 구문이 처리할 수 있는지 알리기 위해 catch 뒤에 패턴을 작성
  • 만약 catch절이 패턴을 갖고 있지 않다면 발생하는 모든 에러를 지역 상수인 error로 바인딩
do {
	try 표현식
 	결과
} catch 패턴 1 {
 	처리 결과
} catch 패턴 2 where 조건 {
 	처리 결과
} catch {
 	처리 결과
}

 

에러를 옵셔널 값으로 변환하기

  • try? 키워드를 사용하면 에러를 옵셔널 값으로 변환하여 처리 가능
  • 만약 try? 뒤에 있는 코드에서 에러가 발생한다면, 반환 값은 nil
func someThrowingFunction() throws -> Int {
	// ...
}
let x = try? someThrowingFunction() // 에러가 발생하면 x는 nil이 됩니다.

// x와 y는 동일한 값을 가질 수 있으며, 동일한 동작을 합니다.
let y: Int?
do {
	y = try someThrowingFunction()
} catch {
 	y = nil
}

 

에러 전파를 비활성화하기

  • 함수나 메서드가 에러를 발생시키지 않을 것이라 확신하는 경우, try! 키워드를 사용
  • 에러 전파를 비활성화하고, 에러가 발생하지 않도록 runtime assertion으로 호출을 래핑
  • 실제 에러가 발생할 시 런타임 에러가 발생

 

정리 작업 지정 (Specifying Cleanup Actions)

  • defer 구문은 현재 코드 블록을 나가기 전에 꼭 실행되어야 하는 코드를 작성
  • 코드가 블록을 빠져나가기 전에 꼭 마무리해야 되는 작업을 할 수 있게 도와줌 
  • defer 구문은 에러 처리 이외의 경우에도 사용 가능
  •  파일 디스크립터를 닫고 수동으로 메모리를 비우기 위해 defer문을 사용 가능
func processFile(filename: String) throws {
	if exists(filename) {
    	let file = open(filename)
 		defer {
 			close(file) // block이 끝나기 직전에 실행, 주로 자원 해제나 정지에 사용
 		}
 		while let line = try file.readline() {
 			// Work with the file.
 		}
 		// close(file) is called here, at the end of the scope.
 	}
}

 

반응형

'⌨️ Language > swift' 카테고리의 다른 글

[Swift] ARC  (0) 2023.02.07
[Swift] 제네릭 (Generic)  (0) 2023.02.07
[Swift] 고차함수  (0) 2023.02.06
[Swift] 클로저 (Closure)  (0) 2023.02.06
[Swift] 익스텐션 (Extensions)  (0) 2023.02.06

댓글