SwiftUI - TCA에서의 비동기 처리 이해하기

CodeCat·2024년 9월 10일

IOS SwiftUI TCA

목록 보기
18/20
post-thumbnail

안녕하세요 !

이번에는 TCA에서의 비동기 처리 이해하기라는 주제로 작성해보려 합니다

TCA의 send 함수의 관계, 그리고 비동기 작업의 결과를 안전하게 상태에 반영하는 방법에 대해 살펴볼 예정입니다

비동기 처리의 어려움

func doAsyncBar() async {
    var foo = ""
    Task {
        foo = "TASK"
    }
}

이 코드는 컴파일 에러를 발생시킵니다 왜 그럴까요?

변수 foo를 새로운 스레드(Task)에서 수정하는 작업입니다

하지만 foo 값이 언제 변경될지는 불확실한데요

이러한 문제는 동시성 이슈를 야기할 수 있습니다

해결 방안

상수 사용

func doAsyncBar() async {
    let foo = ""
    Task {
        print(foo)
    }
}

이 방법은 컴파일 에러를 해결하지만, 값을 수정할 수 없어요 ㅜㅜㅜ

Task의 결과 활용

func doAsyncBar() async {
    let foo = ""
    let result = Task {
        let task = "Task"
        return task + foo
    }
    
    print(await result.value)
}

이 방법은 Task 내에서 값을 안전하게 사용하고 결과를 반환할 수 있게 해줍니다

inout 파라미터 사용 시도

var foo = "_Foo"

func doAsyncBar(_ foo: inout String) async {
    let result = Task {
        let task = "Task"
        return task + foo
    }
  
    print(await result.value)
}

하지만 이 방법도 inout 파라미터를 비동기 context에서 사용할 수 없다는 에러를 발생시킵니다

TCA의 해결책: MainActor와 send

TCA는 이러한 문제를 MainActor와 send 함수를 통해 해결합니다 (저번 포스팅에서 살명 드렸죠?)

var foo = "_Foo"

func doAsyncBar(
    _ foo: inout String,
    mainCompletion: @escaping @MainActor (String) -> Void
) async {
    Task { [foo = foo] in
        let taskResult = "Task" + foo
        await mainCompletion(taskResult)
    }
}

Task {
    await doAsyncBar(&foo) { result in
        print("Result :", result)
        foo = result
        print("Foo :", foo)
    }
}

이 방식은 다음과 같은 이점을 제공합니다:

  1. 값을 안전하게 캡처하여 Task 내에서 사용할 수 있습니다
  2. 결과를 메인 스레드에서 처리할 수 있습니다
  3. 비동기 작업의 결과를 안전하게 상태에 반영할 수 있습니다

TCA의 .run 메서드

TCA는 이러한 패턴을 .run 메서드로 추상화하여 제공합니다:

case .requestButtonTapped:
    return .run { send in
        let fetchedImage = try await requestImages()
        await send(.requestResponse(fetchedImage))
    } catch: { error, send in
        print(error)
    }
    
case let .requestResponse(image):
    state.image = image
    return .none

TCA는 MainActor와 send 함수를 통해 비동기 작업의 결과를 안전하게 처리하고, 상태 업데이트를 메인 스레드에서 수행할 수 있게 해줍니다

이상으로 포스팅 마무리 하겠습니다.

.
.
.

감사합니다.

profile
코드와 고양이의 만남

0개의 댓글