Notice
Recent Posts
Recent Comments
Link
ยซ   2024/05   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
๊ด€๋ฆฌ ๋ฉ”๋‰ด

lgvv98

[REST API] ์นด์นด์˜ค ์›น ๊ฒ€์ƒ‰ API - Swift ๋ณธ๋ฌธ

โš ๏ธ deprecated โš ๏ธ/REST API ์—ฐ์Šต์žฅ

[REST API] ์นด์นด์˜ค ์›น ๊ฒ€์ƒ‰ API - Swift

๐Ÿฅ• ์บ๋Ÿฟ๋งจ 2021. 9. 25. 20:28

โœ… ์šฐ์™€ ์ •๋ง ์”๋‚˜์„œ ์ด ๊ธ€ ์“ฐ๋Ÿฌ ๋ฐ”๋กœ!! ๋ฐ”๋กœ!! ๊ธ€ ์“ฐ๋Ÿฌ ์™”๋‹ค!!!

 

์šฐ์„  ์ด๋Ÿฐ๊ฑฐ์— ์ง„์งœ ๋„ˆ๋ฌด๋„ˆ๋ฌด ์•ฝํ•œ ๋‚˜๋ผ์„œ, ํ•˜๋‚˜ํ•˜๋‚˜ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ณด๊ณ  ์ง€๋‚˜๊ฐ€๋„๋ก ํ• ๊ฒŒ.

 

โœ… ๋ชฉ์ฐจ

 1. ์นด์นด์˜ค API ๋ฐœ๊ธ‰ ๋ฐฉ๋ฒ• 

 2. Xcode ๊ธฐ๋ณธ ์„ธํŒ…

 3. Codable ๋งŒ๋“ค๊ธฐ

 4. Alamofire ์ด์šฉํ•ด์„œ ํ†ต์‹ ํ•˜๊ธฐ

 5. ์ตœ์ข… ์†Œ์Šค์ฝ”๋“œ

 

โœ… ์นด์นด์˜ค API ๋ฐœ๊ธ‰ ๋ฐฉ๋ฒ•

 

https://developers.kakao.com/

 

Kakao Developers

์นด์นด์˜ค API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•ด๋ณด์„ธ์š”. ์นด์นด์˜ค ๋กœ๊ทธ์ธ, ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ, ์นœ๊ตฌ API, ์ธ๊ณต์ง€๋Šฅ API ๋“ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

developers.kakao.com

 

์•„๋ž˜์— ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•ด์„œ

๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํด๋ฆญ

 

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ถ”๊ฐ€ํ•˜๊ธฐ ํด๋ฆญ
์—ฌ๊ธฐ ํ•„๋“œ๋ฅผ ์ฑ„์šด ํ›„ ์ €์žฅ 
๋‚ด๊ฐ€ ๋งŒ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋“ค์–ด๊ฐ€๊ธฐ

 ๐ŸŸ  ์˜†์— iOS๊ฐ€ ๋ถ™์–ด ์žˆ๋Š”๋ฐ, ๋‚˜๋Š” ๋จผ์ € ํ•ด๋‘” ์ƒํƒœ์ด๊ณ  ์ฒ˜์Œํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์—†์œผ๋‹ˆ๊นŒ ๋„˜์–ด๊ฐ€๊ธฐ!

 

ํด๋ฆญ!

๐ŸŸ  ํ”Œ๋žซํผ ๋ถ€๋ถ„ ํด๋ฆญํ•ด์„œ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ํ”Œ๋žซํผ ๋“ฑ๋กํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค

 

โšก๏ธ ์•ฑ ํ‚ค ๋ถ€๋ถ„์„ ๋ณด๋ฉด ํ‚ค๊ฐ€ ๋ฐœ๊ธ‰๋˜์–ด ์žˆ์„ํƒ ๋ฐ, ์šฐ๋ฆฌ๋Š” REST API ํ‚ค๋ฅผ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ด์•ผ

 

 

โœ… Xcode ๊ธฐ๋ณธ ์„ธํŒ…

 

๐ŸŸ  Main.Storyboard

