2023년 1월 1일
08:00 AM
Buffering ...

최근 글 👑

[Swift-TIL] 예외처리 - 만약 에러가 발생한다면.. (실습편)

2024. 11. 7. 19:42ㆍIOS/Swift-TIL
SMALL

예외처리의 이론편에 이어서 실습편이다.

음.. 필자는 에러가 생길 수 있는 예외가

일어날 수 있는 코드라고 인지하는 것을

do로 감싸줄 것이다.

 

do = 한번 해봐

 

다음에 에러가 일어날 수 있는

코드이기 때문에 try

시도해보겠다는 뜻에 try 이며,

에러가 생기지 않는다면,

그대로 진행을 할 것이고,

에러가 만약에 생기면 catch

에러를 캣치 한다는 것이다.

 

그러면 에러를 어떻게 catch 하냐면,

예외가 일어날 수 있는 코드에서

에러를 던진다(throw error).

 

그래서 에러를 던져주는 쪽이 있고,

그 에러를 받아서 처리해 주는 쪽이 있다.

말로만 하면 감이 잘 오지 않으니

 

느낌적으로 정리해본다면,

문제가 생길만한 코드에서

문제가 생길 수 있는 부분에서

만약 그게 문제가 터졌다면, 에러를 던져주고

얘가 에러를 던지면 받아주는 곳이 있구나~ 라고

이해하면 된다.

 

실습을 진행해 보기로 하겠다.

새로운 프로젝트 파일을 만들어주고

이름은 Exception 이라고 지어줬다.

 

빠르게 시간 많이 사용하지 않고

쓸 수 있는 텍스트 필드로 입력을 하나 받고

VStack으로 묶어 주도록 하겠다.

이렇게 만들어 주고

다음엔 텍스트와 버튼을 만들어주겠다.

이렇게 해주는데,

버튼 안쪽에는 나눴을 때에

해야 할 행동들이고,

변화될 값(사항)을 정의 해줘야하니

@State var inputNumber = "" 를 해주자.

음.. 텍스를 입력할꺼니까 따옴표로

문자열을 표기한 것이다.

이렇게 텍스트를 입력할꺼니까

"text: $inputNumber" 이렇게 해주도록 한다.

Text()에는 Text("나눈 결과는 다음과 같다. \(resultNumber)") 이렇게

해주도록 하겠다.

당연히 resultNumber에 대한 내용도 정의를 해줘야겠다.

resultNumber는 @State var resultNumber: Float = 0

이렇게 정의를 해주는데 얘는 "실수"로 정의를 해줬다.

왜냐면 0으로 나눌것이기 때문이다.

 

그리고, 다른숫자로 나눌 것이기

때문이기도 하다.

 

그렇다면,

시뮬레이터에서 3나누기를 하면

뭔가가 나와야 하겠으니

버튼안에 액션을 정의 해줘야 하니

"resultNumber = "

필자는 무조건 10을 나눈걸로 기준을 잡았다.

10 나누기를 해주고 inputNumber는

String 즉, 문자열이기 때문에

float으로 바꿔줘야 하니

Float(inputNumber) 이렇게 해주면

문제가 생기는데,

왜냐하면,

필자는 착한 사람이기 때문에

숫자는 3, 5 이렇게 숫자만 넣을 건데,

여기는 a, b, c, d가 전부 들어갈 수 있으니,

a, b, c, d를 넣고 float로 바꾸면 터져버린다.

 

그렇기 때문에 이를 해결하기 위해선

 

이렇게 표시가 될것인데,

만약에 이게 float 아니면 어떻게 할꺼냐 하는데,

그러면 1로 해달라고 넣어준다.

이렇게 하면,

a가 들어오면 1이라고 쳐달라고 하는것이다.

결과로 4를 나누면 2.5가 나와야 한다.

오.. 2.5 맞다..

잘 나오는것 같다.

잘 되고 있는걸 확인할 수 있다.

이렇게 틀을 만들어 놓고

이제 정의한 부분들을

함수로 만드는 것이다.

이렇게 해주는데, Float를 반환 받아야 하니까..

이렇게 해주고,

이제 함수를 정의해 주자.

요렇게 해주자.

잘되는지 시뮬레이터에서도 확인해보고,

잘 되는게 확인이 되었으니,

여기에 0을 나누게 되면 어떻게 되는가?

오....

무한.. 좋다..

이미 이건 Xcode가 처리를 해준 것인데,

if문을 통해 만들어야겠다.

이렇게 했을 때

오타가 있어서 수정하였습니다.
inputNuber -> inputNumber

 

에러는 어떻게 던져주는 걸까?

 

throws

이 함수는 문제가 생길 수 있는 부분을

처리할 것이라고 알려주는 것이다.

 

만약에 0이라면,

에러를 던져야하는데 에러가 없으니

만들어줘야 한다.

 

에러는 직접 정의할 수 있다.

이렇게 하면 이제

DevideError는 에러라는 이름의

그냥 enum이고,

에러는 "DevideError {" 여기에

"Error"를 써주면 된다.

 

