[Swift]비동기 처리에 관한 고찰

유경박·2023년 8월 29일
0

Swift로 IOS 개발을 하다보면 GCD를 이용하게되고 GCD를 이용하여 비동기 처리를 계속 하다보면 콜벡 헬에 빠질수도 있다.

factorio thumbnail (물론 이는 escaping closure를 사용했을때 얘기다)


한편, 최근 async/await이라는 키워드가 추가되어 비동기 처리를 쉽게 동기화하여 작업을 처리할 수 있지만서도 모든 비동기 콜백 형식의 프로그램 구조를 async/await으로 바꾸기에는 한계가 있다.

그 이유는 아래와 같다.
1)async await은 시스템 리소스를 사용하기 때문에 남발을 하게된다면 CPU 점유율과 퍼포먼스가 오히려 안좋은 결과를 초래한다.
다른 언어(C/C++, C#)의 경우 스레드를 직접 생성하여 User과 관리할수 있는 반면 Swift는 GCD가 관리하기 때문에 자원이 한정적이다.

2)Swift 5.5버전부터 등장하였기때문에 호환성 관련해서도 문제가 발생할수 있다.(특히 마이그레이션하면서 단순히 Task나 main.actor블록으로 감싸서 많은 코드를 async 함수에서 사용한다면 오히려 속도가 저하될수 있다.)

3)Suspension points를 고려하여 코드를 작성하여야 하며 이를 간과한채 개발을하다가 문제가 발생시 컴파일에러나 런타임에러가 발생하지 않기에 디버깅에 많은 시간을 소요할 수 있다.(뿐만 아니라 스레드의 점유가 너무 길어진다거나 데드락이 생길경우 Task.yield()와 같은 스레드 점유권 관련 처리도 추가적으로 해줄 필요가 있다.)

(다시 한번 강조하지만, 모바일 앱의 자원은 다른 개발분야보다 한정적이다(적어도 응용프로그램쪽보다 더..))

따라서 현재 코드 가독성을 고려하여 async/await으로 마이그레이션을 하는 곳이 많을것이라고 생각하는 한편 아직 레거시 코드를 접해보지 않았지만 GCD를 통한 비동기 작업은 한번에 어떻게 완료할수 있을지 궁금하여 조사를 하게 되었는데 그때 사용하는것이 Dispatch.Group이다.

사용방법은 다음과 같다.

1) Dispatch Group 생성한다
let group = DispatchGroup()

2) Group으로 처리할 작업에 Enter ~ Leave를 넣는다.
i)
group.enter()
...
..
group.leave()

ii)
group.enter()
..
..
..
group.leave()
..
..
..
(마치 멀티스레드의 Critical Section을 처리하는 방법과 비슷하다)

3)최종적으로 완료된 작업들을 UI에 업데이트 시키고자 할때 group에 있는 작업들을 notifiy하여 UI업데이트 시킨다.

group.notify(queue : .main) { [weak self] in
//UI 업데이트
}

아무래도 Swift는 스레드 관련하여 GCD가 관리하다보니 코드도 직관적이고 사용법도 쉽다.
이와같은 방식은 나중에 혹시라도 백그라운드로 Batch 작업단위로 일을 처리할때 사용할것 같다.
(async await과 달리 시스템적으로 락걸릴일이 없기떄문에 더욱 안정적일듯 하다)

profile
으아아

0개의 댓글