iOS API JSON 데이터 가져오기 (날씨 API)

Tabber·2021년 7월 29일
0

앱공부정리

목록 보기
2/4

너무 어려웠던 API

강의를 들으며 앱 공부를 하고 있는 요즘. 최근 2주 동안 내 머리를 골치 아프게 했던 것이 있었다. 바로 API. 강의를 보고, 진짜 최소 100개 이상의 블로그를 찾아봤는데도, 내 머리와 손으로 와닫지가 않았다.

그래서 다시 강의를 시작했다. 다시 처음부터 차근차근.

시작해보자!

이 글의 API는 Open Weathermap 의 날씨 API를 사용하였습니다.
글을 읽으시며 따라하실 분들은 위 링크를 눌러 글을 따라와 주시기 바랍니다.

API 만들기

먼저 API를 사용하려면, API KEY 를 만들어야 한다.
위에 있는 링크를 들어가서 (계정이 없을테니) Sign In 을 누른다.

그리고 계정을 만든다.
여러가지를 작성하고

위 체크 리스트 3개 굳이 할필요는 없다. 해도 첫번째 정도?

그러면 계정 생성 끝!

그리고 계정을 생성했을때 입력했던 메일에 인증 링크 메일이 올 것이다. 그것 까지 확인해줘야 API 사용이 가능할 것이다.

그리고 난 뒤 중앙 상단에 API -> API Keys 를 누르게 되면

지금 가린 곳에 자신의 API Key가 보일것이다.
복사를 해놓던지 이 페이지를 열어두던지 하자.

API 사용해보기

다시 API 페이지 들어와서 Current Weather Data의 도큐멘트로 들어가자.

그럼 바로 보이는 코드가 있을 것이다.

api.openweathermap.org/data/2.5/weather?q={도시 이름}&appid={API 키}

위 코드를 복사해도 괜찮다. 한글로 되어있는곳을 도시 이름 (ex: London), API 키(자신이 받았던 키) 를 입력해서 자신의 인터넷 창에서 엔터를 해보자.

London을 입력해서 얻은 JSON 형식의 API정보이다.
이렇게 보이지 않고, 하얀색 바탕에 주르륵 뜬다면 (크롬의 경우) JSON Viewer Pro 을 다운받아 써보자.

이렇게 일단 API 정보를 개인 API키로 표시해보았다.

근데 뭔가 이상하다. temp는 온도를 의미하는 딕셔너리다. 근데 293도?
이런경우엔 아까 입력했던 URL에 &units=metric 를 넣자. 정상적으로 온도가 나올 것이다.
이것에 대한 정보는 Format 을 보자.

자, 이제 Xcode를 이용해보자!

JSON 데이터 가져오기

struct WeatherManger {
    // API 링크
    let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=c739bf09299ed05af242af0066543929&units=metric"
    
    // 날씨 앱이니까 원하는 곳의 URL을 구성해야 하므로, fetchWeather 메서드를 이용하여 원하는 URL을 구해옴
    func fetchWeather(cityName: String) {
        let urlString = "\(weatherURL)&q=\(cityName)"
        // 만든 URL을 performRequest로 전달
        performRequest(urlString: urlString)
    }
}

weatherURL 변수를 만들어 아까 사용했던 링크를 복사해준다. 단, 약간의 위치 변경과 삭제를 이루어야 한다.
아까는 q=London&units=metric 이었던것을 위와 같은 형식으로 바꿔줘야 한다. 사실 바꾸어도 잘 돌아간다.

그리고 난 뒤에 func fetchWeather() 메서드를 이용하여 원하는 곳의 도시 이름을 넣을 수 있게 한다.

그리고 중간에 있는 performRequest() 메서드를 구현해보자.

이 코드들은 WeatherManager 구조체 안에 모두 다 존재하는 것입니다.

// 네트워킹 4단계를 수행할 곳
    func performRequest(urlString: String) {
        if let url = URL(string: urlString) {
        
            let session = URLSession(configuration: .default)
            
            let task = session.dataTask(with: url, completionHandler: handle(data: response: error:))
            
            task.resume()
        }
    }

