Firebase Extensions로 모바일 앱에 Firestore 벡터 검색 추가

1. 개요

이 Codelab에서는 Firestore 벡터 유사성 검색을 사용하여 앱에 강력한 검색 기능을 추가하는 방법을 알아봅니다. Swift 및 SwiftUI로 작성된 메모 작성 앱을 위한 시맨틱 검색 기능을 구현합니다.

일부 문서가 표시된 Cloud Firestore 콘솔(오른쪽의 iOS 앱에서도 확인 가능)

학습할 내용

준비 사항

  • Xcode 15.3
  • Codelab 샘플 코드 Codelab의 이후 단계에서 다운로드합니다.

2. Firebase 프로젝트 만들기 및 설정

Firebase 벡터 검색 확장 프로그램을 사용하려면 Firebase 프로젝트가 필요합니다. Codelab의 이 부분에서는 새 Firebase 프로젝트를 만들고 Cloud Firestore 및 Firebase 인증과 같은 필수 서비스를 활성화합니다.

Firebase 프로젝트 만들기

  1. Firebase에 로그인합니다.
  2. Firebase Console에서 프로젝트 추가를 클릭한 다음 프로젝트 이름을 Firestore Vector Search Lab으로 지정합니다.프로젝트 만들기(3단계 중 1단계: 프로젝트 이름 선택)
  3. 프로젝트 만들기 옵션을 클릭하여 진행합니다. 메시지가 표시되면 Firebase 약관에 동의합니다.
  4. 이 앱에는 애널리틱스를 사용하지 않으므로 Google 애널리틱스 화면에서 이 프로젝트에 Google 애널리틱스 사용 설정 체크박스를 선택 해제합니다.
  5. 마지막으로 프로젝트 만들기를 클릭합니다.

Firebase 프로젝트에 대한 자세한 내용은 Firebase 프로젝트 이해를 참조하세요.

Console에서 Firebase 제품 사용 설정 및 설정

빌드 중인 앱은 Apple 앱에 사용할 수 있는 몇 가지 Firebase 제품을 사용합니다.

  • Firebase 인증: 사용자가 앱에 쉽게 로그인할 수 있도록 지원합니다.
  • Cloud Firestore: 클라우드에 구조화된 데이터를 저장하고 데이터가 변경되면 즉시 알림을 받을 수 있습니다.
  • 데이터베이스를 보호하기 위한 Firebase 보안 규칙

이러한 제품 중 일부는 특수 구성이 필요하거나 Firebase Console을 사용하여 사용 설정해야 합니다.

Firebase 인증에 익명 인증 사용 설정

이 애플리케이션은 익명 인증을 사용하여 사용자가 먼저 계정을 만들지 않고도 앱을 사용할 수 있도록 합니다. 따라서 온보딩 프로세스가 매끄럽게 진행됩니다. 익명 인증 및 이름이 지정된 계정으로 업그레이드하는 방법에 대해 자세히 알아보려면 익명 인증 권장사항을 참조하세요.

  1. Firebase Console의 왼쪽 패널에서 빌드 > 인증을 클릭합니다. 그런 다음 시작하기를 클릭합니다.Firebase 인증 사용 설정
  2. 이제 인증 대시보드가 표시되며, 여기에서 가입한 사용자를 확인하고 로그인 제공업체를 구성하며 설정을 관리할 수 있습니다.
  3. 로그인 방법 탭을 선택합니다. 이 탭으로 바로 이동하려면 여기를 클릭합니다.
  4. 제공업체 옵션에서 익명을 클릭하고 스위치를 사용으로 전환한 다음 저장을 클릭합니다.

Cloud Firestore 설정

이 Swift 애플리케이션은 Cloud Firestore를 사용하여 메모를 저장합니다. Cloud Firestore를 설정하는 방법은 다음과 같습니다.

  1. Firebase Console의 왼쪽 패널에서 빌드 > Firestore 데이터베이스를 클릭합니다. 그런 다음 데이터베이스 만들기를 클릭합니다.Cloud Firestore 사용 설정
  2. 데이터베이스의 위치를 선택하고 Gemini를 사용할 수 있는 위치를 선택합니다. us-central1만 사용해도 됩니다. 하지만 이 위치는 나중에 변경할 수 없습니다. 다음을 클릭합니다.
  3. 테스트 모드에서 시작 옵션을 선택합니다. 보안 규칙에 대한 면책 조항을 읽습니다. 테스트 모드를 사용하면 개발 중에 데이터베이스에 자유롭게 쓸 수 있습니다.테스트 모드에서 Firestore의 보안 규칙 설정
  4. 만들기를 클릭하여 데이터베이스를 만듭니다.

