func fetchPhoto(url: URL, completionHandler: @escaping (UIImage?, Error?) -> Void) {
	let task = URLSession.shared.dataTask(with: url) { data, response, error in
		if let error = error {
				completionHandler(nil, error) // 아래에서는 DispatchQueue.main에 넣고 있는데, 여기서는 안 넣고 있다. 
				// return을 안하고 있다.
		}

		if let data = data, let httpResponse = response as? HTTPURLResponse,
				httpResponse.statusCode = 200 {
			DispatchQueue.main.async {
				completionHandler(UIImage(data: data), nil) // UIImage가 nil일 수 있다. 
			}
		} else {
			completionHandler(nil, DogsError.invalidServerResponse
		}
	}
	task.resume()
}
func fetchPhoto(url: URL) async throws -> UIImage {
	let (data, response) = try await URLSession.shared.data(from: url)

	guard let httpResponse = response as? HTTPURLResponse,
					httpResponse.statusCode == 200 else {
				throw DogsError.invalidServerResponse
		}

	guard let image = UIImage(data: data) else {
		throw DogsError.unsupportedImage
	}
	
	return image
}
func data(from url: URL) async throws -> (Data, URLResponse)
func data(from request: URLRequest) async throws -> (Data, URLResponse)

func upload(for request: URLRequest, from data: Data) async throws -> (Data, URLResponse)
func upload(for request: URLRequest, fromFile url: URL) async throws -> (Data, URLResponse)

// 다운로드 받은 파일을 자동으로 지우지 않는다. 수동으로 지워야 한다.
func download(from url: URL) async throws -> (URL, URLResponse)
func download(for request: URLRequest) async throws -> (URL, URLResponse)
func download(resumeFrom resumeData: Data) async throws -> (URL, URLResponse)
let handle = async {
	let (data1, response1) = try await URLSession.shared.data(from: url1)
	// ...
	let (data2, response2) = try await URLSession.shared.data(from: url2)
	// ...
}
func bytes(from url: URL) async throws -> (URLSession.AsyncBytes, URLResponse)
func bytes(for request: URLRequest) async throws -> (URLSession.AsyncBytes, URLResponse)

struct AsyncBytes: AsyncSequence {
	typealias Element = UInt8
}

// 예제

func onAppearHandler() async throws {
	let (bytes, response) = try await URLSession.shared.bytes(from: Self.eventStreamURL)
	guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
		throw DogsError.invalidServerResponse
	}

	for try await line in bytes.lines {
		let photoMetadata = try JSONDecoder().decode(PhotoMetadata.self, from: Data(line.utf8))
		await updateFavoriteCount(with: photoMetadata)
	}
}