본문으로 건너뛰기

Cloud Firestore

개요

Cloud Firestore는 Google Cloud의 완전 관리형 NoSQL 문서 데이터베이스로, DTA-WIDE 시스템에서 다음과 같은 용도로 사용됩니다:

  • 사용자 프로필 데이터 저장
  • 애플리케이션 설정 관리
  • 실시간 데이터 동기화
  • 비정형 데이터 저장소

모드 및 구성

DTA-WIDE는 다음과 같은 Firestore 구성을 사용합니다:

  • 모드: Native 모드
  • 리전: europe-west3 (Frankfurt)
  • 데이터베이스 유형: 기본 데이터베이스

다중 데이터베이스 구성

Firestore의 다중 데이터베이스 기능을 활용하여 다음과 같은 용도별 데이터베이스를 구성했습니다:

데이터베이스 ID용도
(default)기본 데이터베이스, 공통 데이터 저장
analytics분석 데이터 저장
dbm-iosiOS 앱 관련 데이터 관리
dbm-androidAndroid 앱 관련 데이터 관리
genai생성형 AI 관련 데이터 저장
logs-mobile모바일 애플리케이션 로그 저장
medical-statement의료 명세서 관련 데이터 저장
mobile공통 모바일 데이터 저장

각 데이터베이스는 독립적인 스토리지 및 처리량 할당량을 가지며, 특정 워크로드에 맞게 최적화되어 있습니다.

데이터 모델

컬렉션 구조

DTA-WIDE 시스템은 다음과 같은 주요 컬렉션을 사용합니다:

컬렉션 이름설명주요 필드
users사용자 프로필 정보email, name, created_at
posts게시물 데이터author_id, title, content, published_at, tags
settings애플리케이션 설정environment, debug_mode, api_timeout
analytics분석 데이터user_id, event_type, timestamp, data

인덱스 설정

성능 최적화를 위해 다음과 같은 복합 인덱스가 구성되어 있습니다:

컬렉션인덱스 필드순서용도
usersemail, created_atASC, DESC사용자 검색 및 정렬
postsauthor_id, published_atASC, DESC작성자별 최신 게시물 조회
poststags, published_atARRAY_CONTAINS, DESC태그별 최신 게시물 조회
analyticsuser_id, event_type, timestampASC, ASC, DESC사용자별 이벤트 분석

액세스 패턴

데이터 읽기

  • 단일 문서 읽기: 문서 ID를 사용한 직접 조회
  • 컬렉션 쿼리: 필터링, 정렬 및 페이징을 적용한 쿼리
  • 실시간 리스너: 데이터 변경 시 실시간 업데이트

데이터 쓰기

  • 단일 문서 쓰기: 개별 문서 생성 및 업데이트
  • 일괄 쓰기: 트랜잭션을 이용한 원자적 업데이트
  • 자동 생성 ID: 문서 ID 자동 생성

보안 규칙

Firestore 보안 규칙은 Firebase Authentication과 함께 사용되어 데이터 액세스를 제어합니다:

rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// 사용자는 자신의 프로필만 읽고 쓸 수 있음
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}

// 게시물은 공개적으로 읽을 수 있지만 작성자만 수정 가능
match /posts/{postId} {
allow read: if true;
allow create: if request.auth != null;
allow update, delete: if request.auth != null &&
request.auth.uid == resource.data.author_id;
}

// 설정은 관리자만 접근 가능
match /settings/{document=**} {
allow read, write: if request.auth != null &&
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
}
}
}

모범 사례

데이터 모델링

  • 중첩 데이터 대신 별도 컬렉션 사용
  • 쿼리 패턴에 맞는 문서 구조 설계
  • 큰 문서 분할 (1MB 제한)

쿼리 최적화

  • 필요한 필드만 조회
  • 적절한 복합 인덱스 구성
  • IN 쿼리 대신 OR 조건 사용 제한

비용 관리

  • 불필요한 인덱스 제거
  • 불필요한 읽기/쓰기 최소화
  • 대량 데이터는 Cloud Storage 사용

다중 데이터베이스 활용

  • 도메인별 워크로드 분리
  • 읽기/쓰기 부하 분산
  • 데이터 격리 및 보안 강화
  • 용도별 확장성 관리

Terraform을 통한 인프라 관리

구현 요소

Firestore를 Terraform으로 관리하기 위해 다음 요소를 구현했습니다:

  1. Terraform 모듈: 재사용 가능한 Firestore 구성
  2. Terragrunt 구성: 환경별 설정값 관리
  3. 배포 파이프라인: CI/CD와 통합

Terraform 모듈 구조

Firestore 모듈은 다음과 같은 구조로 구현되어 있습니다:

infrastructure/
└── terraform/
└── modules/
└── firestore/
├── main.tf # 리소스 정의
├── variables.tf # 입력 변수
├── outputs.tf # 출력 변수
└── README.md # 사용 가이드

주요 기능

  • Native 모드 Firestore 데이터베이스 생성
  • 다중 데이터베이스 관리
  • 컬렉션 인덱스 관리
  • 초기 문서 데이터 설정
  • 필요한 API 활성화

환경별 Terragrunt 구성

개발, 스테이징, 프로덕션 환경별로 다음과 같이 Terragrunt 구성 파일이 작성되어 있습니다:

infrastructure/
└── terragrunt/
├── dev/
│ └── firestore/
│ └── terragrunt.hcl # 개발 환경 구성
├── stage/
│ └── firestore/
│ └── terragrunt.hcl # 스테이징 환경 구성
└── prod/
└── firestore/
└── terragrunt.hcl # 프로덕션 환경 구성

