메인 데이터소스인 Firestore를 조작할 수 있는 추상화 기능을 제공하는 Firestore Service 구현했습니다.
공유사항
이전 회의에서 라이브로 공유드린 문서 디코딩 시 런타임 에러가 발생하는 이슈가 Firebase 패키지 버전 업데이트 후 해결된 부분을 확인했습니다.
21 브랜치에서 Firebase 패키지 버전을 업데이트했습니다.
as-is : 10.21.0
to-be : 10.22.1
✏️ 작업 사항
GSNetowrk 모듈 추가
Firestore Service 인터페이스 프로토콜 정의
Firestore Service 구현체 LiveFirestoreService 구현
사용법
더미 데이터
let chat: Chat = .dummy
let message: Message = .dummy
문서 생성
/// 지정된 컬렉션에 모델을 생성합니다.
/// - Parameters:
/// - in collection: 모델을 생성할 컬렉션입니다.
/// - with model: 저장할 모델의 인스턴스입니다.
func create<T: GSModel>(
in collection: FirestoreCollection,
with model: T
) throws
try service.create(in: .chat, with: chat)
/// 지정된 컬렉션에 모델을 생성합니다.
/// - Parameters:
/// - superCol superCollection: 상위 컬렉션입니다.
/// - superDoc superDocumentID: 상위 문서의 ID입니다.
/// - in collection: 모델을 생성할 컬렉션입니다.
/// - with model: 저장할 모델의 인스턴스입니다.
func create<T: GSModel>(
superCol superCollection: FirestoreCollection,
superDoc superDocumentID: String,
in collection: FirestoreCollection,
with model: T
) throws
try service.create(
superCol: .chat,
superDoc: chat.id,
in: .message,
with: message
)
문서 조회
/// 지정된 컬렉션의 모든 문서를 조회합니다.
/// - Parameters:
/// - from collection: 조회할 컬렉션입니다.
/// - Returns: 해당 컬렉션의 모든 모델을 포함하는 배열을 반환합니다.
func fetch<T: GSModel>(
from collection: FirestoreCollection
) async throws -> [T]
let fetchedChats: [Chat] = try await service.fetch(from: .chat)
/// 지정된 컬렉션과 문서 ID를 사용하여 모델을 조회합니다.
/// - Parameters:
/// - from collection: 조회할 컬렉션입니다.
/// - at documentID: 조회할 문서의 ID입니다.
/// - Returns: 지정된 타입의 모델을 반환합니다.
func fetch<T: GSModel>(
from collection: FirestoreCollection,
at documentID: String
) async throws -> T
let fetchedChat: Chat = try await service.fetch(
from: .chat,
at: chat.id
)
/// 지정된 컬렉션의 모든 문서를 조회합니다.
/// - Parameters:
/// - superCol superCollection: 상위 컬렉션입니다.
/// - superDoc superDocumentID: 상위 문서의 ID입니다.
/// - from collection: 조회할 컬렉션입니다.
/// - Returns: 해당 컬렉션의 모든 모델을 포함하는 배열을 반환합니다.
func fetch<T: GSModel>(
superCol superCollection: FirestoreCollection,
superDoc superDocumentID: String,
from collection: FirestoreCollection
) async throws -> [T]
let fetchedMessages: [Message] = try await service.fetch(
superCol: .chat,
superDoc: chat.id,
from: .knock
)
/// 지정된 컬렉션과 문서 ID를 사용하여 모델을 조회합니다.
/// - Parameters:
/// - superCol superCollection: 상위 컬렉션입니다.
/// - superDoc superDocumentID: 상위 문서의 ID입니다.
/// - from collection: 조회할 컬렉션입니다.
/// - at documentID: 조회할 문서의 ID입니다.
/// - Returns: 지정된 타입의 모델을 반환합니다.
func fetch<T: GSModel>(
superCol superCollection: FirestoreCollection,
superDoc superDocumentID: String,
from collection: FirestoreCollection,
at documentID: String
) async throws -> T
let fetchedMessage: Message = try await service.fetch(
superCol: .chat,
superDoc: chat.id,
from: .message,
at: message.id
)
/// 지정된 컬렉션에서 특정 조건을 만족하는 모든 문서를 조회합니다.
/// - 단일 쿼리일 때 사용합니다. 복합 쿼리를 사용하시려면 getCollectionPath로 컬렉션 경로를 설정하고, .query 체이닝으로 원하는 조건을 설정한 뒤 .fetch를 호출해주세요.
/// - Parameters:
/// - from colRef: 조회할 컬렉션입니다.
/// - where field: 조건을 적용할 필드입니다.
/// - by query: 조건으로 적용할 쿼리 연산자입니다.
/// - Returns: 조건을 만족하는 모든 모델을 포함하는 배열을 반환합니다.
func fetch<T: GSModel>(
from collection: FirestoreCollection,
where field: any FirestoreFieldProtocol,
by query: FirestoreQueryOperation
) async throws -> [T]
let fetchQueryChats: [Chat] = try await service.fetch(
from: .chat,
where: FirestoreField.Chat.createdDate,
by: .orderBy(type: .descending)
)
/// 지정된 컬렉션에서 특정 조건을 만족하는 모든 문서를 조회합니다.
/// - 단일 쿼리일 때 사용합니다. 복합 쿼리를 사용하시려면 getCollectionPath로 컬렉션 경로를 설정하고, .query 체이닝으로 원하는 조건을 설정한 뒤 .fetch를 호출해주세요.
/// - Parameters:
/// - superCol superCollection: 상위 컬렉션입니다.
/// - superDoc superDocumentID: 상위 문서의 ID입니다.
/// - from colRef: 조회할 컬렉션입니다.
/// - where field: 조건을 적용할 필드입니다.
/// - by query: 조건으로 적용할 쿼리 연산자입니다.
/// - Returns: 조건을 만족하는 모든 모델을 포함하는 배열을 반환합니다.
func fetch<T: GSModel>(
superCol superCollection: FirestoreCollection,
superDoc superDocumentID: String,
from collection: FirestoreCollection,
where field: any FirestoreFieldProtocol,
by query: FirestoreQueryOperation
) async throws -> [T]
let fetchQueryMessages: [Message] = try await service.fetch(
superCol: .chat,
superDoc: chat.id,
from: .message,
where: FirestoreField.Message.isRead,
by: .equalTo(value: true)
)
복합 쿼리 조회
문서 조회 코드에 명시된 fetchQuery는 단일 쿼리만 가능합니다.
복합 쿼리가 필요한 경우에는 getCollectionPath으로 경로를 가져오고, 체이닝 방식으로 필요한 쿼리를 적용한 뒤 fetch로 조회할 수 있습니다.
updating 파라미터 배열을 작성할 때, 첫 번째 아이템의 타입까지만 작성하고 나면 두 번째 아이템부터는 필드 타입이 추론되어서 타입 생략으로도 접근이 가능합니다.
/// 지정된 컬렉션의 모델을 업데이트합니다. 모델의 ID를 사용해서 문서를 조회합니다.
/// - Parameters:
/// - in collection: 업데이트 모델이 위치한 컬렉션입니다.
/// - at model: 업데이트할 모델입니다.
/// - updating fields: 업데이트할 필드 리스트입니다.
func update<T: GSModel, U: FirestoreFieldProtocol>(
in collection: FirestoreCollection,
at model: T,
updating fields: [U]
) throws
/// 지정된 컬렉션의 모델을 업데이트합니다. 모델의 ID를 사용해서 문서를 조회합니다.
/// - Parameters:
/// - superCol superCollection: 상위 컬렉션입니다.
/// - superDoc superDocumentID: 상위 문서의 ID입니다.
/// - in collection: 업데이트 모델이 위치한 컬렉션입니다.
/// - at model: 업데이트할 모델입니다.
/// - updating fields: 업데이트할 필드 리스트입니다.
func update<T: GSModel, U: FirestoreFieldProtocol>(
superCol superCollection: FirestoreCollection,
superDoc superDocumentID: String,
in collection: FirestoreCollection,
at model: T,
updating fields: [U]
) throws
개요
메인 데이터소스인 Firestore를 조작할 수 있는 추상화 기능을 제공하는 Firestore Service 구현했습니다.
공유사항
이전 회의에서 라이브로 공유드린 문서 디코딩 시 런타임 에러가 발생하는 이슈가 Firebase 패키지 버전 업데이트 후 해결된 부분을 확인했습니다.
21 브랜치에서 Firebase 패키지 버전을 업데이트했습니다.
✏️ 작업 사항
사용법
더미 데이터
문서 생성
문서 조회
복합 쿼리 조회
문서 조회 코드에 명시된 fetchQuery는 단일 쿼리만 가능합니다.
복합 쿼리가 필요한 경우에는
getCollectionPath
으로 경로를 가져오고, 체이닝 방식으로 필요한 쿼리를 적용한 뒤 fetch로 조회할 수 있습니다.문서 업데이트
try service.update( in: .chat, at: chat, updating: [FirestoreField.Chat.joinedMemberIDs, .createdDate, .lastContent, .unreadMessageCount] )
/// 지정된 컬렉션의 모델을 업데이트합니다. 모델의 ID를 사용해서 문서를 조회합니다. /// - Parameters: /// - superCol superCollection: 상위 컬렉션입니다. /// - superDoc superDocumentID: 상위 문서의 ID입니다. /// - in collection: 업데이트 모델이 위치한 컬렉션입니다. /// - at model: 업데이트할 모델입니다. /// - updating fields: 업데이트할 필드 리스트입니다. func update<T: GSModel, U: FirestoreFieldProtocol>( superCol superCollection: FirestoreCollection, superDoc superDocumentID: String, in collection: FirestoreCollection, at model: T, updating fields: [U] ) throws
try service.update( superCol: .chat, superDoc: chat.id, in: .message, at: message, updating: [FirestoreField.Message.imageContent, .isRead, .sentDate] )