URLSession와 API를 활용해 날씨 데이터를 받아와 보여주는 앱의 주요 기능들을 구현해보았다.
로컬 환경에서 데이터를 스스로 넣고, 그걸 사용하는 단계에서 외부에서 데이터를 받아오는 단계가 되다 보니까 해야 할 작업도 늘어나고, 코드도 어려워져서 헷갈리는 부분이 많았다..
// 서버 데이터를 불러오는 메서드 private func fetchData<T: Decodable>(url: URL, completion: @escaping (T?) -> Void) { let session = URLSession(configuration: .default) session.dataTask(with: URLRequest(url: url)) { data, response, error in guard let data = data, error == nil else { print("데이터 로드 실패") completion(nil) return } // http status code 성공 범위. let successRange = 200..<300 if let response = response as? HTTPURLResponse, successRange.contains(response.statusCode) { guard let decodedData = try? JSONDecoder().decode(T.self, from: data) else { print("JSON 디코딩 실패") completion(nil) return } completion(decodedData) } else { print("응답 오류") completion(nil) } }.resume() } // 서버에서 현재 날씨 데이터를 불러오는 메서드 private func fetchCurrentWeatherData() { var urlComponents = URLComponents(string: "https://api.openweathermap.org/data/2.5/weather") urlComponents?.queryItems = self.urlQueryItems guard let url = urlComponents?.url else { print("잘못된 URL") return } fetchData(url: url) { [weak self] (result: CurrentWeatherResult?) in guard let self, let result else { return } // UI 작업은 메인 쓰레드에서 작업 DispatchQueue.main.async { self.tempLabel.text = "\(Int(result.main.temp))°C" self.tempMinLabel.text = "최소: \(Int(result.main.temp_min))°C" self.tempMaxLabel.text = "최고: \(Int(result.main.temp_max))°C" } guard let imageUrl = URL(string: "https://openweathermap.org/img/wn/\(result.weather[0].icon)@2x.png") else { return } // image 를 로드하는 작업은 백그라운드 쓰레드 작업 if let data = try? Data(contentsOf: imageUrl) { if let image = UIImage(data: data) { // 이미지뷰에 이미지를 그리는 작업은 UI 작업이기 때문에 다시 메인 쓰레드에서 작업. DispatchQueue.main.async { self.imageView.image = image } } } } } // 서버에서 5일 간 날씨 예보 데이터를 불러오는 메서드 private func fetchForecastData() { var urlComponents = URLComponents(string: "https://api.openweathermap.org/data/2.5/forecast") urlComponents?.queryItems = self.urlQueryItems guard let url = urlComponents?.url else { print("잘못된 URL") return } fetchData(url: url) { [weak self] (result: ForecastWeatherResult?) in guard let self, let result else { return } // result 콘솔에 찍어보기 for forecastWeather in result.list { print("\(forecastWeather.main)\n\(forecastWeather.dtTxt)\n\n") } // UI 작업은 메인 쓰레드에서 DispatchQueue.main.async { self.dataSource = result.list self.tableView.reloadData() } } }이게 주요 함수들인데.. 뭐가 뭔지 잘 몰라서 강의도 두번 돌려보고 따라 쳐보기도 두번 했지만 여전히 감이 잘 오진 않는다.
어떤 흐름인지는 대강 이해가 가는데 사용되는 메서드들이나 제너럴,옵셔널,타입캐스팅이 난무하는 코드가 날 어지럽게 만든다..
더 많이 보고 코드를 하나씩 뜯어서 무슨 뜻인지 이해해 보자.. 🤯
갈수록 새로운 것들이 나와 어려워지는 것 같지만 또 배우는 재미가 있어서 마냥 싫지만은 않다.
이 코드들 씹어먹기..