상세 컨텐츠

본문 제목

[Swift Concurrency] Async/Await 진짜 쉽게 이해하기 (1) - Do,Try,Catch 알기

Swift

by Mr.Garlic 2023. 6. 12. 12:08

본문

비동기 작업을 아름답게, Async/Await의 사용법 익히기

async? 우리때는 nsync가 짱이었어!!!

안녕하세요 이웃님들~ 그리고 Swift 정보의 바다속에서 어쩌다가 제 블로그에 방문하신 여러분~

저는 모호한것을 참 싫어하는데요~ 그래서 앱개발과외할때도 그렇고 항상 퍼뜩 이해가 되는 설명을 하고 싶어해요~

Async/Await에 대해서 앞으로 몇개의 글을 올릴 예정인데요!

오늘은 들어가기에 앞서 기본적으로 알아야 하는 문법이 있어서 그것 먼저 설명을 드리겠습니다! 

Do,Try,Catch 문법 (일명 에러 던지고 받기)

기존에 이 문법을 잘 알고계신 분이라면 다음 화로 진행하세요!

영어시간에 다들 Do, Try, Catch, Throw라는 단어 다 배우셨죠~ 저도 배웠습니다~ 하하

Do -> 해라

Try -> 해봐라

Catch -> 잡아라

Throw -> 던져라

네 참 쉬운데요?

 

Swift 문법에서도 이 단어들을 종종 보게 됩니다ㅎㅎ 

오늘 설명할 Do, Try, Catch 문법에서 그렇습니다!

 

엄청 어려운건 아니고요~ 이런 상황에서 쓰입니다.

우리가 이미지를 받아오는 함수를 작성한다면 아래와 같은 모양이겠죠~~ 

func getImage() -> UIImage {

}

근데 이미지를 API로 받아오게 된다면... (대부분 API로 이미지 받아오잖아요.. 그쵸?)

이 동작은 비동기 적일겁니다.

비동기가 뭐냐!
우리가 API 요청을 하면 서버에 가서 응답을 받아와야 하잖아요? 아마 뭐 저기 땅끝마을 서버실에 갔다가 올수도 있고... 하여튼 좀 늦게옵니다. 그래서 요청하고 나서 저희는 저희 할 일을 좀 하다가 응답이 왔다고 하면? 그때 가서 그 이미지를 받아서 가공을 하든 그림을 바꿔주든 우리가 응답으로 받은 내용을 사용하고 싶습니다. 이런 동작을 비동기 라고 합니다. 

 

자 그러면 일단 throws 키워드를 사용해서 우리가 만든 getImage 함수 안에 API 요청을 하는 코드를 작성해볼게요~!

 

throws란?

어떤 함수를 만들었는데, 그 함수가 성공과 실패시에 서로 다른 타입의 값을 전달해준다면.. 우리 기존에는 어떻게 했을까요? Result 타입으로 성공 실패를 나누어주거나, escaping closure사용해서 completionHandler를 사용할때는 인자로 넣어주기도 하고 그랬을거예요~

 

throws는 조금더 명확하게~ 깔끔하게~ 성공과 실패를 나눠줄수가 있어요. 

여기서 잠깐~ throw라는 단어 왜쓸까요? 우리도 에러를 던져준다고 하잖아요? 원래도 영어로 에러가 발생한다 할때 throws an error 이런식으로 말해서 사실 그냥 동사를 그대로 갖다 쓴거예요~ 

 

그래서 함수 리턴하기 전에 그앞에 throws가 써있다? 에러일때는 뭔가 다른걸 던져주고 있다 보시면 됩니다~!

// 주소는 예시예요! 이미지를 불러올 이미지 주소를 넣어주고
let url = URL(string: "https://ios-developer-storage.tistory.com/")!

func getImage() throws -> UIImage {
	// 그럼 이 if문까지는 동기적으로 실행이 주욱 되다가
	if URLSession.shared.dataTask(with: url) { data, response, error in
    // 요 안에는 비동기로 나중에 실행이 되겠죠?
    // 이 가드문을 잘 통과하면 이미지가 온거고, 아니면 실패를 한거겠죠?
     guard 
         let data = data, 
         let image = UIImage(data: data), 
         let response = response as? HTTPURLResponse else {
         // 실패했을때는 에러에 디스크립션을 전달해주고 싶어서 여기에서 throw를 사용합니다.
         	throw error.localizeddescription
         }
         // 여기는 성공했을 때니까 정상적으로 이미지를 리턴해줍니다.
         return image
     }
}

 

자 그러면~ 이렇게 작성한 함수를 사용할때는 어떻게 하면 될까요?

사용할때는 try를 기억하시면 됩니다. 

 

이렇게 쓰면 "너 throw 라서 실패하면 이미지가 아니라 다른거 올건데 이렇게 쓰면 어떡해!" 라고 앵앵 웁니다.

let image = getImage()

 

이렇게 써주시면 됩니다. 정말 쉽군요.

let image = try getImage()

try를 쓰면 좋은점이 do, catch 구문을 써서 에러를 핸들링하기가 참 좋다는 것인데요.

굳이 throw로 에러처리를 했으니까 do, catch와 함께 깔끔한 에러처리를 해보겠습니다.

보시면 아시겠지만, do 안에는 throw하는 함수를 호출해서 성공했을 때의 처리를 해주시면 되는데요, try가 실패하면 그 이하의 코드는 모두 실행이 되지 않아요. 그리고 바로 catch로 넘어갑니다.

 

만약에 try가 실패하더라도 이하의 구문들이 실행이 되었으면 좋겠다면 try? 를 사용해서 옵셔널하게 해주시면 catch로 바로 넘어가지 않고 실행을 다 할겁니다. 

do {
	let image = try getImage()
} catch {
	print(error)
}

 

자 이렇게 do { try } catch { 에러처리 } 를 다 배웠습니다! 

다음 시간에는 do, try, catch가 async await 적용하면서 왜 필요한지 보면서

async await을 알아보도록 하겠습니다~!!

ㅎㅎ

 

관련글 더보기