3. 모바일 앱 연결

이 Codelab 섹션에서는 간단한 메모 앱의 소스 코드를 다운로드하고 방금 만든 Firebase 프로젝트에 연결합니다.

샘플 앱 다운로드

  1. https://github.com/FirebaseExtended/codelab-firestore-vectorsearch-ios로 이동하여 저장소를 로컬 머신에 클론합니다.
  2. Xcode에서 Notes.xcodeproj 프로젝트를 엽니다.

Firebase 프로젝트에 앱 연결

앱에서 Firebase 서비스에 액세스할 수 있도록 하려면 Firebase Console에서 앱을 설정해야 합니다. 여러 클라이언트 애플리케이션을 동일한 Firebase 프로젝트에 연결할 수 있습니다. 예를 들어 Android 또는 웹 앱을 만드는 경우 동일한 Firebase 프로젝트에 연결해야 합니다.

Firebase 프로젝트에 대한 자세한 내용은 Firebase 프로젝트 이해를 참조하세요.

  1. Firebase Console에서 Firebase 프로젝트의 개요 페이지로 이동합니다.Firebase Console의 개요 페이지
  2. iOS+ 아이콘을 클릭하여 iOS 앱을 추가합니다.
  3. Apple 앱에 Firebase 추가 화면에서 Xcode 프로젝트 (com.google.firebase.codelab.Notes)의 번들 ID를 입력합니다.
  4. 원하는 경우 앱 닉네임 (iOS용 참고사항)을 입력할 수 있습니다.
  5. '앱 등록'을 클릭하여 다음 단계로 이동합니다.
  6. GoogleServices-Info.plist 파일을 다운로드합니다.
  7. GoogleServices-Info.plist를 Xcode 프로젝트의 Notes 폴더로 드래그합니다. 이 작업은 Assets.xcassets 파일 아래에 놓는 것이 좋습니다.plist 파일을 Xcode로 드래그
  8. 필요한 경우 항목 복사를 선택하고 대상에 추가에서 메모 대상이 선택되어 있는지 확인한 후 완료를 클릭합니다.파일 추가 옵션 선택 대화상자에서 '필요한 경우 복사' 선택
  9. 이제 Firebase Console에서 나머지 설정 프로세스를 클릭하여 진행할 수 있습니다. 이 섹션의 시작 부분에서 다운로드한 샘플에는 이미 Firebase Apple SDK가 설치되어 있고 초기화도 설정되어 있습니다. 콘솔로 이동을 클릭하여 프로세스를 완료할 수 있습니다.

앱 실행

이제 앱을 실행해 보겠습니다.

  1. Xcode로 돌아가서 iOS 시뮬레이터에서 앱을 실행합니다. 실행 대상 드롭다운에서 iOS 시뮬레이터 중 하나를 먼저 선택합니다.실행 대상 드롭다운에서 iOS 시뮬레이터 선택
  2. 그런 다음 실행 버튼을 클릭하거나 ⌘ + R을 누릅니다.
  3. 시뮬레이터에서 앱이 실행되면 몇 가지 메모를 추가합니다.
  4. Firebase Console에서 Firestore 데이터 브라우저로 이동하면 앱에서 새 메모를 추가할 때 생성되는 새 문서를 확인할 수 있습니다.일부 문서를 보여주는 Cloud Firestore 콘솔과 동일한 문서를 보여주는 iOS 시뮬레이터

4. Firestore 확장 프로그램을 사용한 벡터 검색 설치

Codelab의 이 부분에서는 Firestore 확장 프로그램을 사용한 벡터 검색 확장 프로그램을 설치하고 작업 중인 메모 작성 앱의 요구사항에 맞게 구성합니다.

