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으로 지정합니다.프로젝트 만들기, 1/3단계: 프로젝트 이름 선택
  3. 프로젝트 만들기 옵션을 클릭하며 살펴봅니다. 메시지가 표시되면 Firebase 약관에 동의합니다.
  4. 이 앱에는 애널리틱스를 사용하지 않으므로 Google 애널리틱스 화면에서 이 프로젝트에 Google 애널리틱스 사용 설정 체크박스를 선택 해제합니다.
  5. 마지막으로 프로젝트 만들기를 클릭합니다.

Firebase 프로젝트에 관해 자세히 알아보려면 Firebase 프로젝트 이해를 참고하세요.

Firebase 요금제 업그레이드

Firebase Extensions 및 기본 클라우드 서비스를 사용하려면 Firebase 프로젝트가 사용한 만큼 지불(Blaze) 요금제를 사용해야 합니다. 즉, Cloud Billing 계정에 연결되어 있어야 합니다.

  • Cloud Billing 계정에는 신용카드와 같은 결제 수단이 필요합니다.
  • Firebase와 Google Cloud를 처음 사용하는 경우 $300 크레딧과 무료 체험판 Cloud Billing 계정을 받을 자격이 되는지 확인하세요.
  • 이벤트의 일환으로 이 Codelab을 진행하는 경우 주최자에게 사용 가능한 Cloud 크레딧이 있는지 문의하세요.

프로젝트를 Blaze 요금제로 업그레이드하려면 다음 단계를 따르세요.

  1. Firebase Console에서 요금제 업그레이드를 선택합니다.
  2. Blaze 요금제를 선택합니다. 화면에 표시된 안내에 따라 Cloud Billing 계정을 프로젝트에 연결합니다.
    이 업그레이드의 일환으로 Cloud Billing 계정을 만들어야 하는 경우 Firebase Console에서 업그레이드 과정으로 돌아가서 업그레이드를 완료해야 할 수도 있습니다.

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

빌드 중인 앱에는 Apple 앱에 사용할 수 있는 다음과 같은 몇 가지 Firebase 제품이 사용됩니다.

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

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

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

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

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

Cloud Firestore 설정

이 Swift 애플리케이션은 Cloud Firestore를 사용하여 메모를 저장합니다.

Firebase 프로젝트에서 Cloud Firestore를 설정하는 방법은 다음과 같습니다.

  1. Firebase Console의 왼쪽 패널에서 빌드를 펼친 다음 Firestore 데이터베이스를 선택합니다.
  2. 데이터베이스 만들기를 클릭합니다.
  3. 데이터베이스 ID(default)로 설정된 상태로 둡니다.
  4. 데이터베이스의 위치를 선택하고 다음을 클릭합니다.
    실제 앱의 경우 사용자와 가까운 위치를 선택하려고 합니다.
  5. 테스트 모드에서 시작을 클릭합니다. 보안 규칙에 관한 면책 조항을 읽습니다.
    이 Codelab의 후반부에서 데이터를 보호하는 보안 규칙을 추가합니다. 데이터베이스에 대한 보안 규칙을 추가하지 않은 채 앱을 공개적으로 배포하거나 노출하지 마세요.
  6. 만들기를 클릭합니다.

Firebase용 Cloud Storage 설정

웹 앱은 Firebase용 Cloud Storage를 사용하여 사진을 저장, 업로드, 공유합니다.

Firebase 프로젝트에서 Firebase용 Cloud Storage를 설정하는 방법은 다음과 같습니다.

  1. Firebase Console의 왼쪽 패널에서 빌드를 펼치고 저장소를 선택합니다.
  2. 시작하기를 클릭합니다.
  3. 기본 Storage 버킷의 위치를 선택합니다.
    US-WEST1, US-CENTRAL1, US-EAST1의 버킷은 Google Cloud Storage의 'Always Free' 등급을 활용할 수 있습니다. 다른 모든 위치의 버킷은 Google Cloud Storage 가격 및 사용량을 따릅니다.
  4. 테스트 모드로 시작을 클릭합니다. 보안 규칙에 관한 면책 조항을 읽습니다.
    이 Codelab의 후반부에서 데이터를 보호하는 보안 규칙을 추가합니다. 스토리지 버킷에 대한 보안 규칙을 추가하지 않은 채 앱을 공개적으로 배포하거나 노출하지 마세요.
  5. 만들기를 클릭합니다.

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

