[ URLSession ] ํฌ์ผ๋ชฌ API๋ก ์๋ฒ์์ ์ด๋ฏธ์ง ๋ฐ์ดํฐ ๋ฐ์์ค๋ ํ๋ฆ ์ฐพ๊ธฐ
1. URL ์์ฑ ๋ฐ ๊ฒ์ฆ
URL(string:) ๋ฉ์๋๋ฅผ ์ฌ์ฉํด URL ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ ํจ์ฑ์ ๊ฒ์ฆํ๋ค.
guard let url = URL(string: "https://example.com/api") else {
print("Invalid URL")
return
}
2. URLRequest ๊ฐ์ฒด ์์ฑ (์ต์ )
๊ธฐ๋ณธ GET ์์ฒญ์ URL ๊ฐ์ฒด๋ก ๋ฐ๋ก ์์ฑํ ์ ์์ง๋ง, HTTP ๋ฉ์๋ ๋ณ๊ฒฝ์ด๋ ํค๋ ์ค์ ์ด ํ์ํ๋ค๋ฉด URLRequest ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
var request = URLRequest(url: url)
request.httpMethod = "GET" // ๊ธฐ๋ณธ๊ฐ์ GET, ํ์์ ๋ฐ๋ผ ๋ณ๊ฒฝ ๊ฐ๋ฅ
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
3. URLSession ๊ฐ์ฒด ์์ฑ
์ ํ์ด ์ ๊ณตํ๋ ๊ธฐ๋ณธ ์ธ์
์์ฑ, ์ผ๋ฐ์ ์ธ ์์ฒญ์ URLSession.shared(Singleton Session)์ ์ฌ์ฉํ๊ณ
ํ์์ ๋ฐ๋ผ ์์ฑ์๋ฅผ ํตํ ์ปค์คํ ์ค์ ์ ์ฌ์ฉํด URLSessionConfiguration ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
// ๊ธฐ๋ณธ ์ค์ -> ์ปค์คํ
๋ถ๊ฐ, ์๋ต์ ํด๋ก์ ํํ๋ก ์ ๋ฌ, ๋ฐฑ๊ทธ๋ผ์ด๋ ํํ ์ฒ๋ฆฌ ๋ถ๊ฐ
let session = URLSession.shared
// ์ปค์คํ
์ค์
let session = URLSession(configuration: .default)
// default : shared์ ์ ์ฌํ๋ ์ปค์คํ
๊ฐ๋ฅ, ์๋ต์ ํด๋ก์ ๋๋ Delegate ํํ๋ก ์ ๋ฌ
// ephemeral : ์ ๋ณด๋ฅผ ํ๋ฐ์ํค๊ณ ์ถ์ ๋
// background : ์ฑ์ ์ฐ๊ณ ์์ง ์์ ๋ ์ด๋ค ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ์ถ์ ๋ ์ฌ์ฉ (ex. ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฌ์)
4. Data Task ์์ฑ ๋ฐ ์์ : ๋คํธ์ํฌ ์์ฒญ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ฏ๋ก ํด๋ก์ ๋ฅผ ์ฌ์ฉํด ์๋ต์ ์ฒ๋ฆฌํ๋ค.
dataTask(with: completionHandler:) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ ์์ฒญ์ ์ํํ๊ณ , ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌ
๋คํธ์ํน์ ํ๋ ์ฝ๋๋ค์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํด์ผํ๋ ์ด์ ๋ CPU์ ๋ถํ๋ฅผ ์ผ์ผํค๋ ์์ ์ผ๋ก
๋ฉ์ธ ์ค๋ ๋์์ ์คํ ์ํค๋ฉด ์ฑ์ด ๋ฒ๋ฒ ๊ฑฐ๋ฆด ์ ์๋ค.
๊ทธ๋์ .resume()์ด ์คํ๋ ๋ค์์ .shared.dataTask ์ฝ๋๋ค์ด ์คํ๋๋ค.
๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ๋์ํ๊ธฐ ๋๋ฌธ์ UI๊ด๋ จ ์ฒ๋ฆฌ๋ ๋ฉ์ธ ์ค๋ ๋๋ก ์ ํํด์ค์ผ ํ๋ค.
๊ตฌํ๋ถ์์ ๋ฉ์ธ ์ค๋ ๋๋ก ๋ฐ๊ฟ์ฃผ๋ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋ฐฉ๋ฒ๋ ์๋ค. ๐
let url = URL(string: "")!
URLSession.shared.dataTask(with: url) { data, response, error in
// ์์ ๊ตฌํ๋ถ์์ ๋ฉ์ธ ์ค๋ ๋๋ก ๋ฐ๊ฟ์ฃผ๋ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๊ธฐ๋ ํ๋ค.
DispatchQueue.main.async {
guard error == nil else {
completion(nil, .failedRequest)
return
}
guard let data = data else {
completion(nil, .noData)
return
}
// HTTPURLResponse๋ก ํ์
์บ์คํ
// URLResponse > HTTPURLResponse๋ ์์ ๊ด๊ณ
guard let response = response as? HTTPURLResponse else {
completion(nil, .invaildResponse)
return
}
guard response.statusCode == 200 else {
completion(nil, .failedRequest)
return
}
do {
let result = try JSONDecoder().decode(Lotto.self, from: data)
completion(result, nil)
} catch {
completion(nil, .invaildData)
}
}
}.resume()
์ฝ๋ ์ถ์ฒ : https://taekki-dev.tistory.com/115
๐ ํด๋ก์ (data, response, error) in
let task = session.dataTask(with: request) { data, response, error in
// ์๋ฌ ์ฒ๋ฆฌ
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
// ์๋ต ์ํ ์ฝ๋ ํ์ธ
if let httpResponse = response as? HTTPURLResponse {
print("Status code: \(httpResponse.statusCode)")
guard (200...299).contains(httpResponse.statusCode) else {
print("Request failed with status code: \(httpResponse.statusCode)")
return
}
}
// ๋ฐ์ดํฐ ํ์ธ
guard let data = data else {
print("No data received")
return
}
// ๋ฐ์ดํฐ ์ฒ๋ฆฌ (์: JSON ๋์ฝ๋ฉ)
// JSON ํ์ฑ : ์๋ฒ์์ ๋ฐ์ JSON ๋ฐ์ดํฐ๋ฅผ JSONDecoder๋ฅผ ์ฌ์ฉํ์ฌ Swift ๊ตฌ์กฐ์ฒด๋ก ๋์ฝ๋ฉ(๋ณํ)
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print("JSON response: \(json)")
} catch {
print("JSON decoding error: \(error.localizedDescription)")
}
}
// ํ์คํฌ ์์
task.resume()
๐ JSON ํ์ฑ
์๋ฒ๊ฐ JSON ํ์์ ๋ฐ์ดํฐ๋ฅผ ์๋ต์ผ๋ก ๋ณด๋ด์ค ๋ ์ด๋ฅผ Swfit์ ๋ฐ์ดํฐ ๊ตฌ์กธ ๋ณํํ๋ ๊ณผ์
class ImageRepository {
func fetchRandomPokemonImage(completion: @escaping (UIImage?) -> Void) {
let randomId = Int.random(in: 1...1000)
let urlString = "https://pokeapi.co/api/v2/pokemon/\(randomId)"
guard let url = URL(string: urlString) else {
completion(nil)
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๊ณ , ์๋ฌ๊ฐ ์๋์ง ํ์ธ
guard let data = data, error == nil,
// JSON ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ์ฌ ๋์
๋๋ฆฌ๋ก ๋ณํ
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
// JSON์์ 'sprites' ๋์
๋๋ฆฌ๋ฅผ ๊ฐ์ ธ์ด
let sprites = json["sprites"] as? [String: Any],
// 'sprites' ๋์
๋๋ฆฌ์์ 'front_default' URL ๋ฌธ์์ด์ ๊ฐ์ ธ์ด
let imageUrlString = sprites["front_default"] as? String,
// URL ๋ฌธ์์ด์ URL ๊ฐ์ฒด๋ก ๋ณํ
let imageUrl = URL(string: imageUrlString) else {
// ์คํจํ ๊ฒฝ์ฐ completion ํธ๋ค๋ฌ ํธ์ถ
completion(nil)
return
}
// ์ฑ๊ณตํ ๊ฒฝ์ฐ ์ด๋ฏธ์ง ๋ค์ด๋ก๋ ๋ฉ์๋ ํธ์ถ
self.downloadImage(from: imageUrl, completion: completion)
}
task.resume()
}
private func downloadImage(from url: URL, completion: @escaping (UIImage?) -> Void) {
DispatchQueue.global().async {
if let imageData = try? Data(contentsOf: url),
let image = UIImage(data: imageData) {
DispatchQueue.main.async {
completion(image)
}
} else {
DispatchQueue.main.async {
completion(nil)
}
}
}
}
}
import Foundation
func performGetRequest(urlString: String, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
// 1. URL ์์ฑ
guard let url = URL(string: urlString) else {
print("Invalid URL")
return
}
// 2. URLSession ์์ฑ (๊ณต์ ์ธ์คํด์ค ์ฌ์ฉ)
let session = URLSession.shared
// 3. Data Task ์์ฑ ๋ฐ ์์
let task = session.dataTask(with: url) { data, response, error in
// 4. ์๋ต ์ฒ๋ฆฌ
completion(data, response, error)
}
task.resume() // ์์ฒญ ์์
}
// ์ฌ์ฉ ์์
let url = "https://api.example.com/data"
performGetRequest(urlString: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
guard let data = data else {
print("No data received")
return
}
// ๋ฐ์ดํฐ ์ฒ๋ฆฌ (์: JSON ํ์ฑ)
print(String(data: data, encoding: .utf8)!)
}
import Foundation
func performPostRequest(urlString: String, parameters: [String: Any], completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
// 1. URL ์์ฑ
guard let url = URL(string: urlString) else {
print("Invalid URL")
return
}
// 2. URLRequest ๊ฐ์ฒด ์์ฑ ๋ฐ ์ค์
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do {
// 3. ์์ฒญ ๋ฐ๋ ์ค์
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
} catch let error {
print("Error serializing JSON: \(error.localizedDescription)")
return
}
// 4. URLSession ์์ฑ (๊ณต์ ์ธ์คํด์ค ์ฌ์ฉ)
let session = URLSession.shared
// 5. Data Task ์์ฑ ๋ฐ ์์
let task = session.dataTask(with: request) { data, response, error in
// 6. ์๋ต ์ฒ๋ฆฌ
completion(data, response, error)
}
task.resume() // ์์ฒญ ์์
}
// ์ฌ์ฉ ์์
let url = "https://api.example.com/submit"
let parameters = ["key1": "value1", "key2": "value2"]
performPostRequest(urlString: url, parameters: parameters) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
guard let data = data else {
print("No data received")
return
}
// ๋ฐ์ดํฐ ์ฒ๋ฆฌ (์: JSON ํ์ฑ)
print(String(data: data, encoding: .utf8)!)
}