확장 프로그램 설치 시작

  1. Firestore 섹션에서 확장 프로그램 탭을 클릭합니다.Firestore Console에서 Firebase Extensions 탭 선택
  2. 확장 프로그램 허브 살펴보기를 클릭합니다.Firestore 콘솔의 Firebase Extensions 탭
  3. '벡터'를 입력합니다.
  4. 'Firestore 확장 프로그램을 사용한 벡터 검색'을 클릭합니다.Firebase Extensios Hub 방문 페이지 그러면 확장 프로그램의 세부정보 페이지로 이동하여 확장 프로그램, 작동 방식, 필요한 Firebase 서비스, 구성 방법에 대해 자세히 알아볼 수 있습니다.
  5. Firebase Console에서 설치를 클릭합니다.Firestore를 사용한 벡터 검색 확장 프로그램의 설치 버튼
  6. 모든 프로젝트 목록이 표시됩니다.
  7. 이 Codelab의 첫 번째 단계에서 만든 프로젝트를 선택합니다.Firebase 프로젝트 선택기 화면

확장 프로그램 구성

Firebase Extensions는 Firebase용 Cloud Functions를 활용하므로 프로젝트에서 사용한 만큼만 지불하는 Blaze 요금제를 사용해야 합니다. Firestore 확장 프로그램과 함께 벡터 검색을 사용하려면 먼저 프로젝트를 업그레이드해야 합니다.

  1. 프로젝트 업그레이드를 클릭하여 계속 진행합니다. 프로젝트를 Blaze 요금제로 업그레이드
  2. 기존 결제 계정을 선택하거나 새 결제 계정을 만듭니다. 계속을 클릭합니다.결제 계정 선택
  3. 예산 (예: 10000 KRW)을 설정하고 계속을 클릭한 다음 구매를 클릭합니다.예산 설정하기
  4. 사용 설정된 API와 생성된 리소스를 검토합니다.사용 설정된 API 검토
  5. 필요한 서비스를 사용 설정합니다.필수 서비스 사용 설정
  6. Cloud Storage를 사용 설정할 때 보안 규칙의 테스트 모드를 선택합니다.
  7. Cloud Storage가 Cloud Firestore 인스턴스와 동일한 위치를 사용하는지 확인합니다.
  8. 모든 서비스가 사용 설정되면 다음을 클릭합니다.모든 서비스를 사용 설정한 후 다음을 클릭하세요.
  9. 이 확장 프로그램에 부여된 액세스 권한을 검토하세요.
  10. 확장 프로그램을 구성합니다.
    • LLM으로 Vertex AI를 선택합니다.
    • 컬렉션 경로: notes
    • 기본 쿼리 한도: 3
    • 입력란 이름: text
    • 출력 필드 이름: embedding
    • 상태 필드 이름:* *status*
    • 기존 문서 삽입:
    • 기존 문서 업데이트:
    • Cloud 함수 위치: us-central1
  11. 확장 프로그램 설치를 클릭하여 설치를 완료합니다.

몇 분 정도 소요될 수 있습니다. 설치가 완료되기를 기다리는 동안 튜토리얼의 다음 섹션으로 넘어가 벡터 임베딩에 대한 배경 정보를 읽어보세요.

5. 배경

설치가 완료되기를 기다리는 동안 Firestore를 사용한 벡터 검색 확장 프로그램의 작동 방식에 관한 배경 정보는 다음과 같습니다.

벡터, 임베딩, 벡터 데이터베이스란 무엇인가요?

  • 벡터는 수량의 크기와 방향을 나타내는 수학적 객체입니다. 비교 및 검색이 용이한 방식으로 데이터를 나타내는 데 사용할 수 있습니다.
  • 임베딩은 단어나 구문의 의미를 나타내는 벡터입니다. 다량의 텍스트 코퍼스에서 신경망을 학습시키고 단어 간의 관계를 학습하여 생성됩니다.
  • 벡터 데이터베이스는 벡터 데이터를 저장하고 검색하는 데 최적화된 데이터베이스입니다. 이를 통해 특정 쿼리 벡터와 가장 유사한 벡터를 찾는 프로세스인 효율적인 최근접 이웃 검색이 가능합니다.

벡터 검색은 어떻게 작동하나요?

