일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- swift 모듈화
- 무한스크롤
- webp
- Tuist
- xcode 공백 표시
- .pbxproj
- xcode 엔터 표시
- Cocoa Pod
- SwiftUI
- 테스트 타겟
- 타뷸레이션
- spm 에러
- 팀 개발을 위한 git
- swiftdata
- png
- 메모이제이션
- JPG
- heic
- 함께자라기
- fetchdescriptor
- 코드스쿼드
- contentalignmentpoint
- JPEG
- github 시작하기
- nidthirdpartylogin
- 캐러셀
- NVME
- Firestore
- TestFlight
- 클린 아키텍처
- Today
- Total
Sure, Why not?
Firestore 본문
들어가기에 앞서,
DB를 세팅하기 위해, Firestore를 자연스럽게 학습할 기회가 생겼습니다.
DB, DBMS, SQL 같은 용어들을 대략적으로는 알고 있지만, 갑자기 질문들어오면 어떻게 설명해야 할지 막막할 때가 있기에,
기본 용어를 정리하고 Firestore를 학습하고자 합니다.
🤔 DataBase?
🙋♂️
아래 4가지 특성이 있는 데이터의 집합소라고 생각하면 됩니다.
- 통합된(Integrated) 데이터 → 각 사용자들의 데이터를 한 곳에 모여 있습니다.
- 저장된(Stored) 데이터 → 컴퓨터 하드웨어 저장 장치에 저장되어 있습니다.
- 운영(Operational) 데이터 → 고유 기능을 수행하기 위해 필요로 합니다.
- 공용(Shared) 데이터 → 여러 사용자들이 공동 소유, 관리, 활용합니다.
🤔 DataBase Management System?
🙋♂️
먼저 DB와 DBMS는 다른 개념입니다.
데이터를 효율적으로 Create, Read, Update, Delete할 수 있도록 도와주는 시스템입니다.
DBMS의 기능은 아래 3가지와 같습니다.
- 정의(Definition) 기능
- DB의 구조를 정의합니다.
- 데이터를 담을 공간, 공간의 이름 등
- 조작(Manipulation) 기능
- 데이터의 CRUD 작업을 수행합니다
- 사용자와 DB간의 상호작용을 제공합니다
- 제어(Control) 기능
- 데이터를 다루는 작업을 정확하게 수행합니다.
- 데이터에 대한 권한, 보안 관리를 수행합니다.
- 여러 사용자가 동시에 데이터 처리 접근을 해도, 결과를 정확하게 유지하도록 제어합니다.
🤔 Relational DBMS?
🙋♂️
테이블끼리 서로 관계를 맺고 있는 시스템입니다.
테이블이라 함은 열과 행으로 이루어진 데이터가 저장되는 공간으로 생각하면 됩니다.
우리가 알고 있는 거의 대부분의 DBMS가 관계형임을 알 수 있습니다.
이때, 데이터를 CRUD하는 언어인 SQL로 데이터와 상호작용을 수행합니다.
🤔 그럼 관계형이 아닌 애들은?
🙋♂️
RDBMS에 대항하여 새로운 저장 방식으로,
NoSQL이 등장하게 되었습니다.
SQL이 아니다 라는 뜻이 아니라, No RDBMS의미도 아닌,
BerkeleyDB와 같은 예외처럼 여러 장단점을 가진 예외상황이 있기 때문에,
Not only SQL로 SQL을 더 유연하게 사용하고 싶다 이런 의미로 받아들이면 됩니다.
NoSQL은 문서, 키-값, 그래프 등 유연하게 데이터를 관리하고 싶은 것을 의미합니다.
기존에 관계형은 미리 테이블같은 것을 따로 만들어놔야 하는데,
미리 선언하고, 데이터도 거기에 맞춰서 넣어야 했었습니다.
그러나 NoSQL은
“아 몰랑 우선, 데이터 다 집어넣어” 일단 저장을 하고,
그리고 어떻게 해석할지는 스크립트로 말해줄게처럼,
읽는 건 나중에 걱정하는 것입니다.
로그기록이 많은 서비스에서
우선 빨리빨리 영혼없이 저장해야 할텐데,
이때 RDBMS는 하나하나 저장할때 체크하기 때문에 비교적 느립니다.
그래서 NoSQL을 채택하는 것이죠.
NoSQL은
- 빠른 저장
- 낮은 비용
- 분산 처리
와 같이 강점이 있습니다.
그러나 어떤 조건이 가진 데이터를 찾을 때는 모든 서버가
그 데이터가 해당하는지? 일을 해야하기 때문에
적은 건수로 조회하는 것에 비효율적입니다.
그러나 대량 데이터를 조회할 때는 어차피 다 조회해야하기 때문에
빅데이터에 폭발적인 퍼포먼스를 보여줍니다.
그래서 정리하자면,
DB를 도입할 때,
“뭐가 좋다” → 그래? 써볼까 이런 과정이 아니라
사용용도와 목적에 맞게 검토하여 도입하는 것이 중요합니다.
🤔 Maria DB와 MySQL??
🙋♂️
무료 오픈소스 RDBMS입니다.
2009년 오라클에서 인수된 MySQL이 상용화될 것에 우려해서,
MySQL의 일부 개발자들이 독립해서 만든 DBMS입니다.
MySQL과 MariaDB는 거의 형제라고 봐도 무방합니다.
지금까지, DB관련된 기본 키워드를 정리하였고
Firestore에 대해 학습하는 시간을 가지겠습니다.
🤔 Firestore란?
🙋♂️
Google Firebase 플랫폼에서 제공하는 NoSQL 기반의 클라우드 데이터베이스입니다.
Firestore는 실시간 데이터 동기화와 확장성에 뛰어납니다.
컬렉션 구조로 저장되는 문서로 데이터를 저장합니다.
컬렉션은
- 여러 문서를 담고 있는 폴더 같은 역할을 합니다.
문서는
- 하나의 데이터 단위를 의미합니다.
- JSON과 유사한 구조로 저장합니다.
- 각 문서는 키-값으로 구성되어 있습니다.
필드는
- 문서의 속성을 나타냅니다.
- 키-값으로 실제 데이터가 들어있는 것을 알 수 있습니다.
🤔 Firestore 세팅
🙋♂️
- Firebase에서 프로젝트를 생성합니다.
- plist파일 Xcode에 이동시키기
- 앱에 Firebase를 추가합니다. (SPM or Pod)
- Firebase 초기화코드를 작성합니다.
간단한 예제를 통해 Firestore를 학습하겠습니다.
1. 먼저 유저 모델를 정의하였습니다.
// Model/User.swift
struct User: Identifiable, Codable {
var id: String = UUID().uuidString
var name: String
var age: Int
}
2. Firestore와 상호작용하는 관리자를 만들었습니다.
import FirebaseFirestore
enum FirestoreError: Error {
case documentNotFound
case decodingError
case unknownError
}
class FirestoreManager {
let db = Firestore.firestore()
func addUser(user: User, completion: @escaping (Result<Void, FirestoreError>) -> Void) {
do {
try db.collection("users").document(user.id).setData(from: user) { error in
if let error = error {
print("Error writing user: \\(error)")
completion(.failure(.unknownError))
} else {
completion(.success(()))
}
}
} catch {
completion(.failure(.decodingError))
}
}
func fetchAllUsers(completion: @escaping (Result<[User], FirestoreError>) -> Void) {
db.collection("users").getDocuments { snapshot, error in
if let error = error {
print("Error fetching users: \\(error.localizedDescription)")
completion(.failure(.unknownError))
return
}
guard let documents = snapshot?.documents else {
completion(.failure(.documentNotFound))
return
}
let users: [User] = documents.compactMap { document in
do {
return try document.data(as: User.self)
} catch {
print("Error decoding user: \\(error.localizedDescription)")
return nil
}
}
completion(.success(users))
}
}
}
3. 뷰에서 데이터를 표시하고 관리하는 UI를 구성합니다.
import UIKit
class ViewController: UIViewController {
private let firestoreManager = FirestoreManager()
private let tableView = UITableView()
private let addUserButton = UIButton(type: .system)
var users: [User] = []
var currentUserCount = 10
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
fetchAllUsers()
}
private func setupViews() {
tableView.translatesAutoresizingMaskIntoConstraints = false
addUserButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tableView)
view.addSubview(addUserButton)
addUserButton.setTitle("Add User", for: .normal)
addUserButton.addTarget(self, action: #selector(addUserButtonTapped), for: .touchUpInside)
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UserCell")
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.leftAnchor.constraint(equalTo: view.leftAnchor),
tableView.rightAnchor.constraint(equalTo: view.rightAnchor),
tableView.bottomAnchor.constraint(equalTo: addUserButton.topAnchor, constant: -10),
addUserButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
addUserButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20)
])
}
private func fetchAllUsers() {
firestoreManager.fetchAllUsers { [weak self] result in
switch result {
case .success(let users):
DispatchQueue.main.async {
self?.users = users
self?.tableView.reloadData()
}
case .failure(let error):
DispatchQueue.main.async {
print("Failed to fetch users: \\(error)")
}
}
}
}
@objc private func addUserButtonTapped() {
currentUserCount += 1
let newUser = User(id: UUID().uuidString, name: "호근\\(currentUserCount)", age: currentUserCount)
firestoreManager.addUser(user: newUser) { [weak self] result in
switch result {
case .success:
DispatchQueue.main.async {
self?.users.append(newUser)
self?.tableView.reloadData()
}
case .failure(let error):
DispatchQueue.main.async {
print("Failed to add user: \\(error)")
}
}
}
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath)
let user = users[indexPath.row]
cell.textLabel?.text = "\\(user.name) - Age: \\(user.age)"
return cell
}
}
결과
정리
Firestore를 학습하기 위해,
DB와 관련된 키워드를 정리하였고, 간단한 예제로 Firestore의 추가하고 조회하는 기능을 구현해 보았습니다.
다양한 쿼리 조건과 정렬, 제한사항이 필요한 상황이 온다면,
추후 공식 문서를 참고하여서, 최적화된 데이터 조회 방식을 학습해야 할 것 같습니다.
Reference
'💻' 카테고리의 다른 글
Tuist를 활용한 모듈화 (6) | 2024.10.02 |
---|---|
Dynamic Programming (1) | 2024.09.30 |
HDD, SSD, DRAM의 차이 (0) | 2024.09.11 |
PNG와 JPEG의 차이 (2) | 2024.09.05 |
Memory Leak 메모리 누수 (0) | 2024.09.02 |