비동기식/대기 동작 - 비동기 코드를 작성하는 새로운 방법

Async/await 메커니즘은 새로운 비동기 코드를 작성하는 방법으로 전통적으로 완성 처리 프로그램(클로즈업이라고 부른다)을 사용하여 비동기 코드를 작성한다.비동기 함수는 비동기 코드를 동기 코드처럼 작성할 수 있습니다.Swift 5.5 릴리즈에서는 데모 목적으로 Xcode 13 beta를 사용했습니다.

비동기 코드를 작성하는 새로운 방법


async/await가 해결할 수 있는 다섯 가지 주요 문제는 다음과 같다.
  • 마지막 피라미드
  • 오류 처리 향상
  • 비동기 함수의 조건 집행
  • 잊어버리거나 잘못된 콜백
  • 어설픈 콜백 API로 인한 동기화 API의 설계 및 성능 문제 제거
  • Async await은 비동기식과 병렬 함수를 순서대로 실행하는 메커니즘을 제공합니다. 이것은 코드를 읽기, 유지보수, 확장하기 쉽게 하는 데 도움이 됩니다. 이것은 software development에서 매우 중요한 매개 변수입니다.

    비동기식/대기 및 프로세서 완료


    우선, 우리는 전통적으로 완성 처리 프로그램 작성 함수를 어떻게 사용하는지 보여 드리겠습니다.모든 사람이 이런 방법을 잘 안다.
    오해하지 마라. 이것은 처리 프로그램을 완성하여 함수를 작성하는 좋은 방법이다.여러 해 동안 우리는 줄곧 이렇게 해 왔다projects.Swift 코드에서, 완성 처리 프로그램은 일반적으로 함수가 되돌아온 후에 값을 돌려보낼 수 있도록 하는 데 사용된다.
    그럼에도 불구하고, 스wift 컴파일러는 코드에 오류가 들어왔는지 이상한 상황을 확인하기가 쉽지 않다.
    더 간결한 코드를 위해 NetworkManager라는 새 Swift 파일을 만들었습니다.이 서류에서, 우리는 우리의 요구를 처리하고 있다.우리의 사용자는name, 이메일,username의 구조입니다.
    struct User: Codable {
        let name: String
        let email: String
        let username: String
    }
    
    // MARK: fetch users with completion handler
    func fetchUsersFirstExample(completion: @escaping (Result<[User], NetworkingError>) -> Void) {
    
        let usersURL = URL(string: Constants.url)
    
        guard let url = usersURL else {
    
            completion(.failure(.invalidURL))
            return
        }
    
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            if let _ = error {
                completion(.failure(.unableToComplete))
            }
    
            guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
                completion(.failure(.invalidResponse))
                return
            }
    
            guard let data = data else {
                completion(.failure(.invalidData))
                return
            }
    
            do {
                let users = try JSONDecoder().decode([User].self, from: data)
                completion(.success(users))
            } catch {
                completion(.failure(.invalidData))
            }
        }
        task.resume()
    }
    
    보시다시피 이곳에는 많은 일들이 일어났다.디버깅하기는 매우 어렵다. 사용자 데이터만 얻는 데 있어서 많은 오류 처리가 있었고, 우리는 결국 많은 코드를 얻었다.대부분의 프로그래머들은 프로젝트에 두 개의 이런 코드를 작성해야 하는데, 이것은 매우 중복되고 보기 흉하게 변할 것이다.
    ViewController에서swift 파일에서, 우리는 하나의 테이블 보기에 데이터를 표시하기로 결정했기 때문에, 우리는 테이블 보기를 만들고 그 데이터 원본에 부합하도록 만들었다.일단 우리가 이 함수를 호출하기로 결정하면, 그것은 다음과 같다.
    //MARK: 1. example -> with completion handlers
    private var users = [User]()
    ​
    private func getUsersFirstExample() {
        NetworkManager.shared.fetchUsersFirstExample { [weak self] result in
            guard let weakself = self else { return }
    
            switch result {
            case .success(let users):
                DispatchQueue.main.async {
                    weakself.users = users
                    weakself.tableView.reloadData()
                }
            case .failure(let error):
                print(error)
            }
        }
    }
    

    비동기 함수 정의 및 호출


    다른 한편, 다음은 async/await를 사용하여 함수를 작성하는 방법으로 상술한 예시의 모든 조작을 완성할 수 있다.
    //MARK: fetch users with async/await using Result type
    func fetchUsersSecondExample() async -> Result<[User], NetworkingError> {
        let usersURL = URL(string: Constants.url)
    
        guard let url = usersURL else {
            return .failure(.invalidURL)
        }
    
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let users = try JSONDecoder().decode([User].self, from: data)
    
            return .success(users)
        }
        catch {
            return .failure(.invalidData)
        }
    }
    
    비동기 함수는 실행하는 도중에 멈출 수 있는 특수한 함수이다.이것은 동기화 함수와 반대로, 동기화 함수는 완성될 때까지 운행하거나, 오류를 던지거나, 영원히 돌아오지 않는다.
    우리는 async와 await 두 개의 키워드를 사용합니다.
    우리는 async 키워드를 사용하여 컴파일러에게 코드가 언제 비동기적인지 알려 줍니다.wait 키워드를 사용하면 컴파일러에게 데이터나 오류가 돌아올 때까지 일시 정지 함수를 선택할 수 있음을 알려 줍니다.C# 및 Javascript와 같은 다른 언어와 같이 함수의 스레드를 잠금 해제할 수 있는 위치를 나타냅니다.
    URLSession과 같은 Swift API도 비동기적입니다.
    그러나 우리는 비동기적인 상하문(예를 들어 UIKit 기반 보기 컨트롤러)에서 비동기적인 표시가 있는 함수를 어떻게 호출합니까?
    우리가 해야 할 일은 호출을 비동기 클립에 포장하는 것이다. 이것은 반대로 임무를 만들 것이다. 우리는 그 중에서 비동기 호출을 실행할 수 있다. 아래와 같다.
    //MARK: 2. example -> async/await with Result type
    private func getUsersSecondExample() {
        async {
            let result = await NetworkManager.shared.fetchUsersSecondExample()
    
            switch result {
            case .success(let users):
                DispatchQueue.main.async {
                    self.users = users
                    self.tableView.reloadData()
                }
            case .failure(let error):
                print(error)
            }
        }
    }
    
    결과 유형은 Swift 5.0에 도입되었으며 이 솔루션의 이점은 완료 프로세스를 개선하는 것입니다.
    물론 Swift 5.5에 async/await가 도입되었기 때문에 그것들은 그다지 중요하지 않게 변했다.
    그러나 그것은 결코 쓸모가 없는 것이 아니다. 왜냐하면 그것은 여전히 결과를 저장하는 가장 좋은 방법이기 때문이다.
    다음은 결과 유형을 사용하지 않고 async/await를 사용하는 또 다른 예입니다. 이것은 더욱 간결한 방법입니다.
    //MARK: fetch users with async/await third example, without Result type
    func fetchUsersThirdExample() async throws -> [User]{
        let usersURL = URL(string: Constants.url)
        guard let url = usersURL else { return [] }
        let (data, _) = try await URLSession.shared.data(from: url)
        let users = try JSONDecoder().decode([User].self, from: data)
        return users
    }
    
    ViewController에서 비동기 함수를 호출합니다.swift 파일:
    override func viewDidLoad() {
        super.viewDidLoad()
        configureTableView()
        async {
            let users = await getUsersThirdExample()
            guard let users = users else { return }
            self.users = users
            self.tableView.reloadData()
        }
    }
    ​
    //MARK: 3. example -> async/await without Result type
    private func getUsersThirdExample() async -> [User]? {
        do {
            let result = try await NetworkManager.shared.fetchUsersThirdExample()
            return result
        } catch {
            // handle errors
        }
        return nil
    }
    
    상술한 예시에서 우리가 도,try,catch에서 Swift의 기본 오류 처리를 사용할 수 있는 가장 좋은 점이 하나 더 있다. 비동기 호출을 실행할 때도 마찬가지다.
    두 가지 예에서 보듯이 보존 주기를 피하기 위해 약한 셀프 캡처가 없고, 주 라인에서 UI를 업데이트할 필요가 없습니다. 왜냐하면 이 문제를 처리하기 위해 주 참여자 (@mainacctor) 가 있기 때문입니다. (Swift의 새로운 병렬 모드를 사용할 때만 주 참여자에 접근할 수 있습니다.)
    봐라, 이것은 우리의 결과다.

    결론


    Async/await는 Swift 병렬 옵션의 일부분일 뿐입니다.애플의 SDK는 그것들을 대량으로 사용하기 시작했다.이것은 Swift로 비동기 코드를 작성하는 새로운 방법을 제공했다.유일한 단점은 오래된 운영체제 버전과 호환되지 않는다는 것이다. 우리는 여전히 async/await를 사용하지 않은 다른 코드와 상호작용을 해야 한다.이 문서는 Swift의 비동기식 프로그래밍을 이해하는 데 도움이 되었으면 합니다.
    이 모델에 대한 정보나 Swift concurrency가 도입한 모든 정보를 알고 싶다면 애플의 공식 사이트를 방문해 문서를 읽어 보세요.또한 다음과 같은 유용한 링크를 볼 수 있습니다.
  • Use async/await with URLSession
  • Meet async/await in Swift
  • Swift Evolution Proposal - Async/await (GitHub)

  • Swift Programming language - Concurrency
  • 소스 코드에 관심이 있으면 my GitHub account를 방문하십시오.

    좋은 웹페이지 즐겨찾기