벡터 검색은 쿼리 벡터를 데이터베이스의 모든 벡터와 비교하는 방식으로 작동합니다. 쿼리 벡터와 가장 유사한 벡터가 검색 결과로 반환됩니다.

두 벡터 간의 유사성은 다양한 거리 측정항목을 사용하여 측정할 수 있습니다. 가장 일반적인 거리 측정항목은 두 벡터 사이의 각도를 측정하는 코사인 유사성입니다.

6. Firestore 확장 프로그램을 사용한 벡터 검색 사용해 보기

이 Codelab 앞부분에서 다운로드한 iOS 앱에서 Firestore 확장 프로그램이 포함된 벡터 검색을 사용하기 전에 Firebase Console에서 확장 프로그램을 사용해 볼 수 있습니다.

도움말 읽기

Firebase Extensions에는 작동 방식에 대한 문서가 포함되어 있습니다.

  1. 확장 프로그램 설치가 완료되면 시작하기 버튼을 클릭합니다. Firebase Console의 Firebase Extensions 개요 페이지
  2. 자세한 내용은 '이 확장 프로그램의 작동 방식' 탭을 확인하세요.
    • 문서를 notes 컬렉션에 추가하여 문서의 임베딩을 계산하는 방법
    • ext-firestore-vector-search-queryCallable 호출 가능 함수를 호출하여 색인을 쿼리하는 방법
    • _firestore-vector-search/index/queries 컬렉션에 쿼리 문서를 추가하여 색인을 쿼리하는 방법
    • 또한 커스텀 임베딩 함수를 설정하는 방법도 설명합니다. 확장 프로그램에서 지원하는 LLM이 요구사항을 충족하지 않고 다른 LLM을 사용하여 임베딩을 계산하려는 경우 유용합니다. Firestore 확장 프로그램을 사용한 벡터 검색 문서
  3. Cloud Firestore 대시보드 링크를 클릭하여 Firestore 인스턴스로 이동합니다.
  4. _firestore-vector-search/index 문서로 이동합니다. 확장 프로그램이 이 Codelab의 이전 단계에서 만든 모든 메모 문서의 임베딩 컴퓨팅을 완료했음을 보여줍니다.Firestore 콘솔 내의 색인 구성
  5. 이를 확인하기 위해 메모 문서 중 하나를 열면 vector<768> 유형의 embedding라는 추가 필드와 status 필드가 표시됩니다.Firestore 콘솔 내의 벡터 임베딩 필드

샘플 문서 만들기

Firebase Console에서 새 문서를 만들어 확장 프로그램이 작동하는 것을 볼 수 있습니다.

  1. Firestore 데이터 브라우저에서 notes 컬렉션으로 이동하여 가운데 열에서 + 문서 추가를 클릭합니다.새 문서 추가
  2. 자동 ID를 클릭하여 고유한 새 문서 ID를 생성합니다.
  3. 문자열 유형의 text 필드를 추가하고 value 필드에 텍스트를 붙여넣습니다. lorem ipsum 또는 다른 임의의 텍스트가 아니어야 합니다. 예를 들어 뉴스 기사를 선택합니다.텍스트 필드 추가
  4. 저장을 클릭합니다.
    • 확장 프로그램이 상태 필드를 추가하여 데이터를 처리 중임을 나타내는 방법을 확인하세요.
    • 잠시 후 값이 vector<768>인 새 필드 embedding가 표시됩니다.
    새 문서의 벡터 임베딩 상태 업데이트

쿼리 실행