그러면 

여기에 보이는

"if inputNuber == 0"

만약에 0이라면, 이게 에러라고 생각한다

 

DivideError.devidedByZero 이다.

어떻게? 던져준다.

"throw"

이렇게 하면 위 코드에서 문제가 생길꺼다.

필자는 이부분에서 "throw" 와 "throws" 를 헷갈렸는데,

다들 헷갈리지 않길 바란다.

"devideTen" 얘는 에러를 던지는 함수니까

문제가 생길 수 있다.

"에러가 발생할 수 있는 녀석인데 에러처리를 안할꺼냐?"

라고 말하고 있는것이다.

 

그러면 이 에러를 처리하기 위해선

일단 해보는 do를 써봐야겠다.

do, catch 문제가 생기면

내가 얘를 잡는다.

그리고

이렇게 옮겨주고 어떻게 하느냐?

한번 해보라는 뜻의 try를 해준다.

try resultNumber = devideTen(with: (Float(inputNumber) ?? 1.0))

이걸 진행 하고 문제가 생기면 "catch"

 

그렇다면,

에러를 정의를 해줬고

에러를 던지고

 

에러를 받을 꺼다.

 

그렇다면,

시뮬레이터에서

0을 입력하면

에러 0이 등장하게된다.

그런데 이게 조금 꺼림칙해서

다른 방식으로 조금 해보려 한다.

 

캣치를 늘려봐야겠다.

 

하나만 받을 수 있는게 아니라

여러개를 받을 수 있다..

음...

"DivideError.devidedByZero"

 

만약에 0으로 나눠졌다 한다면

이렇게 해주고,

시뮬에서 실행을 해보자.

음.. 잘나오는것 같다.

그러면 이제 

이 부분이 예외 처리가 되는 것이다.

만약의 0이면,

result에는 0으로 해달라..

이렇게 예외처리를 해주는거다.

이후 다시 시뮬을 실행하면,

"0으로 나누었다"만 나온다.

-1로 바꾸고 0을 나누었을 때

-1.000 들이 나오고

뭐.. 이런식으로

에러를 처리해 줄 수 있다는 것이다.

조금 정리를 해보자면,

에러가 발생할 수 있는 부분을 탐지하면서

물론, 필자의 방식처럼 에러를 안던져도 된다.

그냥 0이 아닐 때에만 나누라는 정의로

"if inputNumber ! =0 {" 

이렇게 하면 예외처리를 한거다..

이렇게 해도 문제가 없지만,

0으로 나눠줄 수 있는 케이스가

있는데 사용자가 0을 입력하는 걸 막을 수가 없으니

입력을 받았을 때 어떠한 제스처를 취하는데

예로 "0으로 나눴으니 다른 숫자를 입력해라"

라고 하려면 0으로 나눠졌다는 것을

명시적으로 던져야 하니

그래서 "throw DivideError.devidedByZero" 이렇게

던져줬다.

그런데 여기서 던지려면

이함수가 무언가 에러를 던질 수 있는 녀석이라는 것을

그 자리에 표시를 해야 된다.

그게

"func devideTen(with inputNumber: Float) throws -> Float {"

이것이다.

함수이름과 파라미터와 그 반환 값 사이에 throw 수를 던져주고

여기서

"throw DivideError.devidedByZero"

에러를 던지는 거다.

 

그러면 "devideTen"을 실행하는

"devideTen(with: (Float(inputNumber) ?? 1.0))" 이녀석은

에러를 던지는데,

에러가 날아오면 위험하니

에러처리를 해달라고 할것이기 때문에

그러면, do try 한번 해보자 하고

그렇게 에러가 생기면,

잡는다는 catch

그런데,

이 에러의경우 필자가 정의한 에러다.

그런데, 실제로는 에러가 다양하다.

 

예를 들어서,

"인터넷이 끊어졌다."

"인터넷 반응 속도가 매우 느리다."

"와이파이가 바뀌었다."

"보안이 매우 취약하다."

이런 경우 사용자에게 지금 뭔가 잘못되었다고

알려주는 에러의 케이스를 쭈욱 정리하고

위와 같이 정의 해서 순간마다 던져 주는데,

이를 고려하지 않으면..

"서버에 요청하기" "받기"

"요청했고 받았을 때 데이터를 넣어 반환"

"요청을 던졌는데 그 사이에 와이파이가 바뀠었다면.."

"만약에 와이파이가 바뀌었다면 그 에러를 던져주고"

"인터넷이 끊어지면 끊어졌다고 에러를 던져주고"

"속도가 느리면 느리다고 에러를 던져주고"

 

그렇게 코드에 어떤 예외들을 막 넣어주면

쓰는 사용자 입장에서 훨 씬 더 쾌적하고 개발하는

사람들도 문제가 생기지 않을 코드라고 인식과 더불어

신뢰성도 증가한다.

 

이처럼 예외처리는 코드에 대한 신뢰성을

높이고 안정성을 높이는 작업이기 때문에

반드시 필요하다고 볼 수 있다.

728x90