clamp
Clamp
clamp
글쓰기 관리
전체 방문자
오늘
어제
  • 분류 전체보기 (509)
    • IOS (85)
    • SwiftUI+TCA+Combine (9)
    • RxSwift + MVVM (56)
    • Clean Architecture (12)
    • SWIFT (56)
    • iOS - TDD (2)
    • 디자인패턴 (4)
    • CS (56)
      • 알고리즘 (29)
      • 운영체제 (15)
      • 자료구조 (2)
      • 네트워킹 (4)
      • 기타 (6)
    • 회고 (0)
    • Firebase (18)
    • SwiftUI (10)
    • iOS - UIKit (11)
    • iOS - 오픈소스 (6)
    • 코딩테스트 (166)
      • 프로그래머스 (164)
    • 정보처리기사 (14)
    • GitHub (2)
글쓰기 / 관리자

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ㅅ
  • Swift
  • uikit
  • Q

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
clamp

Clamp

IOS - Alamofire를 이용한 API 데이터화.
iOS - 오픈소스

IOS - Alamofire를 이용한 API 데이터화.

2022. 2. 22. 15:28

 

https://api.corona-19.kr/

 

Corona-19-API

코로나바이러스감염증-19에 대한 무료 API 서비스를 제공합니다.

api.corona-19.kr

api키를 발급받고

https://api.corona-19.kr/korea/country/new/?serviceKey={api 키} 입력

중괄호는 지워야함.

 

//시도별 현황 api response JSON. (2022년 2월 22일자)
{
    "resultCode": "0",
    "resultMessage": "정상 처리되었습니다.",
    "korea": {
        "countryName": "합계",
        "newCase": "99,573",
        "totalCase": "2,157,734",
        "recovered": "936,891",
        "death": "7,508",
        "percentage": "4179",
        "newCcase": "99,444",
        "newFcase": "129"
    },
    "seoul": {
        "countryName": "서울",
        "newCase": "21,807",
        "totalCase": "561,744",
        "recovered": "274,931",
        "death": "2,307",
        "percentage": "5907",
        "newCcase": "21,769",
        "newFcase": "38"
    },
    "busan": {
        "countryName": "부산",
        "newCase": "6,140",
        "totalCase": "115,860",
        "recovered": "45,169",
        "death": "406",
        "percentage": "3458",
        "newCcase": "6,137",
        "newFcase": "3"
    },
    "daegu": {
        "countryName": "대구",
        "newCase": "4,158",
        "totalCase": "92,836",
        "recovered": "59,172",
        "death": "448",
        "percentage": "3892",
        "newCcase": "4,158",
        "newFcase": "0"
    },
    "incheon": {
        "countryName": "인천",
        "newCase": "7,772",
        "totalCase": "150,084",
        "recovered": "71,128",
        "death": "389",
        "percentage": "5090",
        "newCcase": "7,771",
        "newFcase": "1"
    },
    "gwangju": {
        "countryName": "광주",
        "newCase": "3,247",
        "totalCase": "51,947",
        "recovered": "13,667",
        "death": "110",
        "percentage": "3603",
        "newCcase": "3,239",
        "newFcase": "8"
    },
    "daejeon": {
        "countryName": "대전",
        "newCase": "2,849",
        "totalCase": "53,491",
        "recovered": "16,333",
        "death": "216",
        "percentage": "3683",
        "newCcase": "2,848",
        "newFcase": "1"
    },
    "ulsan": {
        "countryName": "울산",
        "newCase": "1,941",
        "totalCase": "30,482",
        "recovered": "18,134",
        "death": "72",
        "percentage": "2718",
        "newCcase": "1,941",
        "newFcase": "0"
    },
    "sejong": {
        "countryName": "세종",
        "newCase": "648",
        "totalCase": "11,748",
        "recovered": "6,667",
        "death": "5",
        "percentage": "3159",
        "newCcase": "648",
        "newFcase": "0"
    },
    "gyeonggi": {
        "countryName": "경기",
        "newCase": "29,562",
        "totalCase": "655,560",
        "recovered": "230,244",
        "death": "2,359",
        "percentage": "4833",
        "newCcase": "29,558",
        "newFcase": "4"
    },
    "gangwon": {
        "countryName": "강원",
        "newCase": "2,057",
        "totalCase": "41,182",
        "recovered": "23,554",
        "death": "139",
        "percentage": "2677",
        "newCcase": "2,055",
        "newFcase": "2"
    },
    "chungbuk": {
        "countryName": "충북",
        "newCase": "2,187",
        "totalCase": "45,772",
        "recovered": "28,130",
        "death": "149",
        "percentage": "2865",
        "newCcase": "2,181",
        "newFcase": "6"
    },
    "chungnam": {
        "countryName": "충남",
        "newCase": "3,337",
        "totalCase": "71,505",
        "recovered": "22,372",
        "death": "240",
        "percentage": "3374",
        "newCcase": "3,333",
        "newFcase": "4"
    },
    "jeonbuk": {
        "countryName": "전북",
        "newCase": "2,463",
        "totalCase": "52,300",
        "recovered": "28,868",
        "death": "163",
        "percentage": "2927",
        "newCcase": "2,456",
        "newFcase": "7"
    },
    "jeonnam": {
        "countryName": "전남",
        "newCase": "2,109",
        "totalCase": "40,015",
        "recovered": "6,933",
        "death": "54",
        "percentage": "2183",
        "newCcase": "2,106",
        "newFcase": "3"
    },
    "gyeongbuk": {
        "countryName": "경북",
        "newCase": "3,127",
        "totalCase": "66,949",
        "recovered": "21,647",
        "death": "288",
        "percentage": "2549",
        "newCcase": "3,114",
        "newFcase": "13"
    },
    "gyeongnam": {
        "countryName": "경남",
        "newCase": "4,839",
        "totalCase": "88,211",
        "recovered": "49,583",
        "death": "133",
        "percentage": "2662",
        "newCcase": "4,829",
        "newFcase": "10"
    },
    "jeju": {
        "countryName": "제주",
        "newCase": "1,301",
        "totalCase": "18,482",
        "recovered": "11,681",
        "death": "14",
        "percentage": "2731",
        "newCcase": "1,301",
        "newFcase": "0"
    },
    "quarantine": {
        "countryName": "검역",
        "newCase": "29",
        "totalCase": "9,566",
        "recovered": "8,678",
        "death": "16",
        "percentage": "-",
        "newCcase": "0",
        "newFcase": "29"
    }
}

 

 

