강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

sujinnaljin님의 프로필 이미지
sujinnaljin

작성한 질문수

앨런 Swift Concurrency for Swift 6 (Part-2)

20강 Task 내부에서 nonisolated async 호출 예제 질문드립니다

해결된 질문

작성

·

7

0

18분 55초 쯤 예시를 보여주시면서

/// 2) (액터 외부) 동기 코드가 (일반) 비동기 코드에서 불려지면.. 어떤 (컨텍스트에 해당하는) 작업(Task) 내부에서 실행됨 ===> Task 격리
​
func readAny(with books: [Book]) async {
    if let book = books.randomElement() {
        readBook(with: book)
    }
}
​
Task {
    let account = LibraryAccount(idNumber: 1)     /// 액터
    let books = await account.booksOnLoan         /// 액터내부의 (상태)값 가져오기  (Sendable타입)
    
    await readAny(with: books)                    /// 액터 외부에서 실행  (일반적으로 이런 구현은 옳지 않음)
}

위와 같은 코드에서 Task 가 3번 스레드에서 돌아가고 있었다고 치면, account.booksOnLoan 을 가져오는건 2번 스레드로 갈 수 있다고 쳐도, await readAny(with:) 는 다시 Task 와 동일한 3번 스레드에서 돌아가게 될거다! 라고 말씀을 주셨는데요

사실 nonisolated async func 인 readAny 를 await 로 호출을 하는 순간, 해당 함수는 Task 의 스레드는 무관한게 아무 스레드에서나 돌아갈 수 있다고 생각을 했습니다 (실제로 Task 를 mainActor context 로 두고 해당 코드를 돌려봐도 readyAny 는 main 에서 돌아가지 않았구여!)

이해 편의상 돌려서 설명을 주시건가??? 생각이 들지만 혹시 정확히 어떤 의미로 요렇게 말씀을 주신건지 궁금합니다~

감사합니다

저장

답변 2

1

앨런(Allen)님의 프로필 이미지
앨런(Allen)
지식공유자

아 네네, 해당 내용에서느 직관적인 이해를 위해서..
편의상 그렇게 설명드리고 있는 것 뿐입니다 !


비동기(async) 함수로 구현하시면,
백그라운드 쓰레드 어디에서도 실행될 수 있습니다.


Task가 3번 쓰레드라고 가정하고, LibraryAccount 액터가 2번 쓰레드라고 가정하면,
(정확하게 보자면) 비동기 readAny 함수의 경우, 비동기 함수이기 때문에 백그라운드 쓰레드(예를 들어, 4번, 5번, 6번 등) 어떤 곳에서도 실행될 수 있습니다.
(async 함수의 특징)

 

그래서 await키워드가 붙여서 실행시켜야 하는 것이기도 하고요.
(뭐 예를 들자면, readAny 비동기 함수가 4번에서 실행되었다가 3번 쓰레드에서는 그 일이 마칠때까지 기다리는 것이겠죠.)

해당 내용에서 중요한 포인트는 2번 쓰레드(액터 내부)에서 실행되지 않는다는 내용을 설명드리기 위한 내용이라 최대한 직관적인 이해를 위해 (이미 수업의 앞의 내용들은 이해하시고 계시다는 전제 아래) 설명드리고 있다는 점을 이해 부탁드립니다. :)

sujinnaljin님의 프로필 이미지
sujinnaljin
질문자

쪼오금 더 정확하게 말하면 아래 부분은

readAny 비동기 함수가 4번에서 실행되었다가 3번 쓰레드에서는 그 일이 마칠때까지 기다리는 것이겠죠.

3번 쓰레드에서 계속 readAny 를 끝날때까지 기다린다기 보다는, await readyAny 를 만난 순간 3번 쓰레드의 제어권은 시스템에게 돌아가서 해당 스레드에서는 다른 작업이 실행될 수 있구, readyAny 가 끝나는 순간 다음 코드가 있다면 적당한 스레드에서 (Task 가 메인 스레드에 격리되어있다면 해당 스레드에서) 해당 작업을 재개하는게.. 맞겠죠? 👀 그 적당한 스레드는 readyAny 가 실행되던 4번 스레드로 유지될 수도 있구여