Firestore 확장 프로그램을 사용한 벡터 검색에는 앱을 연결하지 않고도 문서 색인을 쿼리할 수 있는 유용한 기능이 있습니다.

  1. Firebase Console의 Firestore 섹션에서 _firestore-vector-search/index 문서로 이동합니다.
  2. + 컬렉션 시작을 클릭합니다.새 하위 컬렉션 추가
  3. 이름이 queries인 새 하위 컬렉션을 만듭니다.
  4. 새 문서를 만들고 query 필드를 문서 중 하나의 텍스트로 설정합니다. 이 방법은 'Swift로 Firestore 문서를 매핑하는 방법' (추가한 메모 중 하나 이상에 이 주제를 설명하는 텍스트가 포함된 경우)과 같은 시맨틱 쿼리에 가장 적합합니다.쿼리 필드 추가
  5. 상태에 오류가 표시될 수 있습니다.오류가 발생했습니다.
  6. 색인이 누락되었기 때문입니다. 누락된 색인 구성을 설정하려면 이 링크로 이동하여 프로젝트의 Google Cloud 콘솔로 이동한 후 목록에서 프로젝트를 선택합니다.올바른 프로젝트 선택
  7. 이제 Cloud 로그 탐색기에 'FAILED_PRECONDITION: 벡터 색인 구성 누락. 다음 gcloud 명령어를 사용하여 필수 색인을 만드세요. ..."로그 탐색기의 오류 메시지
  8. 오류 메시지에는 누락된 색인을 구성하기 위해 실행해야 하는 gcloud 명령어도 포함되어 있습니다.
  9. 명령줄에서 다음 명령어를 실행합니다. 머신에 gcloud CLI가 설치되어 있지 않으면 여기 안내에 따라 설치합니다.
    gcloud alpha firestore indexes composite create --project=INSERT-YOUR=PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
    
    색인을 만드는 데 몇 분 정도 걸립니다. Firebase Console의 Firestore 섹션에 있는 색인 탭에서 진행 상황을 확인할 수 있습니다.새 색인의 상태
  10. 색인이 설정되면 새 쿼리 문서를 만들 수 있습니다.
  11. 이제 결과 필드에 일치하는 문서 ID 목록이 표시됩니다.시맨틱 쿼리의 실행 결과
  12. 이러한 ID 중 하나를 복사하고 notes 컬렉션으로 돌아갑니다.
  13. ⌘+F를 사용하여 복사한 문서 ID를 검색합니다. 이 문서가 쿼리와 가장 정확하게 일치합니다.문서 목록에서 문서 ID 찾기

7. 시맨틱 검색 구현

이제 Firestore 확장 프로그램을 사용하여 모바일 앱을 벡터 검색에 연결하고 사용자가 자연어 쿼리를 사용하여 메모를 검색할 수 있는 시맨틱 검색 기능을 구현할 차례입니다.

쿼리 수행을 위한 호출 가능 함수 연결

Vector Search with Firestore 확장 프로그램에는 모바일 앱에서 호출하여 이 Codelab의 앞부분에서 만든 색인을 쿼리할 수 있는 Cloud 함수가 포함되어 있습니다. 이 단계에서는 모바일 앱과 이 호출 가능 함수를 연결합니다. Firebase의 Swift SDK에는 원격 함수를 원활하게 호출하는 API가 포함되어 있습니다.

  1. Xcode로 돌아가서 이 Codelab의 이전 단계에서 클론한 프로젝트에 있는지 확인합니다.
  2. NotesRepository.swift 파일을 엽니다.
  3. private lazy var vectorSearchQueryCallable: Callable = functions.httpsCallable("")가 포함된 줄을 찾습니다.

호출 가능한 Cloud 함수를 호출하려면 호출할 함수의 이름을 제공해야 합니다.

  1. 프로젝트의 Firebase Console로 이동하고 빌드 섹션에서 함수 메뉴 항목을 엽니다.
  2. 확장 프로그램에서 설치한 함수 목록이 표시됩니다.
  3. 이름이 ext-firestore-vector-search-queryCallable인 항목을 검색하여 이름을 복사합니다.
  4. 코드에 이름을 붙여넣습니다. 다음과 같이 표시됩니다.
    private lazy var vectorSearchQueryCallable: Callable<String, String> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
    

쿼리 함수 호출

  1. performQuery 메서드를 찾습니다.
  2. let result = try await vectorSearchQueryCallable(searchTerm)
    
    를 호출하여 호출 가능 함수 호출

원격 호출이므로 실패할 수 있습니다.

  1. 몇 가지 기본 오류 처리를 추가하여 오류를 포착하고 Xcode의 콘솔에 로깅합니다.
    private func performQuery(searchTerm: String) async -> [String] {
      do {
        let result = try await vectorSearchQueryCallable(searchTerm)
        return [result]
      }
      catch {
        print(error.localizedDescription)
        return []
      }
    }
    

UI 연결