모든 데이터는 아래에 해당하는 값을 갖고있으므로 구조체를 선언한다.

struct CovidOverview: Codable{
    let countryName: String
    let newCase: String
    let totalCase: String
    let recovered: String
    let death: String
    let percentage: String
    let newCcase: String
    let newFcase: String
}

 

 

모든 지역별 수치는 해당값을 갖고있으므로 프로퍼티 이름은 지역명, 자료형은 CovidOverview로 정의한다.

struct CityCovidOverview: Codable{
    let korea: CovidOverview
    let seoul: CovidOverview
    let busan: CovidOverview
    let daegu: CovidOverview
    let incheon: CovidOverview
    let gwangju: CovidOverview
    let daejeon: CovidOverview
    let ulsan: CovidOverview
    let sejong: CovidOverview
    let gyeonggi: CovidOverview
    let gangwon: CovidOverview
    let chungbuk: CovidOverview
    let chungnam: CovidOverview
    let jeonbuk: CovidOverview
    let jeonnam: CovidOverview
    let gyeongbuk: CovidOverview
    let gyeongnam: CovidOverview
    let jeju: CovidOverview
}

 

 

Alamofire를 활용하여 API를 호출할 메서드를 정의해준다.

completionHaner클로저를 전달받는다. API를 요청하고 서버에서 JSON데이터를 응답받거나 요청에 실패하였을 때 completionHaner클로저를 호출하여 해당클로저를 정의한 곳에 응답받을 데이터를 전달한다. 요청에 성공하면 CityCovidOverview 열거형 값을 전달하고, 요청에 실패하거나 에러상황일 경우 Error객체가 열거형 연관값으로 전달될 것이다.

 func fetchCovidOverview(completionHandler: (Result<CityCovidOverview, Error>) -> Void)
    {
    }

 

Alamofire로 request를 한다

Alamofire의 request메서드

 

let url = "https://api.corona-19.kr/korea/country/new/"
        let param = [
            "serviceKey" : "API키"
        ]
        
        AF.request(url, method: .get, parameters: param)

request메서드를 이용해 호출을 하였으면 응답데이터를 받을 수 있는 메서드를 체이닝을 해주어야함.