앱 실행

이제 앱을 사용해 보겠습니다.

  1. Xcode로 돌아가 iOS 시뮬레이터에서 앱을 실행합니다. 실행 대상 드롭다운에서 먼저 iOS 시뮬레이터 중 하나를 선택합니다.실행 대상 드롭다운에서 iOS 시뮬레이터 선택
  2. 그런 다음 Run 버튼을 클릭하거나 ⌘ + 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 프로젝트 선택기 화면

확장 프로그램 구성

  1. 사용 설정된 API 및 생성된 리소스를 검토합니다.사용 설정된 API 검토
  2. 필수 서비스를 사용 설정합니다.필수 서비스 사용 설정
  3. 모든 서비스가 사용 설정되면 다음을 클릭합니다.모든 서비스를 사용 설정한 후 다음을 클릭합니다.
  4. 이 확장 프로그램에 부여된 액세스 권한을 검토합니다.
  5. 확장 프로그램을 구성합니다.
    • LLM으로 Vertex AI를 선택합니다.
    • 컬렉션 경로: notes
    • 기본 쿼리 한도: 3
    • 입력란 이름: text
    • 출력 필드 이름: embedding
    • 상태 필드 이름:* *status*
    • 기존 문서 삽입:
    • 기존 문서 업데이트:
    • Cloud 함수 위치: us-central1
  6. 확장 프로그램 설치를 클릭하여 설치를 완료합니다.

몇 분 정도 걸릴 수 있습니다. 설치가 완료될 때까지 기다리는 동안 튜토리얼의 다음 섹션으로 이동하여 벡터 임베딩에 관한 배경 정보를 읽어 보세요.

5. 백그라운드

설치가 완료될 때까지 기다리는 동안 Firestore를 사용한 벡터 검색 확장 프로그램의 작동 방식에 관한 배경 정보를 확인하세요.

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

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

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

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

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

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

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

도움말 읽기

Firebase 확장 프로그램에는 작동 방식에 관한 문서가 포함되어 있습니다.

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

샘플 문서 만들기

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

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

쿼리 실행

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

  1. Firebase Console의 Firestore 섹션에서 _firestore-vector-search/index 문서로 이동합니다.
  2. + 컬렉션 시작을 클릭합니다.새 하위 컬렉션 추가
  3. 이름이 queries인 새 하위 컬렉션을 만듭니다.
  4. 새 문서를 만들고 query 필드를 문서 중 하나에 있는 텍스트로 설정합니다. 이 방법은 'Firestore 문서를 Swift로 매핑하는 방법'과 같은 의미론적 쿼리에 가장 적합합니다(추가한 메모 중 하나 이상에 이 주제를 다루는 텍스트가 포함된 경우).검색어 필드 추가
  5. 상태에 오류가 표시될 수 있습니다.오류가 발생했습니다.
  6. 색인이 누락되었기 때문입니다. 누락된 색인 구성을 설정하려면 이 링크를 따라 프로젝트의 Google Cloud 콘솔로 이동한 후 목록에서 프로젝트를 선택합니다.올바른 프로젝트 선택
  7. 이제 Cloud 로그 탐색기에 'FAILED_PRECONDITION: Missing vector index configuration. 다음 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를 사용한 벡터 검색 확장 프로그램에 연결하고 사용자가 자연어 쿼리를 사용하여 메모를 검색할 수 있는 시맨틱 검색 기능을 구현할 차례입니다.

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

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 콘솔에 '함수가 잘못된 인수로 호출되었습니다'라는 오류 메시지가 표시됩니다.

결과 목록이 비어 있는 Notes 앱

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

오류 메시지 분석

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

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

올바른 데이터 유형 사용

확장 프로그램에서 매개변수가 어떤 형식이어야 하는지 확인하려면 확장 프로그램의 문서를 확인하세요.

  1. Firebase Console의 Extensions 섹션으로 이동합니다.
  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의 새 벡터 필드 및 벡터 임베딩을 계산하는 방법에 대해 자세히 알아보려면 문서를 확인하세요.