Swift async/await를 적용해보자

윤지하·2025년 9월 2일
0

swift

목록 보기
5/9

오늘은 Swift Concurrency를 공부하기 위해 진행하던 사이드 프로젝트에 async/await를 적용하려고 했어요. 이런 방식으로 하면 된다고 해서 한번 해 봤는데...

💡 URLSession 튜플 구조분해 기본 지식

먼저 URLSession.shared.data(for:) 메서드는 튜플 (Data, URLResponse)를 반환해요:

let (data, response) = try await URLSession.shared.data(for: request)
//    ↑       ↑
//   실제     응답정보
//   데이터   (상태코드 등)

전송 성공/실패만 확인하면 되는 경우, 데이터는 사용하지 않으므로:

let (_, response) = try await URLSession.shared.data(for: request)
//    ↑
//   언더스코어 = "이 값은 사용하지 않겠다"

🚫 작동하지 않던 코드

func sendGossip(_ content: String) async throws {
    let url = URL(string: "http://localhost:3000/api/gossip")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let body = [
        "content": content,
        "deviceId": deviceId
    ]
    
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: body)
    } catch {
        print("❌ JSON 직렬화 오류: \(error)")
        return
    }
    
    let (_, response) = try await URLSession.shared.data(for: request)
    
    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        throw URLError(.badServerResponse)
    }
    
    self.dailyUsage += 1
    print("✅ 뒷담화 전송 완료")
}
Button("전송") {
    Task {
       try await gossipManager.sendGossip(newMessage)
    }
    isComposing = false
    newMessage = ""
}

✅ 해결된 코드

Button("전송") {
    Task {
        do {
            try await gossipManager.sendGossip(newMessage)
            print("✅ 성공!")
            isComposing = false
            newMessage = ""
        } catch {
            print("❌ 에러: \(error)")
        }
    }
}

또는 더 간단하게:

Button("전송") {
    Task {
        try await gossipManager.sendGossip(newMessage)
        isComposing = false
        newMessage = ""
    }
}

🔍 문제의 원인

실행 순서의 차이

문제 있던 버전:

  1. Task { } 시작 (백그라운드에서 비동기 실행)
  2. isComposing = false 즉시 실행 ⚡️
  3. newMessage = "" 즉시 실행 ⚡️
  4. 나중에 sendGossip 완료

해결된 버전:

  1. Task { } 시작
  2. sendGossip 완료까지 대기
  3. 성공하면 isComposing = false 실행
  4. 성공하면 newMessage = "" 실행

💡 핵심 교훈

위치실행 시점특징
Task 외부즉시 실행Task 완료를 기다리지 않음
Task 내부await 완료 후순차 실행 보장

결론: UI 상태 변경 코드는 Task 내부에 넣어서 비동기 작업 완료 후에 실행되도록 해야 함!

profile
성장하고 싶은 개발자

0개의 댓글