728x90
반응형
안녕하세요~ 개발하는 윤기사입니다!!
최근 아주 큰 사건이 있었죠...!? 그래서 블로그에 글을 못쓰고 있었습니다^^
다시 포스팅하려고 이렇게 왔습니다!
오늘 포스팅할 내용은 Network에 관한 내용인데요!
1. URLSession
2. Decode Data
3. Fetch Method
이렇게 3가지에 대해 알아보겠습니다!
- URL Session -
- 데이터를 다운로드 혹은 업로드하는 등의 API를 제공해주는 클래스로 URL이 가리키는 Endpoint를 가지고 있다
- URLSession API를 통해 데이터를 어떻게 전송을 하고 어떻게 동작할지 정책을 설정할 수 있다.
- 간단하고 기본적인 요청인 경우 동작과 전송에 대한 정책이 기본적으로 설정되어 있는 Shared Session을 사용
- 별도 처리를 하기 위해서는 Session Configuration 객체를 통한 Session 생성 가능! -> URLSession을 통해 데이터를 다운로드 혹은 업로드할 때, URLSessionConfiguration으로 세부적인 동작과 정책 설정 가능!
- Github API를 이용해서 한 번 실습해보겠습니다!
import Foundation
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration)
let url = URL(string: "https://api.github.com/users/Yun-YeoJin")!
//session 생성 후 task 생성, URLSession을 통해 생성되는 개별요청이 task.
let task = session.dataTask(with: url) { data, response, error in
//HTTPURLResponse도 URLResponse 클래스의 서브 클래스.
guard let httpResponse = response as? HTTPURLResponse, (200..<300).contains(httpResponse.statusCode) else {
print("---> response \(response)")
return
}
guard let data = data else { return } //옵셔널값이라서
let result = String(data: data, encoding: .utf8)
print(result)
}
task.resume()
- Decode Data -
- Github API를 이용해 개발하는 윤기사 정보를 가져와보겠습니다.
- enum CodingKeys: String, CodingKey { } 를 이용하여 API 통신을 통해 받은 결과 값을 원하는 변수로 바꿔줄 수 있습니다.
- 커스텀 키가 필요할 때만 CodingKeys를 작성하면 됩니다.
// App Model -> JSON : 인코딩(Incoding)
// JSON -> App Model : 디코딩(Decoding)
import Foundation
struct GithubProfile: Codable {
let login: String
let avatarUrl: String
let htmlUrl: String
let followers: Int
let following: Int
enum CodingKeys: String, CodingKey { //매칭을 도와줄 수 있다!
case login
case avatarUrl = "avatar_url"
case htmlUrl = "html_url"
case followers
case following
}
}
// App Model -> JSON : 인코딩(Incoding)
// JSON -> App Model : 디코딩(Decoding)
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration)
let url = URL(string: "https://api.github.com/users/Yun-YeoJin")!
let task = session.dataTask(with: url) { data, response, error in
guard let httpResponse = response as? HTTPURLResponse, (200..<300).contains(httpResponse.statusCode) else {
print("---> response \(response)")
return
}
guard let data = data else { return }
//data -> GithubProfile 하고 싶다!
do {
let decoder = JSONDecoder()
let profile = try decoder.decode(GithubProfile.self, from: data)
print("ProFile : \(profile)")
} catch let error as NSError {
print("error : \(error)")
}
}
task.resume()
- Fetch Method -
- 이번엔 네트워크 예외처리를 통해서 코드를 작성해보겠습니다.
- 네트워크 오류 관련된 enum을 하나 만들고, GithubProfile을 담을 Struct를 하나 만듭니다.
- 그 후 API 통신을 하되 성공했을 때와 실패했을 때를 나누겠습니다.
import Foundation
enum NetworkError: Error {
case invalidRequest
case transportError(Error)
case responseError(statusCode: Int)
case noData
case decodingError(Error)
}
struct GithubProfile: Codable {
let login: String
let avatarUrl: String
let htmlUrl: String
let followers: Int
let following: Int
enum CodingKeys: String, CodingKey {
case login
case avatarUrl = "avatar_url"
case htmlUrl = "html_url"
case followers
case following
}
}
final class NetworkService {
let session: URLSession
init(configuration: URLSessionConfiguration) {
session = URLSession(configuration: configuration)
}
//Result<Success, Failure>
func fetchProfile(userName: String, completion: @escaping (Result<GithubProfile, Error>) -> Void) {
let url = URL(string: "https://api.github.com/users/\(userName)")!
let task = session.dataTask(with: url) { data, response, error in
if let error = error { //에러가 있다면
completion(.failure(NetworkError.transportError(error)))
return
}
if let httpResponse = response as? HTTPURLResponse, !(200..<300).contains(httpResponse.statusCode) {
completion(.failure(NetworkError.responseError(statusCode: httpResponse.statusCode)))
return
}
guard let data = data else {
completion(.failure(NetworkError.noData))
return
} //옵셔널값이라서
//data -> GithubProfile 하고 싶다!
do {
let decoder = JSONDecoder()
let profile = try decoder.decode(GithubProfile.self, from: data)
completion(.success(profile))
} catch let error as NSError {
completion(.failure(NetworkError.decodingError(error)))
}
}
task.resume()
}
}
// network 담당 NetworkService
// NetworkService를 이용한 네트워크 작업
let networkService = NetworkService(configuration: .default)
networkService.fetchProfile(userName: "Yun-YeoJin") { result in
switch result {
case.success(let profile):
print("ProFile: \(profile)") //성공했을 때는 profile
case .failure(let error):
print("ERROR: \(error)") //실패했을 때는 error
}
}
이상 오늘 포스팅은 여기서 마치겠습니다~
요새 날씨가 많이 추워졌는데 감기 조심하시고 건강 꼭 잘 챙기세요!!
윤기사는 오늘도 빡코딩하겠습니다~^^
728x90
반응형
'iOS_Swift 앱개발👍' 카테고리의 다른 글
[iOS_Swift] Delegate Pattern을 이용한 값 전달 _ 29 (0) | 2023.01.14 |
---|---|
[iOS_Swift] RxSwift를 이용한 로그인 화면 만들기 _ 28 (3) | 2022.11.06 |
[iOS_Swift] 터미널 & git 명령어 모음 _ 26 (30) | 2022.10.04 |
[iOS_Swift] TextField (,) 콤마 제거 후 숫자 계산 _ 25 (30) | 2022.10.03 |
[iOS_Swift] TextField 천의 자리마다 (,)콤마 찍기_ 24 (30) | 2022.10.03 |