๋ฒ„ํŠผ ํ•˜๋‚˜์™€ ํ…์ŠคํŠธ ๋ทฐ ํ•˜๋‚˜๋งŒ ๋Œ€์ถฉ ์ฑ„์›Œ๋‘๊ธฐ

 

๐ŸŸ  ViewController.swift

import UIKit
import Alamofire

class ViewController: UIViewController {

    @IBOutlet weak var CallButton: UIButton! // ๋ฒ„ํŠผ
    @IBOutlet weak var APITextView: UITextView! // ํ…์ŠคํŠธ ๋ทฐ
    
    @IBAction func CallButtonClick(_ sender: Any) {
        // ๋ฒ„ํŠผ ํด๋ฆญ์‹œ
    }
    
    
    let url = "https://dapi.kakao.com/v2/search/web"
    
    let headers : HTTPHeaders = [
        "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
        "Authorization": "KakaoAK {Rest API KEY}", // ์ด ๋ถ€๋ถ„์— ๋‹น์‹ ์˜ REST API ํ‚ค ๋„ฃ์–ด์ฃผ๊ธฐ
        
        /* ! ์˜ˆ์‹œ ! 
        "Authorization": "KakaoAK 1abec3hyn81d3nut7as" // KakaoAK ํ•˜๊ณ  ๋„์–ด์“ฐ๊ธฐ ์œ ์‹ฌํžˆ ๋ณด๊ธฐ
        */
    ]
    