사용자가 메모를 검색할 수 있도록 메모 목록 화면에 검색창을 구현합니다. 사용자가 검색어를 입력하면 이전 단계에서 구현한 performQuery 메서드를 호출해야 합니다. SwiftUI에서 제공하는 searchabletask 뷰 수정자 덕분에 코드 몇 줄만 있으면 됩니다.

  1. 먼저 NotesListScreen.swift 앱을 엽니다
  2. 목록 뷰에 검색창을 추가하려면 .navigationTitle("Notes") 줄 바로 위에 .searchable(text: $searchTerm, prompt: "Search") 뷰 수정자를 추가합니다.
  3. 그런 다음 바로 아래에 다음 코드를 추가하여 검색 함수를 호출합니다.
.task(id: searchTerm, debounce: .milliseconds(800)) {
  await notesRepository.semanticSearch(searchTerm: searchTerm)
}

이 코드 스니펫은 semanticSearch 메서드를 비동기식으로 호출합니다. 800밀리초의 제한 시간을 제공하면 작업 수정자가 사용자의 입력을 0.8초 디바운싱하도록 지시할 수 있습니다. 즉, 사용자가 0.8초 이상 입력을 일시중지한 경우에만 semanticSearch가 호출됩니다.

이제 코드가 다음과 같이 표시됩니다.

...
List(repository.notes) { note in
  NavigationLink(value: note) {
    NoteRowView(note: note)
  }
  .swipeActions {
    Button(role: .destructive, action: { deleteNote(note: note) }) {
      Label("Delete", systemImage: "trash")
    }
  }
}
.searchable(text: $searchTerm, prompt: "Search")
.task(id: searchTerm, debounce: .milliseconds(800)) {
  await notesRepository.semanticSearch(searchTerm: searchTerm)
}
.navigationTitle("Notes")
...

앱 실행

  1. ⌘ + R을 누르거나 실행 버튼을 클릭하여 iOS 시뮬레이터에서 앱을 실행합니다.
  2. 이 Codelab 앞부분에서 앱에 추가한 것과 동일한 메모와 Firebase Console을 통해 추가한 메모가 표시됩니다.
  3. 메모 목록 상단에 검색창이 표시됩니다.
  4. 추가한 문서 중 하나에 나타나는 용어를 입력합니다. 이 역시 'Swift에서 비동기 Firebase API를 호출하는 방법'과 같은 시맨틱 쿼리에 가장 적합합니다(추가한 메모 중 하나 이상에 이 주제를 설명하는 텍스트가 포함된 경우).
  5. 검색 결과가 표시될 것으로 예상하지만 대신 목록 뷰가 비어 있고 Xcode 콘솔에 'The function was added with a invalid parameter'라는 오류 메시지가 표시됩니다.

결과 목록이 비어 있는 Notes 앱

이는 데이터를 잘못된 형식으로 보냈음을 의미합니다.

오류 메시지 분석

  1. 문제를 확인하려면 Firebase Console로 이동하세요.
  2. 함수 섹션으로 이동합니다.
  3. ext-firestore-vector-search-queryCallable 함수를 찾고 세로 점 3개를 클릭하여 더보기 메뉴를 엽니다.
  4. 로그 보기를 선택하여 로그 탐색기로 이동합니다.
  5. 오류가 표시됩니다.
Unhandled error ZodError: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "string",
    "path": [],
    "message": "Expected object, received string"
  }
]

이는 데이터를 잘못된 형식으로 보냈음을 의미합니다.

올바른 데이터 유형 사용

