์๋ ํ์ธ์ Foma ์ ๋๋ค!
์ค๋์ Algoria๋ผ๋ API์ ๋ํด์ ์์๋ณด๊ณ ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ๋ ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ฐ๋ก ์์ํ ๊ฒ์~
์๊ณ ๋ฆฌ์๋?๐
์๊ณ ๋ฆฌ์๋ SaaS(Search as a Service) ํ๋ซํผ์ผ๋ก ์ฆ, ๊ฒ์ ์๋น์ค ํ๋ซํผ์ ๋๋ค.
๋ฐฑ์๋,ํ๋ก ํธ์๋,API ํด๋ผ์ด์ธํธ ๋ฑ ๋ค์ํ ํ๊ฒฝ์ผ๋ก API๊ฐ ์ ๊ณต๋ฉ๋๋ค.
๊ฒ์ ์๋น์ค๋ฟ๋ง ์๋๋ผ AI,Analytics ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
๊ฐ๊ฒฉ์ 1000๋ฒ ๊ฒ์์ 1๋ฌ๋ฌ์ ๋๋ค.
(๊ฒ์ 1๋ฒ์ 1์์ด๋... ์ข ๋น์ผ๊ฑฐ ๊ฐ๋ค์...)
์๊ณ ๋ฆฌ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ค ๊ฒ์ด ์ข์๊น์?๐ค
1. ์๋์์ฑ ๊ฒ์๊ธฐ๋ฅ
์๊ณ ๋ฆฌ์๋ ๊ฒ์ ํ ์คํธ์ ๋ฐ๋ผ์ ๊ด๋ จ์๋ ํ ์คํธ๋ฅผ ํฌํจํ๊ฑฐ๋ ๊ด๋ จ์๋ ๋ฐ์ดํฐ๋ค์
๋น ๋ฅด๊ฒ ์ ๊ณตํ์ฌ ์ฌ์ฉ์์๊ฒ ์ข์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
2. ๋์ฌ๋ณด๋
์๊ณ ๋ฆฌ์๋ ์๋์ ๊ฐ์ด ๋ฐ์ดํฐ์ ์ ๋ณด๊ฐ ์ด๋ค ๊ฒ์ด ์๋์ง ๋ณด๊ธฐ ์ฝ๊ฒ ์ ๊ณตํ๋ฉฐ
์ ๋๋ฆฌํฑ์ค๋ ํจ๊ป ์ ๊ณตํ์ฌ ์ ์ ์ ๊ฒ์์ ์ผ๋งํผ ํ์๋์ง ๋ฑ์ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ทธ๋์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋๋ฐ? ๐คจ
๋จผ์ ์๋ ์๊ณ ๋ฆฌ์ ์ฌ์ดํธ๋ก ๊ฐ์ ํ์๊ฐ์ ์ ํด์ค๋๋ค.
๋ก๊ทธ์ธ์ ํ๊ณ ํํ์ด์ง์ ์ค๋ฅธ์ชฝ ์๋จ์ DASHBOARD๋ฅผ ํด๋ฆญํด์ค๋๋ค.
์ผ์ชฝํญ์ API keys๋ฅผ ํญํด์ค๋๋ค.
์ฌ๊ธฐ์ Application ID์ Admin API Key๊ฐ ํ์ํ๋ ์ ์ ์ฅํด์ฃผ์ธ์!
Xcode
์ด์ Xcode๋ก ์ด๋ํด์ ์ฝ์ฝ์ํ์ ์๊ณ ๋ฆฌ์๋ฅผ ์ค์นํด์ค๋๋ค.
pod 'AlgoliaSearchClient', '~> 8.0'
User
์ ์ ์ ๋ณด๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
import Foundation
struct User:Codable {
let name:String
let age:Int
let description:String
init(name:String,age:Int,desc:String) {
self.name = name
self.age = age
self.description = desc
}
}
Storyboard
Searchbar์ ํ ์ด๋ธ๋ทฐ๋ฅผ ์ธํ ํด์ค๋๋ค.
ViewController
AlgoliaSearchClient๋ฅผ import ํด์ฃผ์ธ์!
import AlgoliaSearchClient
์คํ ๋ฆฌ๋ณด๋์์ ์์น๋ฐ์ ํ ์ด๋ธ๋ทฐ๋ฅผ ์ฐ๊ฒฐ์์ผ์ค๋๋ค.
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var table: UITableView!
์์์ ์ ์ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์์ด๋์ ์ด๋๋ฏผ ํค๋ฅผ ์ ์ด์ client๋ฅผ ์ธํ ํด์ฃผ๊ณ
index๋ฅผ users๋ก ์ค์ ํด์ค๋๋ค.( ์ฌ๊ธฐ์๋ user์ ๋ณด๋ฅผ ๋ด์ users๋ผ๊ณ ํ์ง๋ง ์ํ๋ ์ด๋ฆ์ผ๋ก ํ์ ๋ ๋ฉ๋๋ค!)
๊ทธ๋ฆฌ๊ณค user๋ค์ ๋ด์ users๋ฐฐ์ด๊ณผ ๊ฒ์ํ ์ ์ ๋ค์ด ๋ด๊ธธ filterUsers๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
let client = SearchClient(appID: "Application ID", apiKey: "Admin API Key")
lazy var index = client.index(withName: "users")
var users:[User] = []
var filterUsers:[User] = []
์์น๋ฐ ๋๋ฆฌ๊ฒ์ดํธ์ ํ ์ด๋ธ๋ทฐ์ ๋ฐ์ดํฐ์์ค๋ฅผ ์ค์ ํด์ค๋๋ค.
private func configure() {
searchBar.delegate = self
table.dataSource = self
}
ํ ์ด๋ธ๋ทฐ ๋ฐ์ดํฐ์์ค์ ์์น๋ฐ๋๋ฆฌ๊ฒ์ดํธ ๋ฉ์๋๋ฅผ ์ธํ ํด์ค๋๋ค.
extension ViewController:UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filterUsers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
return cell
}
}
extension ViewController:UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
}
}
์ ์ ๋ค์ ์ธํ ํด์ค๋๋ค.
private func setUsers() {
let user1 = User(name: "Foma", age: 26, desc: "์๋
ํ์ธ์ ์ ๋ ํฌ๋ง์
๋๋ค. ๋ง๋์ ๋ฐ๊ฐ์์~")
let user2 = User(name: "gran", age: 27, desc: "์๋
ํ์ธ์ ์ ๋ ๊ทธ๋์
๋๋ค. ์ฒ์๋ต๊ฒ์ต๋๋ค.")
let user3 = User(name: "Fomagran", age: 28, desc: "ํฌ๋ง๊ทธ๋์
๋๋ค!!")
users = [user1,user2,user3]
}
๋ฐ์ดํฐ ์ ์ฅํ๊ธฐ
์์์ ๋ง๋ users๋ฅผ algolia์ ์ ์ฅํด์ค๋๋ค.
private func saveToAlgolia(){
index.saveObjects(users, autoGeneratingObjectID: true) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
}
์คํ์ํจ ๋ค ์๊ณ ๋ฆฌ์ ๋์ฌ๋ณด๋๋ก ์ด๋ํด indices๋ฅผ ๋ณด๋ฉด
index๋ก ๋ง๋ค์ด์ค users๊ฐ ์๊ณ
๊ทธ ์์ ๋ฐ์ดํฐ๋ค์ ์ ์ ์ฅ๋๊ฑธ ๋ณผ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ ์ ๋ ฌํ๊ธฐ
Algolia์ ์๋ ๋ฐ์ดํฐ๋ค์ age๊ธฐ์ค ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํด๋ณด๊ฒ ์ต๋๋ค.
private func sortAlgolia() {
let settings = Settings()
.set(\.customRanking, to: [.asc("age")])
index.setSettings(settings) { result in
switch result {
case .failure(let error):
print("Error when applying settings: \(error)")
case .success:
print("Success")
}
}
}
Algolia ๋์ฌ๋ณด๋๋ก ๊ฐ์ ํ์ธํด๋ณด๋ฉด ๋์ด๊ฐ ์ ์์์ผ๋ก ์ ๋ ฌ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ ์์ ํ๊ธฐ
์ํ๋ ์ค๋ธ์ ํธID๋ฅผ ๋ฃ๊ณ ์์ ํ attribute ์ด๋ฆ๊ณผ ๊ฐ์ ๋ฃ์ ๋ค ์์ ํด์ค๋๋ค.
private func updateObject() {
let updates: [(ObjectID, PartialUpdate)] = [
("1111212002", .update(attribute: "age", value: 30))
]
index.partialUpdateObjects(updates: updates) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
}
Algolia ๋์ฌ๋ณด๋๋ฅผ ํ์ธํด๋ณด๋ฉด ํด๋น objectID๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์ age๊ฐ ์ ๋ณ๊ฒฝ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ ๊ฒ์ํ๊ธฐ
์๋์ ๊ฐ์ด ์์น๋ฐ์ ์ ๋ ฅํ ๊ธ์๊ฐ ํฌํจ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ filterUsers์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ณ
ํ ์ด๋ธ๋ทฐ๋ฅผ reload์์ผ์ฃผ๋ ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
private func searchAlgolia(searchText:String) {
index.search(query: "\(searchText)") { result in
switch result {
case .failure(let error):
print("Error: \(error)")
case .success(let response):
print("Response: \(response.hits)")
do {
self.filterUsers = try response.extractHits()
DispatchQueue.main.async {
self.table.reloadData()
}
} catch let error {
print("Contact parsing error: \(error)")
}
}
}
}
UISearchBarDelegate์ searchBarSearchButtonClicked ๋ฉ์๋์ searchAlgolia ๋ฉ์๋๋ฅผ ๋ฃ์ด์ค๋๋ค.
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchAlgolia(searchText: searchBar.text ?? "")
}
์ด๋ ๊ฒ ์ธํ ํ ๋ค ๊ฒ์์ ํด๋ณด๋ฉด ๊ฒ์์ด๊ฐ ํฌํจ๋ ๋ฐ์ดํฐ๊ฐ ํํฐ๋ง ๋๋๊ฒ์ ๋ณผ ์ ์์ต๋๋ค!
๋ฐ์ดํฐ ์ญ์ ํ๊ธฐ
์ญ์ ํ๊ณ ์ถ์ ์ค๋ธ์ ํธ ์์ด๋๋ฅผ ๋ฃ์ด์ฃผ๊ณ ์ญ์ ํด์ค๋๋ค.
private func deleteObject() {
index.deleteObject(withID: "1111212002") { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
}
Algolia ๋์ฌ๋ณด๋๋ฅผ ๋ณด๋ฉด ํด๋น ์ค๋ธ์ ํธ๊ฐ ์ญ์ ๋๊ฑธ ๋ณผ ์ ์์ต๋๋ค !
์ค๋์ ์ด๋ ๊ฒ Algolia๊ฐ ๋ฌด์์ด๊ณ Algolia์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์์ ํ๊ณ ๊ฒ์ํ๊ณ ์ญ์ ํ๋ ๋ฒ์ ๋ํด์ ์์๋ณด์์ต๋๋ค.
ํน์๋ผ๋ ํ๋ฆฐ ์ ์ด ์๊ฑฐ๋ ๊ถ๊ธํ์ ์ ์ด ์๋ค๋ฉด ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์!
Reference
๋๊ธ