iOS의 네트워킹 흐름에 대해 알아보자

📖iOS의 네트워킹

⭐️비동기적으로 작동⭐

1. URL 주소를 문자열로 생성

let movieURL = "http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?targetDt=20120101&key=7a526456eb8e084eb294715e006df16f" // (서버 주소 + 쿼리 파라미터)
  • 주소가 짧으면 변수를 만들지 않고 바로 구조체에 넣어주기도 함

2. URL 구조체 만들기

let url = URL(string: movieURL)!
  • 이 상수를 애플에서 만들어놓은 생성자에 담아 URL 구조체 생성

3. URL Session 생성

URLSession

애플에서 만들어 놓은 네트워킹을 하는 객체(브라우저 같은 역할)

  • 내부적으로 비동기처리된 함수 (작업이 끝나는 것을 기다리지 X & 서브 쓰레드에서 작업 처리)

Session

일정 시간동안 브라우저(사용자)로부터 들어오는 연결 상태를 일정하게 유지시키는 기술(상태)

let session = URLSession.shared // 싱글톤을 생성하는 타입 속성(훨씬 많이 씀)
let session = URLSession(configuration:.default)

4. session에 일시정지 상태로 작업 부여

dataTask()

서버로부터 응답 데이터를 받아서 Data 객체를 가져오는 작업을 수행하는 메서드 HTTP 요청 메서드를 만드는 역할

let task = session.dataTask(with: url) { data, response, error in
    // error
    if error != nil {
        print(error!)
        return
    }
    //request
    guard let response = response as? HTTPURLResponse, (200..<299) ~= response.statusCode else {
    print("Error: HTTP request failed")
    return
    }
    // data
    guard let safeData = data else {
        return
    }
    
    // Decoding (데이터 잘 갖고 왔움 → 이제 우리가 사용하려는 형태(구조체/클래스)로 변형해서 사용)
    dump(parseJSON(safeData)) // 여기에선 걍 출력만 해봤어용
    
}
  • 파라미터(url)를 가지고 네트워크 통신을 함 → 통신 결과를 콜백함수의 파라미터(data,response, error)로 넘겨줌
  • 여기서 받는 데이터는 jSON형태의 데이터 → 이를 우리가 사용하려는 형태(구조체/클래스)로 변형해서 사용

5. 작업 시작

task.resume()
  • 일시정지된 상태로 작업이 시작하기 때문에 필수

6. Decoding

JSON 형태의 데이터를 우리가 사용하려는 형태의 데이터(구조체/클래스)로 파싱

JSONDecoder()

자동으로 원하는 클래스/구조체 형태로 디코딩하는 객체

decode()

데이터를 파싱해주는 메서드

  • type: 변형하고 싶은 형태(반드시 Decodable이나 Codable 프로토콜 채택)
  • from : JSON이 저장되어 있는 data
func parseJSON(_ movieData: Data) -> [DailyBoxOfficeList]? {
    do {
        let decoder = JSONDecoder()
        
        let decodedData = try decoder.decode(MovieData.self, from: movieData) // error를 발생시킬 수 있는 메서드이므로 try 붙여주기 → try 사용하려면 do-catch로 감싸줘야 함 !!문법 공부!!        
        let dailyLists = decodedData.boxOfficeResult.dailyBoxOfficeList
        
        let myMovielists = dailyLists.map {
            Movie(movieNm: $0.movieNm, rank: $0.rank, openDate: $0.openDt, audiCnt: $0.audiCnt, accAudi: $0.audiAcc)
        } // 고차함수 이용해 생성
        
        return myMovieLists
        
    } catch {
        print("파싱 실패")
        return nil
    }
}
  • 위 코드에서는 데이터를 받아서 .self 형태로 디코딩(변환) 그럼 이제 movieData로 변형되었으니까 여기에 접근해서 데이터 사용 가능
데이터
서버에서 주는 데이터
// MARK: - JSON
// 서버에서 받은 데이터 고대로 출력 시
{
  "boxOfficeResult": {
    "boxofficeType": "일별 박스오피스",
    "showRange": "20120101~20120101",
    "dailyBoxOfficeList": [
      {
        "rnum": "1",
        "rank": "1",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20112207",
        "movieNm": "미션임파서블:고스트프로토콜",
        "openDt": "2011-12-15",
        "salesAmt": "2776060500",
        "salesShare": "36.3",
        "salesInten": "-415699000",
        "salesChange": "-13",
        "salesAcc": "40541108500",
        "audiCnt": "353274",
        "audiInten": "-60106",
        "audiChange": "-14.5",
        "audiAcc": "5328435",
        "scrnCnt": "697",
        "showCnt": "3223"
      },
      {
        "rnum": "2",
        "rank": "2",
        "rankInten": "1",
        "rankOldAndNew": "OLD",
        "movieCd": "20110295",
        "movieNm": "마이 웨이",
        "openDt": "2011-12-21",
        "salesAmt": "1189058500",
        "salesShare": "15.6",
        "salesInten": "-105894500",
        "salesChange": "-8.2",
        "salesAcc": "13002897500",
        "audiCnt": "153501",
        "audiInten": "-16465",
        "audiChange": "-9.7",
        "audiAcc": "1739543",
        "scrnCnt": "588",
        "showCnt": "2321"
      },
    ]
  }
}
 
// MARK: - swift
// 서버에서 준 데이터를 JSONDecoder 객체 이용해 분석하기 위한 것
struct MovieData: Codable {
    let boxOfficeResult: BoxOfficeResult
}
 
// MARK: - BoxOfficeList
struct BoxOfficeResult: Codable {
    let dailyBoxOfficeList: [DailyBoxOfficeList]
}
 
// MARK: - DailyBoxOfficeList
struct DailyBoxOfficeList: Codable {
    let rank: String
    let movieNm: String
    let audiCnt: String
    let audiAcc: String
    let openDt: String
}

JSON 데이터를 swift 코드로 변환 가능한 사이트

내가 쓸 형태로 변환한 데이터
struct Movie {
    static var movieId: Int = 0   // 아이디가 하나씩 부여되도록 만듦
    let movieName: String
    let rank: Int
    let openDate: String
    let todayAudience: Int
    let totalAudience: Int
 
    init(movieNm: String, rank: String, openDate: String, audiCnt: String, accAudi: String) {
        self.movieName = movieNm
        self.rank = Int(rank)!
        self.openDate = openDate
        self.todayAudience = Int(audiCnt)!
        self.totalAudience = Int(accAudi)!
 
        Movie.movieId += 1
    }
}

📖iOS의 네트워킹 과정 요약

  1. (서버와 통신을 하기 위한 주소)문자열을 가지고 URL을 만듦
  2. 애플이 만들어놓은 URL 구조체로 변경
  3. URL Session을 만들고(브라우저 같은 걸 킨 다음에)
  4. 그 안의 데이터 dataTask() 메소드를 사용해 통신 (이 통신의 결과(응답 메세지)가 클로져 안에 주어짐)
    • 이 클로져 안에 작업(에러 처리 후 데이터 디코딩 with JSONDecoder 객체) 부여
  5. 이 함수가 멈춘 상태로 시작함 그래서 resume()메소드로 시작 시켜줌
  6. 클로져 내부를 실행해 클로저 내부 작업 실행

위 내용을 바탕으로 다음 노트에서 iOS의 네트워킹을 연습해보자