-
Notifications
You must be signed in to change notification settings - Fork 3
[승용] Explore structured concurrency in Swift
-
처음 프로그래밍이 나왔을 떈 코드를 읽기 어려웠음
- 명령어의 시퀀스로 이루어져 있어 제어 흐름이 여기저기로 이동함
-
요즘은 그런걸 보기 힘듬
- 구조화된 프로그래밍을 사용해 제어 흐름을 더욱 단일화시킴
- ex) if-then
-
구조화된 프로그래밍은 자연스럽게 nested 및 sequenced 될 수 있다.
- 이는 프로그램을 위에서 아래로 자연스럽게 읽을 수 있도록 도와줌
-
이것들이 구조화된 프로그래밍의 중요한 요소들!
-
그러나 요즘 프로그램들은 비동기적이고 동시적인 코드들을 제공하는데 이들은 구조화된 프로그래밍을 사용해 더 쉽게 코드를 작성할 수 없었다.
-
unstructured 비동기적 코드 예시
- 에러 핸들링 사용 불가
- 반복문 사용 불가
-
async-await을 사용해 개선
- 에러 핸들링 사용 가능
- 반복문 사용 가능
- 반환하는 값이 있음
- asyn-await으로 비동기적 작업은 개선했는데, 여러 개의 작업을 동시적으로 작업하고 싶다면?
- Task 사용
- 각 task들은 다른 실행 흐름과 동시적이게 실행되고, 안전하고 효율적일 때 자동적으로 실행되도록 시스템에 의해 스케줄된다.
- Swift에 깊이 통합되어 있기 때문에 컴파일러가 동시성 문제를 감지할 수 있음
- async 함수를 호출한다고 task가 생성되는 것이 아님.
- Task 호출을 통해 명시적으로 task를 생성함
- async let
-
await 비동기적 작업을 concurrent하게 실행하고 싶을 때 사용 가능
-
binding을 만나면 swift는 child task를 생성
-
child task는 데이터 다운로드 즉시 시작
-
parent task는 result 변수에 임시 값(placeholder)으로 즉시 바인딩
-
이 parent task는 이전에 진행되던 작업과 동일한 흐름이기 때문에 그 아래 구문들을 이어서 실행함
-
그러나 임시 값을 대체할 실제 값이 필요한 구문에서는 child task의 완료를 기다림
-
- 적용 전
![Screenshot 2024-08-18 at 11 58 51 AM](https://private-user-images.githubusercontent.com/22342277/358900030-37284262-e66b-4d64-9dcb-e2387cf2dc69.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAwMzAtMzcyODQyNjItZTY2Yi00ZDY0LTlkY2ItZTIzODdjZjJkYzY5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTM4NDBkYmZiYjY5YmQzMDNiNDkxYzcxODE1M2JlZTRiYzdhOGQ0MDg2OTQwMzEwMWQ1NzI1OTQ5YzMwYWQwZDkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.XkpzAUsSEK8oDrdQesbH7J8i_NQkTLYEDrYszQQyvl8)
- 적용 후
![Screenshot 2024-08-18 at 12 05 22 PM](https://private-user-images.githubusercontent.com/22342277/358900035-a88259cd-06bc-4d02-b05e-215778db352e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAwMzUtYTg4MjU5Y2QtMDZiYy00ZDAyLWIwNWUtMjE1Nzc4ZGIzNTJlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWM3NmY3YmM5MTBjYjExYjNiYWZjZGU2YTczYjIwMjA0ZWRjYzU4YTkxNzAwMDg1YzJmMDNlZWQzOTc5MmIxMTQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.ubvkgO3k053BkTro6Gpivjh9gWUHhyt1Fqn9m41Ekno)
- try awiat은 실제 변수를 사용할 때에만 적용하면 됨
- Swift에서 생성되는 모든 child task는 Task Tree라는 계층구조의 일부이다.
- 이는 단순한 내부 구현 사항이 아닌, structured concurrency의 중요한 개념이다.
- task tree는 task의 속성(cancellation, 우선순위, task-local 변수 등)에 영향을 미친다.
- async 함수에서 다른async 함수를 호출할 때에는 동일한 Task가 호출을 실행하기 위해 사용된다.
![Screenshot 2024-08-18 at 12 48 39 PM](https://private-user-images.githubusercontent.com/22342277/358900060-be602690-4b8c-4b01-b4a6-f21f6b9b88a9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAwNjAtYmU2MDI2OTAtNGI4Yy00YjAxLWI0YTYtZjIxZjZiOWI4OGE5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRjYmJmNjZlYTQ0NGU4MDg2Yjk3OGE0ZTI3NTQwN2U4NDA3YjM3ZTFlZTgxOGIwZDY0MzRmMzJlY2EyNzQ4NWImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.Wg2gNtyxsQTyT7qIg2Cz6XuBIUYcSQYnC2DgYLEDbyA)
- 따라서 fetchOneThumbnail 함수는 해당 Task의 모든 attribute들을 상속받는다.
- async-let 등을 사용해 새로운 structured task를 생성하면, 현재 함수가 실행되고 있는 task의 child task가 된다.
- Task는 특정 함수의 child는 아니지만, lifetime이 함수의 범위에 묶여 있을 수는 있다.
- Task Tree는 parent task와 각 child task와의 연결로 이루어져 있다.
![Screenshot 2024-08-18 at 1 05 08 PM](https://private-user-images.githubusercontent.com/22342277/358900074-9c39461e-7dac-43b1-9cc5-fa2c54825a10.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAwNzQtOWMzOTQ2MWUtN2RhYy00M2IxLTljYzUtZmEyYzU0ODI1YTEwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTEyOWVhNTdhNTJiN2YwZTI5NDc5MGNlYzU4Mzk1OThmMTM2YTlhMmE3MDRkNWYxNjM3YTUzNWZhZTc4YmYxN2QmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.hi1jPcMLYgqi6O3KVJP-TIP1tFbUWoul-PcFku1L-tQ)
- 이 연결은 다음과 같은 규칙을 강제한다:
- 부모 태스크는 자식 태스크가 모두 완료되기 전에는 작업을 끝낼 수 없다.
- 이 규칙은 child task가 await되지 않는 비정상적인 흐름에서도 유지된다.
- 위 코드에서 metadata를 먼저 await하고, data를 나중에 await한다고 가정했을 때 metadata task가 오류를 던지면서 완료되면 fetchOneThumbnail 함수도 즉시 오류를 던지고 종료해야 한다.
- 그렇다면 data task는 어떻게 될까?
- 비정상적인 종료가 발생하면 Swift는 자동으로 await되지 않은 task를 canceled로 표시하고, 종료 전에 해당 task가 완료되기를 기다린다.
- task의 cancel이 task의 중지를 의미하지는 않는다.
- task에게 그 결과가 더이상 필요하지 않음을 알리는 신호만을 보낸다.
- cacel되는 task의 자손 task들도 자동적으로 cancel된다.
- task의 cancel이 task의 중지를 의미하지는 않는다.
- 따라서 fetchOnceThumbnail이 생성한 모든 structured task들이 완료된 후에 에러를 던지며 종료될 것이다.
- 이는 structured concurrency의 핵심 개념으로, task 누수를 방지하고 task의 수명을 자동으로 관리한다.
- 이는 ARC가 자동으로 메모리를 관리하는 방식과 유사하다.
- Swift의 task cancellation은 협력적(cooperative)인 방식으로 이루어진다.
- 코드가 명시적으로 취소 상태를 확인하고 상황에 맞게 실행을 정리해야 한다.
- cancellation을 염두에 두고 코드를 작성해야 한다.
- task는 취소되는 순간에 즉시 멈추지 않는다.
- task의 취소는 어디서든 확인 가능하다.
![Screenshot 2024-08-18 at 2 32 05 PM](https://private-user-images.githubusercontent.com/22342277/358900086-1ff425d5-278a-4386-aa4f-a5b46e1fa9df.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAwODYtMWZmNDI1ZDUtMjc4YS00Mzg2LWFhNGYtYTViNDZlMWZhOWRmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTYzY2NjYzNjMzQ2ZjBjNmE3OGE5ZGIwYmUwNTVmYjUzOGRhNjRmMGU2NjkxMmIwODNhMzY3MGE3YzQzODFhZWMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.9koqOrDCpHmqPi2axkVXzq0j-EIjm3OiZbk9ZCKExfk)
![Screenshot 2024-08-18 at 2 31 56 PM](https://private-user-images.githubusercontent.com/22342277/358900099-1eb7a37b-6fbb-4586-a86a-663a3507cdde.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAwOTktMWViN2EzN2ItNmZiYi00NTg2LWE4NmEtNjYzYTM1MDdjZGRlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTdjNmM3ZDk5YWI5ZDU0ZTAyYmY5OWZjMDQ0ZWMxYjQ3MjQ4YWJjNmFlN2Y4MzdmZmEwNWYyMzNhNjA4ZGQ2NDgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.dsGUEoxGwdWfa6rOrQ9oTE5qrn3e-wkP_NrEQ-aXBtY)
- 따라서 반복적으로 이미지를 다운로드하는 코드에서 cancellation이 발생한다면 그 이미지를 다운로드하지 않고 건너뛰는 코드를 명시적으로 추가해줄 수 있다.
- 여기까지 Async-let task에 대해 알아보았다.
- async-let보다 더 유연하다.
- async-let은 고정된 크기의 concurrency가 있을 때 잘 작동하고, 변수처럼 범위 내에서만 동작한다.
- 위 예시의 fetchOneThumbnail은 하나의 id당 두 개의 child task를 생성한다.
- 이러한 task들은 다음 반복이 시작되기 전에 완료되어야 한다.
- 그러나 동적 동시성, 즉 ID 배열 크기에 따라 동시성 수준을 조정하고 싶다면 Task Group을 사용하는 것이 좋음
- task group은 동적인 갯수의 concurrency를 제공하기 위해 설계된 structured concurrency의 한 형태
- withThrowingTaskGroup 함수를 사용해 작업 그룹 생성 가능
![Screenshot 2024-08-18 at 5 19 56 PM](https://private-user-images.githubusercontent.com/22342277/358900139-7dedbf3f-8743-43b8-8c75-825a80836a32.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAxMzktN2RlZGJmM2YtODc0My00M2I4LThjNzUtODI1YTgwODM2YTMyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg2NzMyYTI5NWJlMzZlZmI5MjdkZjhmOTdkYWM3YzI2YTg1M2NkNDQ4MGFhYmE3ZGJiYTc5ODA5ZDVlNmIzY2ImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.5KSHLMNensgDDM6mdarAMrjvllVioe1YYusGPvg6LEk)
- 이 작업 그룹이 정의된 범위를 벗어나면 모든 작업이 자동으로 완료될 때 가지 기다린다.
- group task들의 child task들이 생성되고... 그것들이 모두 끝날 때 까지 기다린 후 thumbnails를 return할 수 있음
- 다만 위 코드는 경쟁 조건 문제가 있음
- thumbnails에 동시적으로 여러 스레드들이 접근해 작업 가능
- 아래와 같이 개선할 수 있다:
![Screenshot 2024-08-18 at 5 23 34 PM](https://private-user-images.githubusercontent.com/22342277/358900143-eba5c11e-78e4-4b31-80ea-05c769143fe6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAxNDMtZWJhNWMxMWUtNzhlNC00YjMxLTgwZWEtMDVjNzY5MTQzZmU2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAzMmY3MjJkM2RjYjI5Yjg0YzYwNGMwNWUyMTFhOGZiNWRkNTM2NzQ4NTZkMTFhZDE1NzQ4YmRlOTFiZjhlZGUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0._XFur2tVrQ_j1L03ykbOZAav5bFsLuwd6AiJ1EQaY3Q)
-
타입이 AsyncSequence를 준수한다면 for-await을 사용해 반복 가능
-
Task group은 structured concurrency의 한 형태이지만 async-let과는 약간 다르게 동작한다.
-
만약 task group 안에서 실행 중인 task 중 하나가 오류를 발생시킨다면 이 오류는 그룹 블럭 밖으로 throw되고 그룹 내의 다른 모든 task는 암시적으로(implicitly) cancel된 후 완료될 때 까지 기다리게 된다.
- 이 부분은 async-let과 똑같이 동작
-
그러나 task group이 정상적으로 블록을 빠져나갈 때는 cancellation이 implicit하게 일어나지 않는다.
- 이는 fork-join(분기 후 결합) 패턴을 표현하기 쉽게 만들어준다.
- 작업들은 await될 뿐 cancel되지 않는다.
-
group의 cancelAll 메소드를 사용해 수동으로 모든 작업을 취소할 수 있음
- 모든 작업들이 structured pattern에 들어맞지는 않음
- non-async 코드에서 task가 시작될 경우
- task를 시작할 때 부모 task가 없는 경우
- task의 수명이 단일 범위 또는 단일 함수의 제한이 맞지 않는 경우
- 객체를 활성화하는 메소드에 task를 시작하고, 객체를 비활성화하는 다른 메소드 호출에 task를 종료하고 싶을 수도 있음
- 예시
![Screenshot 2024-08-18 at 5 40 13 PM](https://private-user-images.githubusercontent.com/22342277/358900177-7fd75a90-00b1-44dc-9969-c8d90954e9ff.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAxNzctN2ZkNzVhOTAtMDBiMS00NGRjLTk5NjktYzhkOTA5NTRlOWZmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWViNGM1MzVjMTE4ZjA0ZjQ3MWMyMWViOTA1YWJmMTgxNzlhNzdlYjM1OGI2MmU1ZTliYzE4ZTdjZTFmZDNlZGYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.j7h_QqnTyac2gRsR5gZgrZ4FqG3nlnZ3-XEMvUAlKcw)
- collection뷰의 델리게이트에서 fetchThumbnail 함수를 사용하고 싶음
- 그런데 UI와 관련된 코드이기 때문에 @MainActor 적용해 메인 스레드에서 실행되는 코드
- 여기서 await을 그냥 사용할 수는 없음 - 오류 발생
- Swift는 이러한 상황을 위해 unstructured task 생성을 지원함
![Screenshot 2024-08-18 at 5 40 59 PM](https://private-user-images.githubusercontent.com/22342277/358900185-97d7ae83-d794-437a-872e-e82520377cb2.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAxODUtOTdkN2FlODMtZDc5NC00MzdhLTg3MmUtZTgyNTIwMzc3Y2IyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRhMDJlMWZkZGMxM2UwYTBmODkyYTY0OTQ1YzU2MDgzN2E4NzhiOWEyNDg3ZjU2MmI5NTc4YTJkMzIyZjc5MGYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.thrXuXs3ltVlTIQCu3KrvvNL0FixPUXBbPaMkp-wAFM)
- 런타임에 Task를 만나면 Swift는 task를 원래 범위와 같은 actor에서 실행되도록 스케줄링한다.
- 한편 제어권은 즉시 호출자에게 반환된다.
- fetchThumbnails 태스크는 메인 스레드에서 실행되지만, 델리게이트에서 메인 스레드를 블록하지 않고 실행할 기회가 있을 때 실행된다.
- unstructured task의 특징
- 시작 context의 actor를 상속받음
- 원본 task의 우선순위와 기타 특성을 상속받음
- 범위가 지정되지 않음(unscoped)
- task가 시작된 범위(scope)에 수명이 제한받지 않음
- non-async 함수 등 어느 곳에서나 생성 가능
- cancellation 및 에러 전파와 await을 수동으로 관리해야 함
- 아래는 스크롤 범위 바깥으로 벗어난 thumbnail fetch task들을 명시적으로 cancel하는 예시
![Screenshot 2024-08-18 at 5 48 10 PM](https://private-user-images.githubusercontent.com/22342277/358900206-cd3f1e69-b21c-4c83-ba49-1f0e2dd2da45.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAyMDYtY2QzZjFlNjktYjIxYy00YzgzLWJhNDktMWYwZTJkZDJkYTQ1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTU0YTU4YjE1YWZmNmIzM2UxYzI0NjA4OGVlOTY0YzgzMjE1YmMzNGI4NGEyODE0OWU3MThkZGE4ODc5YjhjMjkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.rFDoP4YKOWTUo52U_TsWSVmU3VeFT0ub160l1C9x9_M)
![Screenshot 2024-08-18 at 5 48 27 PM](https://private-user-images.githubusercontent.com/22342277/358900214-0ce435b2-ce4d-456b-9cea-d23935fd1b00.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAyMTQtMGNlNDM1YjItY2U0ZC00NTZiLTljZWEtZDIzOTM1ZmQxYjAwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWM5OWU4OTEyOTYxN2QxNjM0ODk2Njc0M2UyNjQwZDMwOWU4ZTBmYWVhYjMxMTg2NjBmYWJjNGRhMGRlODRiMDQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.iQRStBhKqoSrZ9XkMZ8SWqjnIPj7Ca7puoq62mPcNNI)
-
상위 task로부터 아무런 속성도 상속받고 싶지 않을 때
-
context로부터 완전히 독립적임
-
unstructured task의 일종
-
시작된 범위에 수명이 묶이지 않음
-
시작된 범위의 attribute(actor, 우선순위 등)을 상속받지 않음
-
우선순위 등에 대해 기본값을 가지고 시작하지만 커스텀 매개변수를 넣어줄 수도 있음
-
캐싱하는 detached Task 예시
- priority 설정 가능
- thumbnail 실패해도 얘는 cancel 안 됨 -> 독립적인 실행
- 따라서 fetch 실패해도 일단 캐싱은 해놓고 싶은 목적으로 사용할 때 적절함
-
detached task와 지금까지 살펴본 요소들 조합 가능
-
detached task 안에 structured task 적용 가능
![Screenshot 2024-08-18 at 5 54 42 PM](https://private-user-images.githubusercontent.com/22342277/358900252-21f68eb5-e011-43a6-b4d0-8b1e53f039ef.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAyNTItMjFmNjhlYjUtZTAxMS00M2E2LWI0ZDAtOGIxZTUzZjAzOWVmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTc0MDYyNzM2N2Q0ODdhZWU5OWRkNjM5N2U3YzI0YjdiY2UxNDc1MmRkNGIwODgwOTNiNzU1Nzk3NGU3Nzc1NTYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.spklLAYa0IBXe2tj4YOpF3Evc_5oeQDAe2JS2QTL-dQ)
- 그러면 자동적으로 cancellation을 전파할 수 있고, priority를 하위 task들에게 전파할 수 있어 관리가 쉽다는 장점이 있음
![Screenshot 2024-08-18 at 5 57 57 PM](https://private-user-images.githubusercontent.com/22342277/358900266-20fae966-df5e-4f03-872d-5c8d3a4e8ac3.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2NzU4MzYsIm5iZiI6MTczOTY3NTUzNiwicGF0aCI6Ii8yMjM0MjI3Ny8zNTg5MDAyNjYtMjBmYWU5NjYtZGY1ZS00ZjAzLTg3MmQtNWM4ZDNhNGU4YWMzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDAzMTIxNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJjNTY3ZmI5ZGJiZjBlMGZiNTA1NGU1NDU4NDFlYjRkNjg1NDJhYzRiY2YxYjU4ZmU1NjUxMWY2NTBmZDgyY2EmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.Fz3a28nmwoHzCSyHIWqgTf4zsvRTq-WzbJS1CrOIpzQ)
고병학 | 권승용 | 김대황 | 김인환 | 유정주 | 윤동주 | 이준복 | 이창준 | 정종인 | 홍승현 |
---|---|---|---|---|---|---|---|---|---|
bengHak | ericKwon95 | qwerty3345 | loinsir | jeongju9216 | yoondj98 | junbok97 | SwiftyJunnos | chongin12 | WhiteHyun |