내일배움캠프 iOS

UIKit) TIL # 52 앱개발 심화주차 개인과제 - Lv 2 API 연결

yjuni22 2025. 1. 2. 23:34

 

책 검색 KAKAO API 를 사용하기 위해 

 

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

에서 회원가입 후

 

API 키 발급

 

API 사용이 가능한 키를 발급 받아야 한다.

 


데이터 확인

 

 

사이트 내 REST API 테스트 탭에서

 

응답정보와 명세에 대한 내용을 확인할 수 있었다.

 

스위프트 내에서는 다음 코드를 활용하여 네트워크 통신을 할 수 있다.

예시코드)

    let url = URL(string: "https://dapi.kakao.com/v3/search/book?query=세이노")!
    
    var request = URLRequest(url: url)
    
    request.allHTTPHeaderFields = ["Authorization": "KakaoAK <이 곳에 RESTAPI Key 를 넣으세요.>"]
    
    URLSession.shared.dataTask(with: request) { data, _, _ in
      print(String(data: data!, encoding: .utf8))
    }.resume()

 

모델 구현

- API 의 JSON 데이터를 토대로 사용할 Codabel 모델 구조체 구현

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

// MARK: - Document
struct Document: Codable {
    let authors: [String]?
    let contents: String?
    let price: Int?
    let publisher: String?
    let thumbnail: String?
    let title: String?
}

 

네트워크 매니저

- 서치바의 텍스트를 가지고 네트워킹할 수 있는 네트워크 매니저 구현

//MARK: - 네트워크에서 발생할 수 있는 에러 정의
enum NetworkError: Error {
    case networkingError
    case dataError
    case parseError
}

//MARK: - Networking (서버와 통신하는) 클래스 모델
final class NetworkManager {
    
    static let shared = NetworkManager()
    
    private init() {}
    
    // TypeAlias
    typealias NetworkCompletion = (Result<[Document], NetworkError>) -> Void
    
    // 검색 단어로 네트워킹 요청하는 함수 (책데이터 가져오기)
    func fetchBooks(searchTerm: String, completion: @escaping NetworkCompletion) {
        
        let urlString = "https://dapi.kakao.com/v3/search/book?query=\(searchTerm)"
        
        performRequest(with: urlString) { result in
            completion(result)
        }
    }
    
    // 실제 Request하는 함수
    private func performRequest(with urlString: String, completion: @escaping NetworkCompletion) {
        print(#function)
        guard let url = URL(string: urlString) else { return }
        
        // url로 request 생성
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        
        // 헤더추가
        request.allHTTPHeaderFields = ["Authorization": "KakaoAK API Key"]
        
        let session = URLSession(configuration: .default)
        
        let task = session.dataTask(with: request) { (data, response, error) in
            if error != nil {
                print(error!)
                completion(.failure(.networkingError))
                return
            }
            
            guard let safeData = data else {
                completion(.failure(.dataError))
                return
            }
            
            // 메서드 실행해서, 결과를 받음
            if let books = self.parseJSON(safeData) {
                print("Parse 실행")
                completion(.success(books))
            } else {
                print("Parse 실패")
                completion(.failure(.parseError))
            }
        }
        task.resume()
    }
    
    // 받아본 JSON 데이터 분석하는 함수
    private func parseJSON(_ bookData: Data) -> [Document]? {
        print(#function)
        
        // 성공
        do {
            // (JSON 데이터 -> BookData 구조체)
            let bookData = try JSONDecoder().decode(BookData.self, from: bookData)
            return bookData.documents
            // 실패
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }
}

 

서치 기능 구현

- 서치바 Delegate 에서 네트워킹 실행

 

extension SearchTapViewController: UISearchBarDelegate {
 
    // 검색버튼 눌렀을 때
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        guard let text = searchTapView.searchBar.text else { return }
        self.view.endEditing(true)
        print(text)
        
        // 빈배열로 다시 만들어줌
        self.bookArrays = []
        
        // 서치바에 입력된 텍스트로 네트워킹 시작
        networkManager.fetchBooks(searchTerm: text) { result in
            switch result {
            case .success(let bookDatas):
                self.bookArrays = bookDatas
                DispatchQueue.main.async { [weak self] in
                    self?.searchTapView.searchCollectionView.reloadData()
                }
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }

 

서치바의 Delegate 프로토콜에서 제공되는 기능인

searchBarSearchButtonClicked 메서드에서

서치버튼이 눌렸을 때의 행동을 정의해줄 수 있다.

 

bookArrays에 담겨있는 것을 초기화 해준 뒤

searchBar.text 로 미리 구현해놓은 네트워킹 메서드를 통해

네트워킹을 실행한다.

이후 API 로 받아온 데이터를 할당하고 컬렉션뷰를 메인쓰레드에서 리로드 해준다.

 

셀에 표시될 정보 설정

func collectionView(_ collectionView: UICollectionView, 
                      cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                      
  let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SearchListCell.id, for: indexPath) as! SearchListCell
            
            cell.bookNameLabel.text = bookArrays[indexPath.row].title
            cell.authorNameLabel.text = bookArrays[indexPath.row].authors?.first
            cell.bookPriceLabel.text = "\(bookArrays[indexPath.row].price ?? 0)원"
            
            return cell
        }

 

UICollectionViewDataSource 의 cellForItemAt 에서 구현해둔 셀의 label 에 

API 데이터를 넣은 bookArrays의 indexpath.row 번째에 해당하는 데이터를 각각 넣어준다.

 

 

검색기능이 잘 불러와지고 셀이 그려지는 것을 확인했다.