SwiftConcurrency 4편 구조화 동시성

김재형·2024년 6월 16일
1
post-custom-banner

시작 하기에 앞서...

해당 글은 1편부터 이어지는 글임으로 꼭 처음부터 봐주시길 바랍니다.

goto

최초의 프로그래밍 언어 (어셈블리어) 에는 for, for-in, while, ifelse 등 과 같은
문법이 존재 하지 않았었습니다. if then goto 만 가능했었습니다.
Dijkstra ( 다익스트라 ) 는 goto는 해롭다. 라고 했었습니다.
goto 란 무엇이고, 왜 쓰지 말라고 했었을까요?

goto가 뭔데.

쉽게 생각해보죠.
코드가 아래방향으로 진행 하고 있었습니다.
그러다. 어느 특정 시점에 상단의 코드로 이동하고 싶었습니다.
저희는 Swift 언어 (객체 지향)를 사용하여서 크게 와 닿지 않겠지만
절차지향 언어인 C 언어로 생각을 해보죠

#include <stdio.h>

int main() {
    int count = 0;

start:
    printf("카운트: %d\n", count);
    count++;

    if (count < 5) {
        goto start;
    }

    printf("끄으읕\n");
    return 0;
}

C 언어를 통해 간단히 구현해 보았습니다.
카운트 값을 점차 1씩 증가 시킨후 5보다 작다면 다시 코드가 올라가는 구조이죠.
하지만 무엇이 문제라는 것일까요?
지금은 코드가 간단한 예시라 문제가 없겠지만 복잡한 코드라면 문제가 생길수 있습니다.
코드의 진행이 어떻게 되는지 알기 어려워 지기 때문이죠.

코드의 발전 - 구조화된 프로그래밍

위와 같은 문제를 해결하기 위해 점차 구조화가 된 프로그래밍 언어들이 등장합니다.
코드의 가독성과 유지 보수성을 높이기 위해 프로그램을 체계적으로 구성하기 시작 하였죠
순차적, 선택적, 반복적 인 구조를 구성하게 되는데 이는 각각 "코드가 아래로", "if, if-else", "for 등"이 해당됩니다.

WWDC 21 구조화된 동시성

Swift 에선?

예시를 통해 확인해 보도록 하죠

Completion Handler

import Foundation

func fetchData(url: URL, completion: @escaping (Data?, Error?) -> Void) {
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        completion(data, error)
    }
    task.resume()
}

let url = URL(string: "https://KingJaeHyung.com")!

fetchData(url: url) { data, error in
    if let error = error {
        print("Error: \(error)")
    } else if let data = data {
        if let json = try? JSONSerialization.jsonObject(with: data, options: []) {
            print("JSON: \(json)")
        }
    }
}

실제로 존재하진 않지만 저의 사이트에서 JSON 데이터를 출력하는 코드를 보겠습니다.
해당 함수를 잘생각해 본다면 코드의 흐름이 아래 방향으로 가다, Completion Handler 를 통해
다시 위로 올라가게 되는 구조 입니다. 다시말해, 함수 내부에서 해결하지 않고, 밖에서 작업이
이루어지는 구조가 되었죠.

Async / Await

import Foundation

func fetchData(url: URL) async throws -> Data {
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

func performAsyncTask() async {
    let url = URL(string: "https://KingJaeHyung.com")!
    do {
        let data = try await fetchData(url: url)
        if let json = try? JSONSerialization.jsonObject(with: data, options: []) {
            print("JSON: \(json)")
        }
    } catch {
        print("Error: \(error)")
    }
}

// 비동기 함수 호출
Task {
    await performAsyncTask()
}

자 이번엔 어떤가요?
코드의 진행이 다시 올라가나요?
awync, await 키워드를 통해 코드의 진행이 더욱 가독성 좋게 바뀌게 되었습니다.

순차적 바인딩 - Sequential Binding

비동기 작업을 순차적으로 수행하는 것을 말하는데, await 키워드를 통해,
각 비동기 작없이 완료 될때까지 기다린후 다음 작업으로 이어집니다.

import Foundation

func fetchData(url: URL) async throws -> Data {
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

func performSequentialTasks() async {
    let url1 = URL(string: "https://KingJaeHyung.com/1")!
    let url2 = URL(string: "https://KingJaeHyung.com/2")!
    
    do {
        let data1 = try await fetchData(url: url1)
        print("Data 1: \(data1)")
        
        let data2 = try await fetchData(url: url2)
        print("Data 2: \(data2)")
    } catch {
        print("Error: \(error)")
    }
}

동시적 바인딩 - Concurrent Binding

Async - let Tasks

Async - let 바인딩은 여러 비동기 작업을 동시에 시작한후, 모든 작업이 완료 될때 까지 기다리지 않습니다.
각 작업의 결과를 독립적으로 사용할수 있죠. 즉 병렬수행 작업에 좋습니다.

import Foundation

func fetchData(url: URL) async throws -> Data {
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

func performTasksWithStructuredConcurrency() async {
    let url1 = URL(string: "https://KingJaeHyung.com/1")!
    let url2 = URL(string: "https://KingJaeHyung.com/2")!
    
    do {
    // 해당 부분 주목
        async let data1 = fetchData(url: url1)
    // 해당 부분 주목
        async let data2 = fetchData(url: url2)
        
        let result1 = try await data1
        let result2 = try await data2
        
        print("Data 1: \(result1)")
        print("Data 2: \(result2)")
    } catch {
        print("Error: \(error)")
    }
}

다시 정리하면 동시적 바인딩은
여러 비동기 적업을 동시에 시작하고, 각 작업이 완료 되기를 기다립니다.
다만, 동시적임으로, 코드의 복잡성이 증가할 가능성이 있습니다.

글을 마치며...

분량을 어느정도로 할지 고민을 많이 하였었습니다.
뒤에 더 많은 내용이 있으나, 너무 많은 내용이 담기면 어지러울 것 같아 이부분 까지 정리해 보았는데요.
다음 편에는 구조화 동시성에 이어, 구조화된 Task 보장하는것은? + Group Task 에대해서 알아 보도록 하겠습니다. 긴글 읽어 주셔서 감사합니다.

profile
IOS 개발자 새싹이
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 6월 19일

다음편 기대하고 있는데 언제쯤 나올까요 ㅠㅠㅠ

답글 달기