Troubleshooting - Capture of 'completion' with non-sendable type '(RegisterResult?) -> Void' in a @Sendable closure 경고
Troubleshooting - Capture of 'completion' with non-sendable type '(RegisterResult?) -> Void' in a @Sendable closure 경고
에러
URLSession을 통해 네트워킹을 처리하는 것을 공부하던 중 아래와 같은 경고가 나타남.
원인
구현했던 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
final class AuthService{
let session = URLSession.shared
func fetchRegister(data: RegisterRequest, completion: @escaping (RegisterResult?) -> Void){
var request = URLRequest(url: URL(string: "http://localhost:9000/api/v1/auth/register")!)
let body = try? JSONEncoder().encode(data)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = body
let task = session.dataTask(with: request) { data, response, error in
if let error = error{
completion(nil)
return
}
if let data = data{
guard let result = try? JSONDecoder().decode(ResponseWrapper<RegisterResult>.self, from: data) else{
completion(nil)
return
}
completion(result.result)
}
}
task.resume()
}
}
dataTask 메서드는 비동기적으로 실행되는데, 이것은 메인 쓰레드가 아닌 백그라운드 쓰레드가 접근할 수 있고 여러 쓰레드가 동시에 접근할 수도 있다는 뜻임.
이런 이유 때문에 매개 변수로 받는 completionHandler는 자동으로 Swift 컴파일러에서 @Sendable 클로저로 간주함.
@Sendable클로저란 여러 스레드나 동시성 컨텍스트에서 안전하게 공유되거나 접근될 수 있는 타입에 클로저를 뜻함.
@escaping이 붙어 있는 completion은 @Sendable로 처리되지 않음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let task = session.dataTask(with: request) { data, response, error in
if let error = error {
completion(nil)
return
}
if let data = data {
guard let result = try? JSONDecoder().decode(ResponseWrapper<RegisterResult>.self, from: data) else {
completion(nil)
return
}
completion(result.result)
}
}
dataTask의 @Sendable로 간주되는 클로저 내부에서 escaping 타입의 클로저를 호출하고 있음.
이때, 컴파일러는 여러 쓰레드에서 호출될 수 있는 dataTask 메서드에서 Thread-safe 하지 않은 completion 클로저를 호출하는 것에 경고를 하는 것임.
This post is licensed under CC BY 4.0 by the author.
