개인 프로젝트를 진행하기 위해 Naver API를 사용해보겠습니당.
🛠️ Contents
먼저 Naver Developers에 접속해서 로그인을 해줍니다.
iOS Bundle ID 확인 방법
- 프로젝트 클릭
- General -> Identify -> Bundle Identifier
애플리케이션 등록하면서 받은 Client ID와 Client Secret을 프로젝트 어딘가에 저장해두고 HTTP 통신할 때 header에 담아서 보내야 한다. 그래야 정상적으로 통신이 가능하다.
하지만 Client ID와 Client Secret은 노출되면 안되기 때문에, 만약 Git 레포지토리에 Public으로 올리는 프로젝트에서 작업 한다면 주의해야 한다.(이런 경우로 과금이 된 사례도 있으니 .. 조심조심 🙏🏻)
그래서 나는 Client ID, Client Secret을 담아둔 파일을 따로 만들고 .gitignore 파일에 올려놨다.
✏️ Storage.swift
struct Storage {
let naverClientID: String = "클라이언트 아이디 복붙"
let naverClientSecret: String = "클라이언트 시크릿 복붙"
}
✏️ .gitignore
Storage.swift
.gitignore 파일 수정 후 commit
✏️ HTTPMethod.swift
enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case put = "PUT"
case head = "HEAD"
case delete = "DELETE"
case patch = "PATCH"
case trace = "TRACE"
case options = "OPTIONS"
case connect = "CONNECT"
}
✏️ Model.swift
struct BookList: Codable {
let total: Int
let start: Int
let display: Int
let items: [Book]
}
struct Book: Codable, Hashable {
let title: String
let image: String
let author: String
let publisher: String
let description: String
}
✏️ requestAPI.swift
import Alamofire
class RequestAPI: ObservableObject {
static let shared = RequestAPI()
private init() { }
@Published var bookList = [Book]()
func requestSearchBookList(query: String) {
let baseURL = "https://openapi.naver.com/v1/search/book.json"
let headers: HTTPHeaders = [
"X-Naver-Client-Id": Storage().naverClientID,
"X-Naver-Client-Secret": Storage().naverClientSecret,
]
let parameters: Parameters = [
"query": query,
"display": 50
]
AF.request(baseURL,
method: .get,
parameters: parameters,
encoding: URLEncoding.default,
headers: headers)
.validate(statusCode: 200...500)
.responseDecodable(of: BookList.self) { response in
switch response.result {
case .success(let data):
guard let statusCode = response.response?.statusCode else { return }
if statusCode == 200 {
DispatchQueue.main.async {
self.bookList = data.items
}
}
print("\(#file) > \(#function) :: SUCCESS")
case .failure(let error):
print("\(#file) > \(#function) :: FAILURE : \(error)")
}
}
}
}
import SwiftUI
struct BookSearchView: View {
@StateObject private var requestAPI = RequestAPI.shared
var body: some View {
NavigationStack {
ScrollView {
ForEach(requestAPI.bookList, id: \.self) { book in
BookSearchRowView(book: book)
}
.searchable(text: $searchKeyword, prompt: "Search for the book you want to find")
.navigationTitle("📗 BookMark")
}
}
.onChange(of: searchKeyword, perform: { _ in
requestAPI.requestSearchBookList(query: searchKeyword)
})
}
}