강의

멘토링

로드맵

Inflearn brand logo image

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

개발자님의 프로필 이미지
개발자

작성한 질문수

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

Task(작업)과 self 사용 관련 및 캡처리스트의 weak self 사용 (5강)

5강 weak self 처리 관련

해결된 질문

작성

·

111

·

수정됨

1

안녕하세요! Swift Concurrency 강의 너무 잘 듣고 있습니다.

 

5강 weak self 처리 관련하여 질문이 있는데요.

 

Task 클로저의 경우 작업이 끝나는 즉시 내부 클로저가 소멸하기 때문에 클로저 내부에서 캡처된 참조도 해조되어 강한 순환 참조가 발생하지 않는다고 나와있는데, 이는 DispatchQueue에 전달하는 클로저에서도 마찬가지 아닌가요? DispatchQueue에 전달된 클로저도 작업이 완료되면 메모리에서 해제되는 것으로 알고 있어서, 약간의 혼란이 생겼습니다.

 

DispatchQueue.global().async {
    self.processData() // self를 강하게 캡처
}

// 클로저가 실행되는 동안 self가 메모리에 유지되며, 작업 완료 후 클로저가 해제되면 self도 참조카운트가 감소되는 것으로 알고 있습니다.

그렇다면 Task와 DispatchQueue의 차이점은 'self를 명시적으로 쓸 필요 없다/써야 한다' 뿐이지, 순환 참조 관련된 처리는 다르지 않지 않을까 하는 고민인데요. 뭔가 제가 잘못 이해한 부분이 있을 것 같습니다. 혹시 이 부분 설명 해주실 수 있으실까요?

 

더불어서 Task를 쓰면 순환 참조가 생길 가능성 자체도 없는 것인지도 궁금합니다.

 

감사합니다 😊

답변 2

1

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

아 네네 맞습니다.
제가 약간 설명에 혼란을 드린 것 같군요!ㅠㅠ

 

아주 정확하게는 Task의 경우 순환참조가 생길 수 있는 경우에도 self가 해제되기 때문에 강한 순환 참조가 발생하지 않는다고 보시면 될 것 같습니다. :)

 

단순하게 아래처럼 사용하면, DispatchQueue와 별반 다르지 않다고 보실 수도 있습니다.

Task {
    self.processData()
}

 

그런데, 공식문서의 예제처럼
https://developer.apple.com/documentation/swift/task

actor Worker {
    var work: Task<Void, Never>?
    var result: Work?

    //....

    func start() {
        work = Task {
            self.result = Work()
        }
    }
}


액터(클래스로 구현해도 상관없음)가 Task 클로저를 가리키고, 클로저에서도 self를 참조해서 (서로가 서로를 가리키는 상황이 발생하더라도) self가 (Task의 특성으로 인해) 메모리에서 해제가 되기 때문에 강환 순환 참조가 발생하지 않는 것입니다.

 

만약에 (서로가 서로를 가리키는) 비슷한 상황을 DispatchQueue로 생각해보면, 아래와 같은 경우는 [weak self]를 사용하지 않으면, 강한 순환 참조가 발생하겠죠 !

class Worker {
    var queue = DispatchQueue.global()

    //....

    func start() {
        queue.async {    // 반드시 [weak self]를 사용해야함
            self.processData()
        }
    }
}

 

따라서, "Task의 경우 순환참조가 생길 수 있는 경우에도 self가 해제되기 때문에 강한 순환 참조가 발생하지 않는다" 라고 보시면 될 것 같습니다.

 

 

감사합니다. :)

0

개발자님의 프로필 이미지
개발자
질문자

빠른 답변 감사합니다!! :)

개발자님의 프로필 이미지
개발자

작성한 질문수

질문하기