BOID

[swift] 함수에서 발생한 오류 알리기(try ,try! ,try? , do - catch) - HoonIOS 본문

swift 시작기

[swift] 함수에서 발생한 오류 알리기(try ,try! ,try? , do - catch) - HoonIOS

HoonIOS 2021. 4. 6. 14:14

안녕하세요 HoonIOS입니다. :)

저번에는 오류처리의 정의와 Error 프로토콜, throw에 대해 알아봤습니다.

 

이제는 오류를 처리하는 방법인 try, try?, try!, Do - catch에 대해 알아보겠습니다.

 

함수에서 발생한 오류 알리기

- 함수에서 발생한 오류를 해당 함수를 호출한 코드에게 알려주는 방법입니다.

- 함수가 오류를 던지면 프로그램의 흐름이 바뀔 가능성이 매우 큽니다. 따라서 오류를 어디서 던지고 받을지 결정을 잘해주어야 합니다.

 

* throw를 이용하여 던진 오류를 try를 이용해서 그 오류를 있는 것은 알지만 시도는 해볼게라는 의미입니다.

 

- try는 try, try!, try?를 통해서 표현을 할 수 있습니다. 따라서 이 3종류에 대한 특징을 알아보겠습니다.

 

종류 특징
try - do~catch 구문과 무조권 같이 써야 합니다.
- 오류가 발생하면 앱이 종료가 되지 않고 catch를 실행시킵니다.
try? - do~catch 구문 없이도 사용이 가능합니다.
- 에러 발생시 nil값을 리턴합니다.
- 에러가 발생하지 않으면 그 반환타입은 옵셔널로 래핑되서 반환됩니다.
try! - 에러가 발생을 하면 크래쉬가 납니다. ( 앱이 강제 종료 )
- 반환 타입은 언래핑된 값이 나옵니다.
- 오류가 발생하지 않는다는 보장아래 사용해야합니다.

 

- 예를 들어 func test( ) throws -> String처럼 함수, 메서드, 이니셜 라이저의 매개변수 뒤에 throws 키워드를 사용하면 해당 함수, 메서드, 이니셜 라이저는 오류를 던질 수 있습니다.

- throws 키워드를 명시해준 함수를 호출했을 때 동작 도중 오류가 발생하면 자신을 호출한 코드에 오류를 던져서 오류를 확인할 수 있습니다.

자판기 동작 도중 발생한 오류를 던지는 예시

( ※ 예시는 야곰의 스위프트 프로그래밍 책에 있는 내용을 참조했습니다. )

코드 설명

* 위 코드에서 vend 메서드의 매개변수 뒤에 throws를 선언해줬으니 오류를 던질 수 있는 메서드입니다. 이 메서드 내부에서는 흐름 제어를 통해 guard문을 통해서 빠른 종료 구문을 사용했습니다.

*  vend 메서드 내에 있는 guard 조건이 만족하지 않으면 throw 키워드를 통해서 오류를 던져서 오류를 던져서 오류를 발생했다는 것을 vend 메서드를 호출했던 코드에게 알립니다. 

 

 참고) throw와 throws의 차이점?

 - throws는 함수 매개변수뒤어 throws를 표현해 오류를 던질수 있다고 표현을 한것입니다.
 - throw는 오류가 발생했다는것을 표현한것입니다.

* vend 메서드는 오류를 던질 가능성이 있으므로 vend를 호출하는 함수인 buyFavoriteSnack함수와 구조체 PurchaseSnack의 이니셜라이저도 throw 키워드를 통해 오류를 던질 가능성이 있음을 표시해줍니다.

* 오류를 던질 가능성이 있는 함수, 이니셜라이저, 메서드를 호출하는 코드는 오류를 처리할 수 있는 구문도 작성을 해야 합니다. 따라서 위의 예시는 throw와  try로 주고 시도만 했지 catch를 통해 처리할 수 있는 코드를 작성하지 않아 컴파일 오류가 뜬것입니다.

 

허허 이렇게 오류를 처리하는 구문의 중요성을 알아버렸습니다. 그럼 이제 오류를 처리하는 오류 처리 방법에 대해 알아보겠습니다.

 

오류처리를 위한 do - catch문

- 이번에는 오류를 처리하는 법인 do - catch구문입니다.

- 함수, 메서드, 이니셜라이저에서 오류를 던져주면 오류 발생을 받은 코드 블록은 do - catch구문을 사용해서 오류처리를 해주면 됩니다.