확장 프로그램에서 예상되는 매개변수 형식을 알아보려면 확장 프로그램 설명서를 참고하세요.

  1. Firebase Console의 확장 프로그램 섹션으로 이동합니다.
  2. 관리 ->Firestore 확장 프로그램을 통한 벡터 검색 관리을 클릭합니다.
  3. 이 확장 프로그램의 작동 방식 섹션에서 입력 및 출력 매개변수의 사양을 확인할 수 있습니다.입력 매개변수 및 결과 값 문서
  4. Xcode로 돌아가서 NotesRepository.swift로 이동합니다.
  5. 파일 시작 부분에 다음 코드를 추가합니다.
    private struct QueryRequest: Codable {
      var query: String
      var limit: Int?
      var prefilters: [QueryFilter]?
    }
    
    private struct QueryFilter: Codable {
      var field: String
      var `operator`: String
      var value: String
    
    }
    
    private struct QueryResponse: Codable {
      var ids: [String]
    }
    
    QueryRequest는 확장 프로그램의 문서에 따라 확장 프로그램에 필요한 입력 매개변수 구조와 일치합니다. 또한 나중에 필요한 중첩된 prefilter 속성도 포함되어 있습니다.QueryResponse는 확장 프로그램의 응답 구조와 일치합니다.
  6. 호출 가능 함수 사양을 찾고 입력 및 출력 유형 업데이트
    private lazy var vectorSearchQueryCallable: Callable<QueryRequest, QueryResponse> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
    
  7. performQuery
    private func performQuery(searchTerm: String) async -> [String] {
      do {
        let queryRequest = QueryRequest(query: searchTerm,
                                        limit: 2)
        let result = try await vectorSearchQueryCallable(queryRequest)
        print(result.ids)
        return result.ids
      }
      catch {
        print(error.localizedDescription)
        return []
      }
    }
    
    에서 호출 가능 함수의 호출을 업데이트합니다.

앱 다시 실행

  1. 앱 다시 실행
  2. 메모에 포함된 용어가 포함된 검색어를 입력합니다.
  3. 이제 필터링된 메모 목록이 표시됩니다.

예상 결과가 포함된 앱의 스크린샷

사용자 데이터 사전 필터링

춤을 추며 축하하기 전 - 앱의 현재 버전에 문제가 있습니다. 결과 세트에 모든 사용자의 데이터가 포함되어 있습니다.

다른 시뮬레이터에서 앱을 실행하고 문서를 더 추가하여 이를 확인할 수 있습니다. 새 문서는 해당 시뮬레이터에만 표시됩니다. 다른 시뮬레이터에서 앱을 다시 실행하면 처음 만든 문서만 표시됩니다.

검색을 실행하면 vectorSearchQueryCallable 호출이 다른 사용자에게 속할 수 있는 문서 ID를 반환하는 것을 확인할 수 있습니다. 이를 방지하려면 프리필터를 사용해야 합니다.

performQuery에서 코드를 다음과 같이 업데이트합니다.

  let prefilters: [QueryFilter] = if let uid = user?.uid {
    [QueryFilter(field: "userId", operator: "==", value: uid)]
  }
  else {
    []
  }

  let queryRequest = QueryRequest(query: searchTerm,
                                  limit: 2,
                                  prefilters: prefilters)

로그인한 사용자의 ID를 기준으로 데이터가 사전 필터링됩니다. 예상대로 Firestore 색인을 업데이트해야 합니다.

명령줄에서 다음 명령어를 실행하여 embedding 필드에 userId 및 벡터 임베딩이 모두 포함된 새 Firestore 색인을 정의합니다.

gcloud alpha firestore indexes composite create --project=INSERT-YOUR-PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=order=ASCENDING,field-path=userId --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding

색인 빌드가 완료되면 앱을 다시 실행하여 예상대로 작동하는지 확인합니다.

사전 필터링된 결과 집합

8. 수고하셨습니다

축하합니다. 이 Codelab을 완료했습니다.

이 Codelab을 통해 학습한 내용은 다음과 같습니다.

  • 시맨틱 검색이 사용 설정된 Cloud Firestore 데이터베이스를 설정합니다.
  • 데이터베이스와 상호작용하는 간단한 SwiftUI 앱을 만듭니다.
  • SwiftUI의 검색 가능한 뷰 수정자와 작업 수정자를 사용하여 검색창을 구현합니다.
  • Firestore SDK의 호출 가능 인터페이스를 사용하여 Cloud 함수를 호출하여 데이터베이스에서 시맨틱 검색을 수행합니다.

이 Codelab에서 얻은 지식을 바탕으로 이제 Cloud Firestore의 시맨틱 검색 기능을 활용하여 사용자에게 더 직관적이고 효율적인 검색 환경을 제공하는 강력한 애플리케이션을 빌드할 수 있습니다.

Firestore의 새로운 벡터 필드와 벡터 임베딩을 계산하는 방법에 관한 자세한 내용은 문서를 참고하세요.