일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- MVVM
- CS
- struct
- 학과별커뮤니티
- 대표
- collectionview
- forEach
- RxSwift
- 딕셔너리
- 이론
- 앱개발
- WeatherKit
- 디자인 패턴
- 네트워크
- mvc
- 세종대학교
- 스트럭트
- 토이프로젝트
- 프로토콜
- SwiftUI
- 반응형
- async
- 구름톤 유니브
- swift
- 협업
- uikit
- 기초문법
- ios
- 실습
- AppStore
- Today
- Total
스윞한 개발자
Swift - Concurrency 본문
저번 포스팅에서는 GCD에 대해 정리해 보는 시간을 가졌는데 이번 포스팅에서는 iOS Concurrency에 대해 정리해 보겠습니다!
# Concurrency
: 비동기 및 병렬 작업을 수행
https://developer.apple.com/documentation/swift/concurrency
https://developer.apple.com/documentation/swift/updating_an_app_to_use_swift_concurrency
동시성을 처리할 때 일반적으로 저번 포스팅에서 정리했던 GDC, completion hadler와 Swift Concurrency를 많이 사용합니다.
GDC API로 비동기 작업을 처리하고, completion handler로 비동기가 끝나는 시점에 필요한 작업을 하도록 동시성 처리를 했는데요, 기존에도 동시성 프로그래밍을 위한 방법들이 존재하고 있었음에도 동시성 생태계/Concurrency 가 도입되었습니다.
# Concurrency가 도입된 이유?
1. 가독성
func makeCrunchyCookie(completion: @escaping ((Cookie) -> Void)) {
makeDough { dough in // ✅ (1)
self.chillDough(dough: dough) { ripedDough in // ✅ (2)
self.bakeCookie(dough: ripedDough, time: bakeTime) { cookie in // ✅ (3)
self.drawFace(cookie: cookie) { crunchyCookie in // ✅ (4)
completion(crunchyCookie)
}
}
}
}
}
위와 같이 completion handler를 이용한 코드 작성 방식은 가독성을 저하시킬 수 있습니다. 기존에는 동시성 프로그래밍을 할 때 completion handler를 많이 사용했고, 그로 인해 너무 많은 콜백이 발생하면서 점점 들여 쓰기가 많아져 가독성이 저하됐습니다.
func makeCrunchyCookie() async throws -> Cookie {
let dough = try await makeDough() // ✅ (1)
let ripedDough = try await chillDough(dough: dough) // ✅ (2)
let cookie = try await bakeCookie(dough: ripedDough, time: bakeTime) // ✅ (3)
let crunchyCookie = try await drawFace(cookie: cookie) // ✅ (4)
return crunchyCookie
}
위와 같이 Concurrency를 사용하면 훨씬 가독성이 있습니다.
2. 에러 핸들링 안정성
기존의 방식 코드에서는 completion handler에 데이터와 에러 정보를 같이 보내주는 방법을 많이 선택합니다. completion handler의 경우 에러처리를 위해 필요한 부분이지만, 작성하지 않아도 컴파일 에러가 발생하지 않습니다.
- 에러 처리를 위해 모든 case에서 completion handler를 리턴
>> 코드를 작성할 때 에러 핸들링을 빼먹지 않았는지 주의할 필요가 있습니다.
3. 동기화 처리
동시성 프로그래밍을 할 때 중요하게 생각해야 하는 점 중 하나는 동기화문제입니다. 동시에 실행되는 여러 코드에서 하나의 변수에 접근할 수 있기 때문에 이를 올바르게 처리해야 합니다.
기존의 GCD는 동기화를 올바르게 처리했는지를 컴파일러가 확인해 주지 않기 때문에 동기화 관련 버그가 발생할 수 있고, 이러한 버그들은 코드를 작성할 때 유의해서 작성하거나 테스팅/디버깅을 통해 확인해야 합니다.
Swift Concurrency에서는 컴파일 단계에서 확인해서 동기화를 제대로 처리하지 않은 코드가 있다면 컴파일 에러를 발생시킵니다.
4. 참조 사이클
closure에서 self capture -> retain cycle 발생 가능성
코드 내부에서 self 키워드에 접근해야 한다면 retain cycle(참조 사이클) 발생 가능성을 고려해야 합니다. 무분별한 [weak self]의 사용은 런타임 오버헤드를 발생시킬 수 있습니다. 또한 nil을 체크해야 하는 수고를 거쳐야 합니다. guard let 문법을 사용한다면 self가 nil 일 때 특정 코드들을 건너뛰게 되는 상황도 발생할 수 있습니다.
** 성능**
GCD를 이용해서 코드를 작성할 때 주의할 점은 thread explosion입니다. 이 문제가 발생하게 된다면 성능이 저하될 수 있습니다.
스레드 블록에서 유발되는 메모리 오버헤드, 너무 많은 컨텍스트 스위칭 -> 스케줄링 오버헤드. 그렇기 때문에 GDC는 항상 이러한 점을 고려해야 합니다.
반면 Concurrency에서는 보다 편하게 스레드를 관리할 수 있습니다. Concurrency에서는 await으로 중단 됐을 때, CPU가 컨텍스트 스위칭을 통해 다른 스레드를 불러오는 것이 아닌 같은 스레드에서 다음 함수를 실행시킵니다.(같은 스레드 내의 함수 호출로 대체)
# awync, await 문법의 도입
- async : 비동기 함수임을 나타냄
- await : async 키워드가 표시된 메서드나 함수의 리턴을 기다림. 즉, async 함수는 비동기적 동작, await 키워드를 사용해 비동기 함수의 결과를 대기
func makeCrunchyCookie() async throws -> Cookie {
let dough = try await makeDough() // ✅ (1)
let ripedDough = try await chillDough(dough: dough) // ✅ (2)
let cookie = try await bakeCookie(dough: ripedDough, time: bakeTime) // ✅ (3)
let crunchyCookie = try await drawFace(cookie: cookie) // ✅ (4)
return crunchyCookie
}
completion handler가 사라지면서, 비동기 함수를 한 줄로 처리할 수 있어 훨씬 가독성이 있습니다. 또한 실수로 개발자가 try await 키워드를 빼먹은 경우에는 컴파일러가 오류를 알려줘 더 안정적인 에러 처리가 가능합니다.
# 동작 과정
구조화된 동시성(Structured Concurrency)이 Swift에도 있습니다.
✅ suspend → resume의 과정
1. await 키워드를 만나면 suspension point로 지정하고 일시정지 (suspend)
2. 스레드의 제어권을 시스템에게 넘겨줌
3. 시스템이 다시 비동기 함수에게 스레드 제어권을 넘겨줌
4. suspension point에서 작업 재개 (resume)
WWDC 2021에 따르면, 애플은 스레드 관리를 개발자에게 맡기기보다 시스템 자체에서 처리해 안전성을 보장하고자 했습니다. 그래서 시스템이 넘겨받은 작업의 우선순위와 실행하기에 적절한 스레드를 고려하여 제어권을 넘겨줍니다.
이렇게 동시성 iOS Concurrency에 대해 살펴보았는데요! 앞으로 더 알아야 할 것들이 많은 거 같아요. 다들 파이팅 해서 멋진 iOS 개발자가 되는 그날까지!!
#참고
https://tech.devsisters.com/posts/crunchy-concurrency-swift/
https://engineering.linecorp.com/ko/blog/about-swift-concurrency
'Swift 이론' 카테고리의 다른 글
Swift - ReactiveX(RxSwift) (2) | 2024.04.12 |
---|---|
Swift - WMO 전체 모듈 최적화 (0) | 2024.04.11 |
Swift - GCD (0) | 2024.04.11 |
Swift - MVC to MVVM 개념정리/클린아키텍쳐(Swift UIkit Fundamental) (0) | 2024.02.06 |
IOS - UICollectionView (4) | 2024.01.30 |