환경별 주요 설정

  • 개발 환경: 기본 인덱스, 디버그 모드 활성화, 전체 데이터베이스 세트
  • 스테이징 환경: 개발 환경과 동일한 인덱스, 디버그 모드 비활성화, 전체 데이터베이스 세트
  • 프로덕션 환경: 추가 인덱스 구성, 성능 최적화 설정, 전체 데이터베이스 세트

배포 방법

Firestore 리소스를 배포하려면 다음 단계를 따릅니다:

사전 요구 사항

  1. 프로젝트가 생성되어 있어야 합니다.
  2. Firestore API가 활성화되어 있어야 합니다:
    gcloud services enable firestore.googleapis.com --project=PROJECT_ID
  3. Terraform 및 Terragrunt가 설치되어 있어야 합니다.
  4. 적절한 GCP 권한이 필요합니다.

배포 단계

개발 환경 배포:

cd infrastructure/terragrunt/dev/firestore
terragrunt init
terragrunt plan
terragrunt apply

프로덕션 환경은 변경 관리 절차를 따라야 합니다:

cd infrastructure/terragrunt/prod/firestore
terragrunt init
terragrunt plan -out=firestore-plan.tfplan
# 계획 검토 및 승인 후
terragrunt apply firestore-plan.tfplan

문제 해결

Provider produced inconsistent result after apply 오류

기존 GCP 프로젝트에 Terraform으로 Firestore 데이터베이스를 프로비저닝할 때 다음과 같은 오류가 발생할 수 있습니다:

Error: Provider produced inconsistent result after apply

When applying changes to google_firestore_database.database, provider
"provider[\"registry.terraform.io/hashicorp/google\"]" produced an
unexpected new value: Root object was present, but now absent.

This is a bug in the provider, which should be reported in the provider's
own issue tracker.

원인:

  • 이 오류는 Firestore 데이터베이스가 이미 존재하는 프로젝트에서 Terraform이 해당 리소스를 새로 생성하려고 할 때 발생합니다.
  • 또는 Terraform 상태와 실제 GCP 상태가 일치하지 않는 경우 발생할 수 있습니다.

해결 방법:

  1. 기존 리소스 임포트:

    # 개발 환경
    cd infrastructure/terragrunt/dev/firestore
    terragrunt import 'google_firestore_database.database' 'PROJECT_ID/(default)'

    # 스테이징 환경
    cd infrastructure/terragrunt/stage/firestore
    terragrunt import 'google_firestore_database.database' 'PROJECT_ID/(default)'

    # 프로덕션 환경
    cd infrastructure/terragrunt/prod/firestore
    terragrunt import 'google_firestore_database.database' 'PROJECT_ID/(default)'

    주의: PROJECT_ID는 각 환경에 맞는 프로젝트 ID로 대체해야 합니다.

    • 개발: dta-cloud-de-dev
    • 스테이징: dta-cloud-de-stage
    • 프로덕션: dta-cloud-de-prod
  2. 임포트 후 재시도: 임포트 후 다시 terragrunt apply 명령을 실행해야 합니다:

    terragrunt apply
  3. 새 환경 설정 시: 새 환경을 설정할 때는 항상 다음 순서를 따르세요:

    1. Firestore API 활성화
    2. 초기 Terraform 상태 임포트
    3. 나머지 리소스 적용

주의사항

  • Firestore 모드(Native/Datastore)는 프로젝트당 한 번만 설정 가능하며 추후 변경 불가
  • 데이터베이스 위치(리전)는 생성 후 변경 불가
  • 인덱스 추가는 즉시 가능하지만 제거는 주의가 필요함
  • Terraform을 통한 대용량 문서 관리는 권장하지 않음 (애플리케이션 코드에서 관리)
  • 다중 데이터베이스는 Firestore Native 모드에서만 지원됨 (Datastore 모드는 지원 안 함)
  • 프로젝트당 최대 100개의 Firestore 데이터베이스 생성 가능

연결 방법

클라이언트 라이브러리

다양한 언어로 Firestore에 접근 가능합니다:

  • Node.js:

    const { Firestore } = require('@google-cloud/firestore');

    // 기본 데이터베이스 연결
    const defaultDb = new Firestore();

    // 특정 데이터베이스 연결
    const analyticsDb = new Firestore({
    databaseId: 'analytics'
    });
  • Python:

    from google.cloud import firestore

    # 기본 데이터베이스 연결
    default_db = firestore.Client()

    # 특정 데이터베이스 연결
    mobile_db = firestore.Client(database='mobile')

인증 설정

서비스 계정을 사용한 인증:

# 환경 변수 설정
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"

주요 기능

  • 실시간 데이터 동기화
  • 오프라인 지원
  • 자동 인덱싱
  • ACID 트랜잭션
  • 다중 데이터베이스 지원

모니터링 및 운영

모니터링 지표

  • 읽기/쓰기 작업 수
  • 인덱스 사용률
  • 스토리지 사용량
  • 오류율
  • 데이터베이스별 성능 지표

성능 최적화

  • 인덱스 최적화
  • 배치 작업 사용
  • 적절한 쿼리 구성
  • 데이터 분산 전략
  • 워크로드에 따른 데이터베이스 분리

변경 이력

버전날짜작성자변경 내용
0.1.02025-03-28bok@weltcorp.com최초 작성