- do 절 내부의 코드에서 try를 통해 오류를 실행시켜보고 그 오류를 던져 catch구문에서 try를 통해 받은 오류를 전달받습니다.

 

do - catch 구문

do {
       try 오류 발생 가능 코드
       오류가 발생하지 않으면 실행하는 코드
   } catch 오류 패턴 1 {
   	처리 코드
   } catch 오류 패턴 2 where 추가 조건 {
   	처리 코드
   }

- catch에서는 처리할 오류의 종류를 써줍니다. 만약 오류의 종류를 써주지 않고 코드 블록을 생성하면 암시적으로 error라는 이름의 지역 상수가 오류의 내용에 들어갑니다.

* 위 코드는 앞에서 for구문에 에러 코드가 나오면서 중단이 되었던 코드를 do~catch 구문에 따라 에러 코드를 대처할 코드를 작성을 해주었습니다. 그래서 에러가 발생해도 중단이 되지 않고 끝까지 정상적으로 동작을 한 것을 볼 수 있습니다.

 

try? 를 이용한 오류처리 (옵셔널 값으로 오류를 처리하기)

- try?를 사용하여 옵셔널 값으로 변환해 오류를 처리할 수 있습니다.

- try? 는 동작하던 코드가 오류를 던지면 그 반환 코드는 nil이 나옵니다.

 

간단한 예시를 들어보겠습니다.

코드 설명

* try? 표현을 사용해서 호출한 함수가 오류를 던지면 반환 값이 nil을 반환합니다. 반면 오류가 발생하지 않으면 옵셔널 값으로 반환되는 것을 확인할 수 있습니다.

( x변수는 에러 코드를 리턴하는 함수를 try? 했으므로 x값은 nil이 출력됩니다. )

* try? 는 또 에러가 아닌 값을 리턴해도 그 값은 Optional로 wrap 되어 있는 것을 볼 수 있습니다. 따라서 try? 표현을 사용하면 반환 타입은 옵셔널이 됩니다.

( y변수는 100 값을 리턴하는 함수를 try? 했으므로 y값은 Optional(100)이 출력됩니다. )

 

- 그냥 출력하면 옵셔널이 나오므로 if 바인딩이나 guard 바인딩을 사용해서 출력하면 Optional이 벗겨진 값이 출력됩니다.

 

try! 를 이용한 오류처리( 오류가 발생하지 않을 것이라고 확신하는 방법 )

- 류가 발생하지 않을 것이라고 확신을 가지고 처리하는 방법입니다.

- 오류를 던질 수 있는 함수(throw가 명신 된 함수) 등을 호출할 때 오류가 절대로 발생하지 않을 것이라고 확신할 수 있을 때 try! 를 사용합니다.

- 느낌표( ! )는 강제 언래핑과 같이 실제 오류가 발생하면 런타임 오류가 발생해서 프로그램이 강제로 종료가 됩니다.

 

* 위 try? 에서 이용해서 예시를  try!로 바꿔서 처리해보겠습니다.

 

코드 설명

* 첫 번째 x변수의 try는 에러가 발생하지 않았으므로 Optional이 벗겨진 100으로 출력하는 것을 볼 수 있지만 두 번째 y변수는 error코드가 return 되므로 런타임 오류가 발생한 결과를 아래 출력 참에 Fatal error를 통해서 확인할 수 있습니다.

 

- 결과적으로 try! 는 에러가 나오는 throw에 오류를 반환하면 런타임 오류를 반환하는 것을 예제를 통해 확인했습니다. 웬만한 확신이 없으면은 강 제언 래핑을 사용하면 안될꺼 같습니다....ㅎㅎ

 

이번에는 throw, throws에서 던진 에러 가능성을 try를 통해서 실행시키고 try에 따라 do ~ catch문을 통해 에러 처리를 해주는 방법에 대해 알아봤습니다.

 

제가 공부할 때 Json을 통해 서버랑 API통신을 할때 많이 공부했었는데요. do~catch를 통해 통신에러가 났을 때 그냥 끝내기보다는 catch를 통해 무슨 에러인지 파악해 고쳤던 기억이 납니다.

 

그만큼 상당히 중요한 부분이니 확실히 이해하고 넘어가시는 게 좋습니다.

 

다음에는 rethrows(다시던지기)와 defer(후처리)에 대해서 포스팅을 해보겠습니다.

반응형
Comments