네트워킹

Swift 2021. 3. 17. 21:26

Postman을 통해서 네트워크 작업을 볼 수 있음

 

ios에서는 URLSession을 통해 네트워크 작업을 할 수 있음

 

Queue

- 컴퓨터 공학에서 말하는 자료 공학

- 먼저 들어온 값이 먼저 나가는 방식

 

네트워킹

- 기본적으로 HTTP라는 방법으로 Rest api를 이용해서 json데이터를 주고받음

 

Concurrency(동시성)

- 동시에 여러 가지 일을 수행하는 능력

- GCD와 Operration 통해서 동시성이 필요한 작업들을 관리해 줄 수 있음

- 사용자 인터랙션 처리, 네트워킹, 백그라운드에서 파일 다운로드, 파일 저장하고 읽기 같은 작업 수행 이러한 작업들을 스레드라고 함

 

Thread(스레드)

- 4개의 스레드가 있다고 가정, 4개의 스레드는 동시에 번갈아가면서 모든 작업을 함

- 메인 스레드는 사용자 인터렉션을 처리하면서 ui 표시하는 작업을 함

- 복잡한 계산이나 네트워크 느린 작업은 메인이 아닌 다른 스레드에서 처리해야 앱의 반응을 빠르게 가져갈 수 있음

 

 

HTTP

- 앱과 서버 간에 데이터를 주고받을 때 사용하는 통신 규약

- 동영상 스트리밍 할 때도 사용(HLS)

 

HTTP Request

- url창에 무언가를 입력하고 엔터를 눌렀을 때 하는 행위가 request 하는 방식

 

1. post: create

- 새로운 데이터를 해당 url에 생성을 요구할 때

 

2. get: read

- 해당 url에 있는 데이터를 보고 싶을 때

 

3. update: update

- 해당 url에 있는 데이터를 수정하고 싶을 때

 

4. delete: delete

- 해당 url에 있는 삭제하고 싶을 때

 

 

GCD

- 해야 할 일들을 만들어서 gcd에 넘기면 시스템에서 알아서 스레드를 할당해서 안전하게 수행시켜줌

- 스레드와 비슷한 개념

- gcd에서 사용하는 큐는 dispatch queue

- 테스크를 동기(Sync) & 비동기(Async)로 처리할 수 있음

 

Sync 

- 앞에 작업이 끝나고 나서 다음 일을 처리하는 방식

 

Async 

- 앞에 작업이 끝나지 않아도 다음 일을 시작하는 방식

- 해당하는 우선순위 작업에 따라 진행

- 다운로드하는 작업은 Async로 진행

더보기
// Async
// 일을 같이 처리
DispatchQueue.global(qos: .background).async {
    for i in 0...5 {
        print("A \(i)")
    }
}

// 우선 순위가 더 높기 때문에 먼저 마무리
DispatchQueue.global(qos: .userInteractive).async {
    for i in 0...5 {
        print("B \(i)")
    }
}

// Sync
// Sync는 먼저 일을 처리 후 그 다음 일을 처리
DispatchQueue.global(qos: .background).sync {
    for i in 0...5 {
        print("A \(i)")
    }
}

DispatchQueue.global(qos: .userInteractive).async {
    for i in 0...5 {
        print("B \(i)")
    }
}

 

Dispatch Queue

1. main queue

- 메인 스레드에서 작동하는 큐

- 시스템에서 제공

// main
DispatchQueue.main.async {
    let view = UIView()
    view.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}

 

2. global queue

- 시스템에 의해 관리되는 큐

- 큐에 들어가는 테스크의 우선순위를 qos 클래스를 통해서 표현할 수 있음

- 시스템에서 제공

 

Qos

우선순위가 높은 순

- 1. userinteractive

-- 바로 수행되어야 할 작업에 대해서 userinteractive 설정

 

- 2. userinitiated

-- 사용자 결과를 기다리는 작업에 사용

 

- 3. default

-- userinitiated 보다 좀 더 걸리는 작업에 사용

 

- 4. utility

-- 몇 초 ~ 몇 분 걸리는 작업에 사용

-- 네트워킹이나 파일 불러오기 같은 작업에 사용

 

- 5.background

-- 사용자에게 당장 인식될 필요가 없는 경우 사용

 

3. custom queue

- 큐를 직접 만들어서 사용해야 하는 경우

- 시스템에서 제공하지 않음

// global
DispatchQueue.global(qos: .userInteractive).async {
    // 가장 먼저 해줘야 하는 일
}

DispatchQueue.global(qos: .userInitiated).async {
    // 사용자가 기다리고 있으니 빨리 해줘야 하는 일
}

DispatchQueue.global(qos: .default).async {
    // 그냥 저냥 해도 되는 일
}

DispatchQueue.global().async { // default는 이런 식으로 표현 가능
    
}

DispatchQueue.global(qos: .utility).async {
    // 시간이 좀 걸리는 일들, 사용자가 당장 없어도 상관 없는 일들, 네트워킹, 큰 파일 다운로드
}