AF.request(url, method: .get, parameters: param)
            .responseData(completionHandler: <#T##(AFDataResponse<Data>) -> Void#>)

completionHandler를 정의해주면 응답데이터가 클로저 파라미터로 전달되게 된다

 

요청에 대한 응답결과는 response.result로 알 수 있다.

요청결과가 .success이면 연관값으로 서버에서 전달받은 data가 전달되게 된다. 

decoder를 생성하고 JSONDecoder 인스턴스를 대입 시켜준다

result 결과는 decoder가 decode를 한다는 메서드로 대충 이해.

첫 번째 파마니터는 매핑 시켜줄 객체 타입이며,  from은 서버에서 전달받은 data를 넣어준다

completionHandler를 호출 하는데 success연관값에는 방금 정의해준 result를 넣어주며, 이 값은 CityCovidOverview 객체타입이다.

만약 JSON데이터가 CityCovidOverview매핑되는데 실패를 한다면 catch구문을 실행한다.

completionhandler를 실행하는데 .failure를 실행하는데 연관값에는 error가 실행됨.

 

 .responseData { response in
                switch response.result{
                case let .success(data):
                    do{
                        let decoder = JSONDecoder()
                        let result = try decoder.decode(CityCovidOverview.self, from: data)
                        completionHandler(.success(result))
                    } catch{
                        completionHandler(.failure(error))
                    }
                }
            }

 

 

fetchCovidOverview메서드 파라미터의 클로저를 이스케이핑 클로저로 선언을 한다

이스케이핑클로저는 클로저가 함수로 이스케이프(탈출한다) 함수의 인자로 클로저가 전달되지만 함수가 반환된 후에도 실행되는것을 의미

함수의 인자가 함수의 영역을 탈출하여 함수밖에서도 사용할 수 있는 개념은 기존에 우리가 알고있는 변수의 scope개념을 완전히 무시한다. 왜냐하면 함수에서 선언된 로컬변수가 로컬변수의 영역을 뛰어넘어 함수의 밖에서도 유효하기 때문

이스케이핑 함수를 사용하는 대표적인 예시로는 비동기작업을 하는경우, 컴플리션 핸들러로 이스케이핑 핸들러를 많이 사용함

보통 네트워킹통신은 비동기적으로 작업되기 때문에 코드에서와 같이  responseData메서드 파라미터에 정의한 completionHandler클로저는 fetchCovidOverview함수가 반환된 뒤에 호출이 된다.

그 이유는 서버에서 데이터를 언제 응답시켜줄지 모르기 때문이다.

그렇기 때문에 이스케이프 컴플리션 핸들러로 정의하지 않는다면 responseData메서드에 정의한 completionHandler가 호출되기 전에 함수가 종료되서 서버의 응답을 받아도 fetchCovidOverview함수에 정의한 completionHandler가 호출되지 않는다. 

그렇기 때문에 함수 내에서 비동기 작업을 하고, 비동기 작업의 결과를 completionHander로 콜백을 해야 한다면, 이스케이핑클로저를 사용하여 함수가 반환된 후에도 실행되게 만들어주어야함. 

클로저 정의 앞에 @escaping를 적어준다.

 func fetchCovidOverview(completionHandler: @escaping (Result<CityCovidOverview, Error>) -> Void)

 

 

 

순환참조를 방지하기 위해 result 앞에 [weak self]를 적어주고

guard let self = self else { return } 을 통하여 일시적으로 self가 Strong reference가 되게 만들어준다,

fetchCovidOverview { [weak self] result in
            guard let self = self else { return }
        }

 

 

최종적으로 fetchCovidOverview가 API JSON data를 가져오는데 성공한다면 debugPrint로 콘솔창에 CityCovidOverview 객체가 나타나고, 실패한다면 error가 콘솔장에 나타나게 된다.

fetchCovidOverview { [weak self] result in
            guard let self = self else { return }
            
            switch result{
            case let.success(result):
                debugPrint("success \(result)")
            case let .failure(error):
                debugPrint("error \(error)")
            }
        }
    }
저작자표시 비영리 동일조건 (새창열림)
    'iOS - 오픈소스' 카테고리의 다른 글
    • [iOS] SDWebImage 라이브러리
    • IOS - Lottie(오픈소스)
    • IOS - Kingfisher(오픈소스)
    • IOS - Alamofire을 이용한 HTTP통신
    clamp
    clamp
    주니어 iOS개발자의 발악!!!!!!!

    티스토리툴바