편의상 이해하기 쉽게 직관적으로 풀어서 설명해주시는걸 알고 저 또한 그 부분을 좋아하지만, 제가 이해하고 있는 부분이 정확하지 않다보니, 말씀주시는 내용 중 어디까지가 편의상 설명해주시는거고, 어디까지가 제가 진짜로 잘못 이해하고 있는걸지 판단하기가 어려운것 같습니다

그래서 앞으로도 이런 비슷한 (ex. 실제로는 ~~ 처럼 동작하는게 맞을까요?) 질문들을 드릴 수 있을것 같아 미리 이해해주시면 감사하겠습니다~

감사합니다

앨런(Allen)님의 프로필 이미지
앨런(Allen)
지식공유자

네 정확하게 맞습니다.
readyAny 가 끝나는 순간, 다른 쓰레드에서 재개 될 수 있다는 것이 "아주 정확하게 " 맞습니다. (교재 29페이지에서 정확하게 그려서 말씀드리고 있고, 그렇게 이해하면.. 설명이 너무 복잡해 지기 때문에.. 계속 편의상 뒤에서 그렇게 하나의 쓰레드로 가정한다고 말씀드리고 있는 것이고요ㅠㅠ)

sujinnaljin님의 프로필 이미지
sujinnaljin
질문자

확인 감사합니다~~!

0

안녕하세요, 인프런 AI 인턴입니다. sujinnaljin님께서 Swift Concurrency에서 Task와 async 함수 호출 관련해서 질문을 주셨네요.

비동기 함수 호출 시 스레드 동작 이해

비동기 함수(async)가 다른 스레드에서 실행될 수 있는 것은 사실입니다. 특히나 Swift의 비동기 모델에서는, 특정 스레드에 고정되지 않고 관련 스케줄에 따라 다른 스레드에서 실행이 가능합니다. 이는 await 표현식 자체가 작업의 중단과 재개를 가능하게 만드는데요, 이로 인해 Task 내의 await 호출은 그 자체로 스레드 전환이 가능하다는 것을 의미합니다.

Task와 스레드

  • Task 내에서 비동기 함수(async) 호출 시, 그 함수는 일반적으로 현재 컨텍스트에 맞게 스케줄되거나, 필요 시 다른 가용 스레드로 전환될 수 있습니다.
  • await 키워드는 해당 비동기 작업이 완료될 때까지 기다리고, 그 정확한 스레드에서 재개될 것이라는 보장은 없습니다.

readAny 함수 호출

readAny(with:) 라는 비동기 함수는 await에 의해 호출되므로, 비동기 함수가 완료된 후 Task의 반복 시점에서 다른 스레드에서 계속될 수 있습니다.

의미 명확화

지식공유자님께서 주신 설명은 특정 스레드에서 실행될 것이라고 단정 짓기보다는, Task 실행 컨텍스트 자체에서의 일반적인 흐름을 예시로 들며 설명하셨을 가능성이 큽니다. Swift의 멀티 스레드 환경에서의 유연성은 스레드 관리나 관리 전략에 의해 구제되므로, 특정 상황에서의 스레드 동작은 환경 설정 및 코드 구조에 따라 달라질 수 있습니다.

참고 및 권장 사항

  • 비동기 코드를 사용할 때, 특정 스레드에서의 실행을 필요로 하는 작업이라면 MainActor 등을 명시적으로 지정하는 것을 권장드립니다.
  • Swift Concurrency에 관해 더 심도 깊은 이해를 원하신다면, Swift 공식 문서 를 참고하세요.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

sujinnaljin님의 프로필 이미지
sujinnaljin

작성한 질문수

질문하기