λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
⌨️ 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.
 	}
}

 

λ°˜μ‘ν˜•