DispatchQueue.global(qos: .background).async {
    // 사용자한테 당장 필요하지 않은 일들, 뉴스데이터 미리 받기, 위치 업데이트, 영상 다운로드 등등
}

 

 

URLSession

- URLSession은 URLSessionConfiguration을 이용해서 생성을 하게 됨

- URLSessionTask를 만들 수 있음(URLSessionTask를 통해 서버와 통신함)

- URLSeesionDelegate을 통해 네트워킹 중간 과정을 확인할 수 있음

 

URLSessionConfiguration

- URLSessionConfiguration을 생성할 때는 URLSession 정책에 따라서 Default, Ephemeral, Background 세 가지 타입으로 만들 수 있음

 

1. Default

- 기본 통신할 때 사용

 

2. Ephemeral

- 쿠키나 캐시 같은 것을 저장하지 않게 정책을 가져갈 때 사용(예: 시크릿 모드)

 

3. Background

- 다운로드할 때 사용

 

URLSessionTask

1.URLSessionDataTask

- 기본적인 데이터를 받는 작업에 사용

- response 데이터를 메모리 상에서 처리

- 백그라운드 세션에 대한 지원이 안됨

 

2. URLSessionUploadTask

- 파일 업로드할 때 사용

 

3. URLSessionDownloadTask

- 파일 다운로드할 때 사용

 

더보기
import UIKit

// url
// 웹 리소스의 주소
let urlString = "https://itunes.apple.com/search?media=music&entity=song&term=Gdragon"
let url = URL(string: urlString)

url?.absoluteString // urlStrung에 입력된 값을 보여줌
url?.scheme // 어떤 방식으로 네트워킹을 하고 있는지 확인 시켜줌
url?.host
url?.path
url?.query // 검색에 대한 조건
url?.baseURL


let baseURL = URL(string: "https://itunes.apple.com")
let relativeURL = URL(string: "search?media=music&entity=song&term=Gdragon", relativeTo: baseURL)

relativeURL?.absoluteString
relativeURL?.scheme
relativeURL?.host
relativeURL?.path
relativeURL?.query
relativeURL?.baseURL



// URLComponents
var urlComponents = URLComponents(string: "https://itunes.apple.com/search?")
let mediaQuery = URLQueryItem(name: "media", value: "music")
let entityQuery = URLQueryItem(name: "entity", value: "song")
let termQuery = URLQueryItem(name: "term", value: "Gragon")

urlComponents?.queryItems?.append(mediaQuery)
urlComponents?.queryItems?.append(entityQuery)
urlComponents?.queryItems?.append(termQuery)

urlComponents?.url
urlComponents?.string
urlComponents?.queryItems

 

 

더보기
import UIKit

var urlComponents = URLComponents(string: "https://itunes.apple.com/search?")!
let mediaQuery = URLQueryItem(name: "media", value: "music")
let entityQuery = URLQueryItem(name: "entity", value: "song")
let termQuery = URLQueryItem(name: "term", value: "지드래곤")

urlComponents.queryItems?.append(mediaQuery)
urlComponents.queryItems?.append(entityQuery)
urlComponents.queryItems?.append(termQuery)
let requestURL = urlComponents.url!

let config = URLSessionConfiguration.default
let session  = URLSession(configuration: config)


struct Response: Codable {
    let resultCount: Int
    let tracks: [Track]
    
    enum CodingKeys: String, CodingKey {
        case resultCount
        case tracks = "results"
    }
}

struct Track: Codable {
    let title: String
    let artistName: String
    let thumbnailPath: String
    
    enum CodingKeys: String, CodingKey {
        case title = "trackName"
        case artistName
        case thumbnailPath = "artWorkUrl100"
    }
}


let dataTask = session.dataTask(with: requestURL) { (data, response, error) in
    guard error == nil else { return }
    
    guard let statusCode = (response as? HTTPURLResponse)?.statusCode else { return }
    let successRange = 200..<300
    
    guard successRange.contains(statusCode) else {
        // handle response error
        return
    }
    
    guard let resultData = data else { return }
    let resultString = String(data: resultData, encoding: .utf8)


// 파싱
    do {
        let decoder = JSONDecoder()
    
        // try - 해당 작업이 항상 성공 한다는 보장이 없음, 시도를 하다가 오류가 생기면 catch 구문으로 빠짐
        let response = try decoder.decode(Response.self, from: resultData)
    
        let tracks = response.tracks
    
        print("tracks: \(tracks.count) -\(tracks.first?.title), \(tracks.last?.thumbnailPath)")
    
    } catch let error {
       print("error: \(error.localizedDescription)") // 오류에 대한 설명은 localizedDescription에 나와 있음
    }
}

dataTask.resume()

'Swift' 카테고리의 다른 글

Firebase / Cocoa Pods  (0) 2021.03.22
넷플릭스 스타일 앱 만들기 / 오픈 소스 가져오는 방법  (0) 2021.03.19
List App  (0) 2021.03.15
뮤직 앱  (0) 2021.03.13
CollectionView  (0) 2021.03.06
Posted by khon98
,