JSON 에 대한 정보를 가져오는 방법은 총 4단계로 구성되어 있다.

1. URL 만들기

if let url = URL(string: urlString) { 

URL 메서드가 옵셔널로 선언되어있기 때문에 if let 구문으로 nil이 아닐경우 돌아가게 만들어야 한다.

2. URL 세션 만들기

let session = URLSession(configuration: .default)

URLSession메서드는 우리가 크롬상에서 보던 JSON 과 같은 형식으로 만들어주는 역할을 한다.

3. task 에 Session 건네주기

let task = session.dataTask(with: url, completionHandler: handle(data: response: error:))

dataTask 메서드는 지정된 URL의 내용을 검색한 다음 Handler 메서드에 호출하는 작업을 만든다.이 메서드는 URLSessionDataTask 를 반환한다.

따라서 출력을 상수로 설정할 수 있다. 그래서 let task에 넣어놓은것이다.

completionHandler는 그냥 매개변수를 받는 용도로 생각할 수 있지만, completionHandler가 받는것은 함수이다.
따라서 handle함수는 뒤에서 정의한다. (클로저로 정의해도 괜찮다)

task가 인터넷에서 데이터를 가져오는것이 완료될 때마다 handle 메서드를 호출하도록 하고, print문이나 다른것들을 실행할 수 있게 해준다.

4. task 시작

task.resume()

start가 아니고 resume인 이유는 중간에 url이 잘못되어 데이터가 잘못나올수도 있으니 start대신 resume으로 시작한다.

handle 함수 만들기

    func handle(data: Data?, response: URLResponse?, error: Error?)-> Void {
        if error != nil {
            print(error!)
            return
        }
        
        // 에러가 발생하지 않았다면 if let 구문으로 들어와 data(옵셔널 데이터)를 언래핑 하게 된다.
        // data는 문자열로 쉽게 출력할 수 있다.
        if let safeData = data {
            // data를 문자열로 출력하는 방법
            // 언래핑한 data를 .utf8 인코딩 방식으로 String 으로 변환
            let dataString = String(data: safeData, encoding: .utf8)
            print(dataString!)
        }
    }

hendle 메서드를 이용하여 task를 실행할 수 있다.
이 메서드로 데이터를 줄수도 있고, 응답을 할 수도 있고, 에러또한 반환이 가능하다.

에러 리턴

if error != nil {
    print(error!)
    return
}

만일 nil 값이 도출됐을경우에 error 값은 nil 이 아닐테니 != 으로 설정을 해주었고, 리턴을 하게 되어 에러를 출력하고 해당 함수는 종료된다.

safeData

에러가 발생하지 않았다면 if let 구문으로 들어와 data(옵셔널 데이터)를 언래핑 하게 된다.

if let safeData = data {
	let dataString = String(data: safeData, encoding: .utf8)
	print(dataString!)
     }
}

언래핑한 data를 .utf8 인코딩 방식으로 String 으로 변환한다.
그리고 출력하게 된다면,
위와 같이 출력이 된다.

도시 이름을 설정하는 법은 너무나도 다양하지만, 필자 앱을 기준으로 하자면

textField에서 받아온 text를 fetchWeather() 로 전달하였다.
당장 결과값을 받고 싶다면,

struct WeatherManger {
    // API 링크
    let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=c739bf09299ed05af242af0066543929&units=metric"
    
    // 날씨 앱이니까 원하는 곳의 URL을 구성해야 하므로, fetchWeather 메서드를 이용하여 원하는 URL을 구해옴
    func fetchWeather(cityName: String) {
        let urlString = "\(weatherURL)&q=예시:London"
        // 만든 URL을 performRequest로 전달
        performRequest(urlString: urlString)
    }
}

이렇게 도시 이름을 넣고 출력 해보자.

다음 글에는 파싱한 것을 가지고 사용하는 법을 작성해보겠다.

profile
iOS 정복중인 Tabber 입니다.

0개의 댓글