32YB SOPT/iOS 세미나

[SOPT] iOS_7주차_정규세미나 (Realm을 사용한 LocalDB)

신_이나 2023. 8. 21. 14:50

 

 

23.05.27 SOPT iOS 7주차 정규세미나 내용

 

 

 

1. Realm 이란

Realm 을 사용하는 가장 대표적인 예시는 카카오톡 채팅방이다. 데이터를 끄고 카톡에 들어가더라도 기존의 대화내용을 볼 수 있는데 이는, 데이터 연결이 끊긴 상태에서도 (네트워크 통신이 되지 않는 상태) 정보를 불러올 수 있다는 의미다. 이때 데이터(위의 예시로는 채팅 내역) 을 LocalDB 에 저장하고 불러오기 때문에 가능한데, 이 LocalDB 의 역할을 Realm 이 수행하는 것이다.

 

승찬팟짱님이 말씀주신 Realm 의 장점들 ,,, 빠른 속도가 가장 큰 장점인데 Thread-Safe하지 않다는 단점이 있다고 한다.

 

 

설명을 해주실 때는 User의 정보를 저장하는 법을 예시로 들어주셨는데 아래처럼 구조체를 선언해야 한다.

class User: Object {
    
    @Persisted(primaryKey: true) var id: Int = 0
    @Persisted var name: String = ""
    @Persisted var age: Int = 0
    @Persisted var phoneNumber: Int = 0
    
    convenience init(id: Int, name: String, age: Int, phoneNumber: Int) {
        self.init()
        self.id = id
        self.name = name
        self.age = age
        self.phoneNumber = phoneNumber
    }
}

 

위에서 PrimaryKey 라는 것이 있다. PrimaryKey는 테이블에 대한 고유 식별값으로 테이블에 오직 한 개만 생성이 가능한다. 검색 기준 이라고 생각하면 편할 것 같다. 따라서 nil 일 수 없다!

따라서 class 인 User 는 데이터를 담고 있는 Table 의 이름이며(전체), Persisted 는 각각의 colum (한 줄씩) 이라고 생각할 수 있다.

 

 

 

데이터의 뼈대를 잡았다면 이제 직접 추가해보아야 한다.

final class RealmViewController: UIViewController {

    let localRealm = try! Realm()

		override func viewDidLoad() {
        super.viewDidLoad()
        
        let task1 = User(id: 100, name: "승찬", age: 27, phoneNumber: 01012345678)
         
        try! localRealm.write {
            localRealm.add(task1)
        }

		print(Realm.Configuration.defaultConfiguration.fileURL!)
    }

import RealmSwift 를 추가하고, let localRealm = try! Realm() 를 통해 Realm 에 접근할 수 있다.  

 

 

 

//추가할 때

try! localRealm.write {
       localRealm.add(task)
}

//전체 삭제할 때

try! localRealm.write {
       localRealm.deleteAll()
}

//부분 삭제할 때

try! localRealm.write {
       localRealm.delete(tasks[삭제할대상 번호])
}

//부분 수정할 때

let taskToUpdate = tasks[indexPath.row]

try! localRealm.write {
       taskToUpdate.수정하고싶은컬럼 = 수정할 내용
}

//일괄 수정할 때

var taskToUpdate: Results<User>!

try! localRealm.write {
       taskToUpdate.setValue(수정하고싶은컬럼, forKey: "수정할 내용")
       taskToUpdate.setValue("추가하고싶은컬럼", forKey: "추가할 내용")
}

위와 같이 Realm 을 통해 추가, 삭제, 수정할 수 있다.

 

 

 

이를 통해 3주차에서 진행했던 CarrotTableView 구현 실습에 Realm 을 사용한 기능을 추가하도록 하였다.

 

 

import Foundation

import RealmSwift

class CarrotResult: Object {

    @Persisted(primaryKey: true) var id: Int
    @Persisted var image: String
    @Persisted var product: String
    @Persisted var place: String
    @Persisted var time: String
    @Persisted var tradeStatus: String
    @Persisted var price: Int
    @Persisted var liked: Bool

    convenience init(id: Int, image: String, product: String, place: String, time: String, tradeStatus: String, price: Int, liked: Bool) {

        self.init()

        self.id = id
        self.image = image
        self.product = product
        self.place = place
        self.time = time
        self.tradeStatus = tradeStatus
        self.price = price
        self.liked = liked
    }
}
import UIKit

import RealmSwift

final class RealmViewController: UIViewController {

    let localRealm = try! Realm()

    override func viewDidLoad() {
        super.viewDidLoad()

        let task = CarrotResult(id: 7,
                               image: ".princess",
                               product: "쿠로미 예뿌죠?",
                               place: "쿠로미 나라",
                               time: "3월 28일",
                               tradeStatus: ".completed",
                               price: 1000000,
                               liked: false)

        try! localRealm.write {
            localRealm.add(task)
        }

        print(Realm.Configuration.defaultConfiguration.fileURL!)
    }
}

우선 이런식으로 구조체를 짜주고  task 를 추가하여 Realm 에 데이터를 저장해주었다.

 

 

 

짠! 

 

 

class CarrotViewController: UIViewController {
    
    private let tableView = UITableView()
    
    let realm = try! Realm()
    
    private lazy var dummy : [CarrotResult] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setStyle()
        setLayout()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.dummy = getRealm()
        self.tableView.reloadData()
    }
    
    //Layout, Style 생략
    
    private func getRealm() -> [CarrotResult] {
        let result = realm.objects(CarrotResult.self)
        var array: [CarrotResult] = []
        result.forEach {
            array.append($0)
        }
        return array
    }
}

extension CarrotViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dummy.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        guard let cell = tableView.dequeueReusableCell(withIdentifier: CarrotTableViewCell.identifier, for: indexPath) as? CarrotTableViewCell else { return UITableViewCell() }
        
        let localRealm = try! Realm()
        cell.configureCell(dummy[indexPath.row])
        let taskToUpdate = dummy[indexPath.row]
        cell.handler = {[weak self] in
            guard let self else { return }
            try! localRealm.write {
                print("\(indexPath.row) 짠 \(taskToUpdate.liked)")
                if taskToUpdate.liked == true {
                    taskToUpdate.liked = false
                    tableView.reloadData()
                }
                else {
                    taskToUpdate.liked = true
                    tableView.reloadData()
                }
            }
        }
        
        return cell
    }
}

 

이런식으로 VC 를 구현하여 Realm 에 데이터를 추가하고 받아오는 실습을 구현하였다!