    // ๋ฌธ์„œ์— ๋ณด๋ฉด ๋” ์ •ํ™•!
    let parameters : [String: Any] = [
                "query": "์‚ผ์„ฑ์ „์ž", // ์–˜๋Š” ํ•„์ˆ˜ ๋‚˜๋จธ์ง€๋Š” ์˜ต์…˜
                "page": 1,
                "size": 15
            ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

}

๐ŸŸ  ์ด๊ฒŒ ๊ฐ€์žฅ ๊ธฐ์ดˆ์ ์ธ ์„ธํŒ…์ด์•ผ ์ผ๋‹จ ์ด๋ ‡๊ฒŒ ์„ค์ •ํ•ด ์ค˜.

 

๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ์งš์–ด๋ณด๋ฉด ๋‘๋ฐฐ๋กœ ๋” ์ข‹๊ฒ ์ง€?

https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide

 

Kakao Developers

์นด์นด์˜ค API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•ด๋ณด์„ธ์š”. ์นด์นด์˜ค ๋กœ๊ทธ์ธ, ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ, ์นœ๊ตฌ API, ์ธ๊ณต์ง€๋Šฅ API ๋“ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

developers.kakao.com

๋ฌธ์„œ์—์„œ ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š” ์˜ˆ์‹œ

์ด ๋ถ€๋ถ„์ด ์œ„์— ์ฝ”๋“œ๋กœ ์ €๋ ‡๊ฒŒ ์ €๋ ‡๊ฒŒ ์ž‘์„ฑ๋˜๋Š”๊ฑฐ์•ผ.

์ด๊ฑธ ์™œ ๋ชปํ•ด? ํ•˜๋Š” ์‚ฌ๋žŒ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ •๋ง ๋‚˜ ์™•์ดˆ๋ณด๋ผ์„œ... ๋‚˜ ํ•˜๋Š”๋ฐ ํ•˜๋ฃจ์ข…์ผ ๊ฑธ๋ ค์„œ ์ด๋Ÿฐ๊ฑฐ ์•Œ๋ ค์ฃผ๋Š” ํฌ์ŠคํŒ…์ด ์žˆ์œผ๋ฉด ์„ธ๋ฐฐ๋กœ ์ข‹์ง€ ์•Š์„๊นŒ? ํ•ด์„œ ์ ์–ด๋‘ฌ

 

ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋ฆฌ์Šคํฐ์Šค๋ฅผ ์ง์ ‘ ์Šคํฌ๋กคํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„๊ฑฐ์•ผ!

 

๐ŸŸ   ์šฐ๋ฆฌ๋Š” Alamofire๋ฅผ ์ด์šฉํ•  ์—์ •์ธ๋ฐ, ์ด๊ฑด pod ์„ค์น˜ํ•ด์•ผํ•˜๋Š” ๋ถ€๋ถ„์ด์•ผ. ๐ŸŸ 

 

2021.04.23 - [iOS/๊ผผ๊ผผํ•œ ์žฌ์€์”จ(์‹ค์ „)] - Alamofire ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ( + CocoaPods ๊ฐœ๋…) ์„ค์น˜ ๋ฐ ์‚ฌ์šฉ๋ฒ•

 

Alamofire ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ( + CocoaPods ๊ฐœ๋…) ์„ค์น˜ ๋ฐ ์‚ฌ์šฉ๋ฒ•

Alamofire๋Š” HTTP ๋„คํŠธ์›Œํ‚น์„ ์œ„ํ•ด ์Šค์œ„ํ”„ํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ๋œ ๋น„๋™๊ธฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, URLRequest + URLSession ๊ฐ์ฒด๋ฅผ ๋ž˜ํ•‘ํ•œ ๊ฐ„๊ฒฐํ•œ ๊ตฌ์„ฑ ๋•๋ถ„์— ๋ชจ๋ฐ”์ผ ์„œ๋ฒ„์™€ HTTPํ†ต์‹ ์„ ๊ตฌํ˜„ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋ฐ”

rldd.tistory.com

 

๐ŸŸ  ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ํ™•์ธํ•˜๊ธฐ

์นด์นด์˜ค ๊ฐœ๋ฐœ์ž ๋ฌธ์„œ์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ

์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ผญ ํ™•์ธ ํ•ด์•ผํ•ด.

 

๐ŸŸ  ์—ฌ๊ธฐ์„œ ๊ฟ€ํŒ 

https://app.quicktype.io/

 

Instantly parse JSON in any language | quicktype

 

app.quicktype.io

JSONํŠธ๋ฆฌ ๋ถ„์„ํ•ด์„œ Codable ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค. 

๋‚ด๊ฐ€ Codable ํ˜ผ์ž ๋งŒ๋“ค๋‹ค๊ฐ€ ์ž˜๋ชป ๋งŒ๋“ค์–ด์„œ, ๊ณ„์† ์•ˆ๋˜๊ณ  ์ง„์งœ ์ŠฌํŽ๋Š”๋ฐ, ์ด๊ฑฐ ์‚ฌ์šฉํ•˜๋‹ˆ๊นŒ ํ•œ๋ฒˆ์— ๋˜์„œ ๋„˜ ํ–‰๋ณตํ–ˆ์–ด ใ… ใ… 

 

โœ… Codable ๋งŒ๋“ค๊ธฐ

์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง!!

โœ… Alamofire ์ด์šฉํ•ด์„œ ํ†ต์‹ ํ•˜๊ธฐ

AF.request(url,
                   method: .get,
                   parameters: parameters,
                   encoding: URLEncoding.default,
                   headers: headers)
            .validate(statusCode: 200..<300)
            .responseJSON { response in
                //์—ฌ๊ธฐ์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ํ™œ์šฉํ•˜์„ธ์š”.
                switch response.result {
                case .success(let res):
                    let resultData = String(data: response.data!, encoding: .utf8)
                    
                    do {
                        // ๋ฐ˜ํ™˜๊ฐ’์„ Data ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜
                        print("1")
                        let jsonData = try JSONSerialization.data(withJSONObject: res, options: .prettyPrinted)
                        print("2")
                        let json = try JSONDecoder().decode(Response.self, from: jsonData)
                        print("3")
                        self.dataSource = json.documents
                        print("4")
                        print(self.dataSource)
                        print("5")
                    } catch (let error) {
                        print("catch error : \(error.localizedDescription)")
                    }
                    self.APITextView.text = self.dataSource[2].contents
                case .failure(let error):
                    print("Request failed with error: \(error)")
                }
            }

 

 

โœ… ์ตœ์ข… ์†Œ์Šค์ฝ”๋“œ

import Foundation
import Foundation
import Alamofire

// MARK: - Welcome
struct Response: Codable {
    let meta: Meta
    let documents: [Document]
}

// MARK: - Document
struct Document: Codable {
    let datetime, contents, title: String
    let url: String
}

// MARK: - Meta
struct Meta: Codable {
    let totalCount, pageableCount: Int
    let isEnd: Bool

    enum CodingKeys: String, CodingKey {
        case totalCount = "total_count"
        case pageableCount = "pageable_count"
        case isEnd = "is_end"
    }
}


class ViewController: UIViewController {

    @IBOutlet weak var CallButton: UIButton!
    @IBOutlet weak var APITextView: UITextView!
    
    
    @IBAction func CallButtonClick(_ sender: Any) {
        // ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ํ•จ์ˆ˜ ํ˜ธ์ถœ
        getPost2()
    }
    
    var dataSource = [Document]()
    let url = "https://dapi.kakao.com/v2/search/web"
    let headers : HTTPHeaders = [
        "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
        "Authorization": "KakaoAK {Your REST API Key}",
    ]
    
    let parameters : [String: Any] = [
                "query": "์‚ผ์„ฑ์ „์ž",
                "page": 1,
                "size": 15
            ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func getPost2() {
        
        AF.request(url,
                   method: .get,
                   parameters: parameters,
                   encoding: URLEncoding.default,
                   headers: headers)
            .validate(statusCode: 200..<300)
            .responseJSON { response in
                //์—ฌ๊ธฐ์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ํ™œ์šฉํ•˜์„ธ์š”.
                switch response.result {
                case .success(let res):
                    let resultData = String(data: response.data!, encoding: .utf8)
                    
                    do {
                        // ๋ฐ˜ํ™˜๊ฐ’์„ Data ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜
                        let jsonData = try JSONSerialization.data(withJSONObject: res, options: .prettyPrinted)
                        let json = try JSONDecoder().decode(Response.self, from: jsonData)
                        self.dataSource = json.documents
                    } catch (let error) {
                        print("catch error : \(error.localizedDescription)")
                    }
                    self.APITextView.text = self.dataSource[2].contents
                case .failure(let error):
                    print("Request failed with error: \(error)")
                }
            }
    }

}

 

โœ… ํ–ฅํ›„ ๋ณด์™„์ . 

HTML ํƒœ๊ทธ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

 

1๏ธโƒฃ HTML ํƒœ๊ทธ ์ง€์šฐ๊ธฐ

self.APITextView.text = self.dataSource[2].contents
							.replacingOccurrences(of: self.HTMLtag,
                                              	  with: "",
                                              	  options: .regularExpression,
                                              	  range: nil)

 

 

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ์ •๊ทœํ‘œํ˜„์‹์„ ํ™œ์šฉํ•˜์—ฌ HTML ํƒœ๊ทธ๋ฅผ ์ง€์šธ ์ˆ˜ ์žˆ๋‹ค.

ํƒœ๊ทธ ์ง€์šด ๊ฒฐ๊ณผ๋ฌผ

 

2๏ธโƒฃ input ๋ฐ›์•„์„œ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ถ€๋ถ„ ๋งŒ๋“ค๊ธฐ

 

1. ์Šคํ† ๋ฆฌ๋ณด๋“œ์— SearchBar๋ฅผ ์ถ”๊ฐ€ํ•œ ํ›„์—, Delegate๋ฅผ ์—ฐ๊ฒฐํ•ด์ค€๋‹ค.

extension ViewController : UISearchBarDelegate {
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        let keyword = searchBar.text
        parameters["query"] = keyword
        getPost2()
    }
}

์ด ์ฝ”๋“œ๋Š” ์„œ์น˜๋ฐ”์—์„œ ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ํด๋ฆญํ•˜๋ฉด ์‹คํ–‰๋œ๋‹ค.

 

๐Ÿ”ถ ์„œ์น˜๋ฐ”๋Š” ๊ตณ์ด IBOutlet์„ ์—ฐ๊ฒฐ์„ ์•ˆํ•ด๋„ ๋œ๋‹ค.

 

3๏ธโƒฃ rx์ด์šฉํ•ด์„œ ๊ฒ€์ƒ‰ ๊ตฌํ˜„ํ•˜๊ธฐ (๊ณ ๋‚œ๋„)

 

Comments