1. 소개
목표
Terraform을 사용하여 인프라 및 Firebase 제품의 프로그래매틱 구성을 비롯한 Firebase 프로젝트를 설정하고 관리할 수 있습니다.
이 Codelab에서는 먼저 Terraform 구성 파일을 빌드하여 새 Firebase 프로젝트를 만드는 방법을 설명한 다음, 해당 프로젝트에서 사용할 앱과 Firebase 제품을 구성하는 방법을 설명합니다. 또한 변경사항을 미리 보고 구현하는 등 Terraform 명령줄의 기본사항도 다룹니다.
Terraform으로 Firebase 프로젝트 및 제품을 설정하고 관리하는 방법을 알아보려면 이 Codelab을 확인하세요.
학습할 내용
- Terraform 구성 파일(
*.tf
)을 만드는 방법 - Terraform CLI 명령어를 사용하여 인프라를 관리하는 방법
- 구성을 수정하여 리소스 및 서비스를 업데이트하는 방법
- 실제 웹 앱에 구성을 적용하는 방법 (친근한 채팅이라고 함)
- 여러 환경(프로덕션, 스테이징 등)에서 동시(및 동기화) 구성을 정의하는 방법
필요한 사항
- 터미널/콘솔
- 원하는 IDE/텍스트 편집기(예: WebStorm, Atom, Sublime, VS Code)
- 선택한 브라우저(예: Chrome)
- Google Cloud CLI (gcloud CLI) - 이 CLI를 설치하고 사용자 계정 또는 서비스 계정을 사용하여 로그인합니다.
이 Codelab을 완료하려면 다음 기본 요건을 비롯하여 Terraform 및 관련 용어에 대한 기본적인 지식이 필요합니다.
- Terraform을 설치하고 공식 튜토리얼을 통해 Terraform에 익숙해지세요.
이 Codelab에서는 Terraform을 통해 프로비저닝하는 항목을 테스트하고 상호작용할 수 있도록 실제 샘플 앱을 제공합니다. 이를 위해 다음이 필요합니다.
- 웹 앱용 샘플 코드 - Codelab의 다음 단계에서 이 코드를 다운로드하세요.
- 패키지 관리자 npm(일반적으로 Node.js와 함께 제공됨) - 이러한 도구를 설치합니다.
- Firebase CLI - 이 CLI를 설치하고 로그인합니다.
2. 시작 코드 가져오기
이 Codelab에서는 Terraform을 통해 프로비저닝한 항목을 실제 웹 앱으로 테스트할 수 있습니다. Terraform 프로비저닝 리소스를 사용하는 데 필요한 모든 단계를 이해할 수 있도록 이 작업을 수행하는 것이 좋습니다.
명령줄에서 Codelab의 GitHub 저장소를 클론합니다.
git clone https://github.com/firebase/codelab-friendlychat-web
또는 Git이 설치되어 있지 않으면 저장소를 ZIP 파일로 다운로드할 수 있습니다.
3. Terraform 구성 만들기
Terraform 설정
- 다운로드한 샘플 앱의 코드베이스에서
web
디렉터리의 루트로 이동합니다. - 해당 디렉터리의 루트에서 다음과 같은 초기 설정으로
main.tf
라는 Terraform 구성 파일을 만듭니다.
main.tf# Terraform configuration to set up providers by version. terraform { required_providers { google-beta = { source = "hashicorp/google-beta" version = "~> 4.0" } } } # Configure the provider not to use the specified project for quota check. # This provider should only be used during project creation and initializing services. provider "google-beta" { alias = "no_user_project_override" user_project_override = false } # Configure the provider that uses the new project's quota. provider "google-beta" { user_project_override = true }
각 google-beta
제공업체에는 Terraform의 작업이 할당량을 확인하는 방식을 결정하는 user_project_override
라는 속성이 있습니다. 대부분의 리소스를 프로비저닝하려면 user_project_override = true
를 사용해야 합니다. 즉, 자체 Firebase 프로젝트와 비교하여 할당량을 확인합니다. 그러나 할당량 확인을 허용할 수 있도록 새 프로젝트를 설정하려면 먼저 user_project_override=false
를 사용해야 합니다. Terraform alias
문법을 사용하면 이 Codelab의 다음 단계에서 두 프로바이더 설정을 구분할 수 있습니다.
디렉터리에서 Terraform 초기화
새 구성을 처음 만들려면 구성에 지정된 제공업체를 다운로드해야 합니다.
이 초기화를 실행하려면 main.tf
구성 파일과 동일한 디렉터리의 루트에서 다음 명령어를 실행합니다.
terraform init
4. Terraform을 통해 Firebase 프로젝트 만들기
'Firebase 프로젝트를 만들 때' 각 Firebase 프로젝트는 실제로 Firebase 서비스가 사용 설정된 Google Cloud 프로젝트라는 점에 유의해야 합니다.
기본 Google Cloud 프로젝트 및 API에 대한 블록 추가
- 먼저 기본 Google Cloud 프로젝트를 프로비저닝합니다.
main.tf
구성 파일에 다음 리소스 블록을 추가합니다.
프로젝트 이름 (예:"Terraform FriendlyChat Codelab"
)과 프로젝트 ID (예:"terraform-codelab-your-initials"
)를 지정해야 합니다.name
값은 Firebase 인터페이스 내에서만 사용되며 최종 사용자에게는 표시되지 않습니다. 하지만project_id
값은 Google에 프로젝트를 고유하게 식별하므로 고유한 값을 지정해야 합니다. main.tf... # Create a new Google Cloud project. resource "google_project" "default" { provider = google-beta.no_user_project_override name = "<PROJECT_NAME_OF_YOUR_PROJECT>" project_id = "<PROJECT_ID_OF_YOUR_PROJECT>" # Required for the project to display in any list of Firebase projects. labels = { "firebase" = "enabled" } }
- 다음으로 필요한 기본 API인 Service Usage API와 Firebase Management API를 사용 설정해야 합니다.
이 API 사용 설정은 일반적으로 Firebase Console을 사용하여 Firebase 프로젝트를 만들 때 백그라운드에서 처리되지만, 사용 설정을 하도록 Terraform에 명시적으로 알려야 합니다.main.tf
구성 파일 (새 Cloud 프로젝트를 생성하는 블록 바로 아래에 있음)에 다음 리소스 블록을 추가합니다.
main.tf
Service Usage API를 사용 설정하면 새 프로젝트에서 할당량 확인을 허용할 수 있게 됩니다. 따라서 후속 리소스 프로비저닝 및 서비스 사용 설정 시에는... # Enable the required underlying Service Usage API. resource "google_project_service" "serviceusage" { provider = google-beta.no_user_project_override project = google_project.default.project_id service = "serviceusage.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Enable the required underlying Firebase Management API. resource "google_project_service" "firebase" { provider = google-beta.no_user_project_override project = google_project.default.project_id service = "firebase.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false }
user_project_override
와 함께 제공자를 사용해야 합니다(별칭 필요 없음).
Firebase 서비스를 사용 설정하려면 블록을 추가하세요.
'Firebase 프로젝트 생성'에 필요한 마지막 작업 프로젝트에서 Firebase 서비스를 사용 설정하는 중입니다.
main.tf
구성 파일에서 계속 진행하여 다음 리소스 블록을 추가합니다.
위에서 언급했듯이 이 리소스 블록은 user_project_override
와 함께 공급자를 사용합니다(별칭 필요 없음).
main.tf
...
# Enable Firebase services for the new project created above.
resource "google_firebase_project" "default" {
provider = google-beta
project = google_project.default.project_id
# Wait until the required APIs are enabled.
depends_on = [
google_project_service.firebase,
google_project_service.serviceusage,
]
}
위의 리소스 블록에서 depends_on
절을 볼 수 있습니다. 이 절은 Terraform에 기본 API가 사용 설정될 때까지 기다리라고 지시합니다. 이 절이 없으면 Terraform에서 종속 항목을 알 수 없으며 리소스를 동시에 프로비저닝할 때 오류가 발생할 수 있습니다.
구성 적용
- 새 리소스를 프로비저닝하고 구성 파일에 지정된 API를 사용 설정하려면
main.tf
파일과 동일한 디렉터리 (web
이어야 함)의 루트에서 다음 명령어를 실행합니다.terraform apply
- 터미널에서 Terraform은 수행할 작업 계획을 출력합니다.
모든 것이 예상대로 표시되면yes
를 입력하여 작업을 승인합니다.
main.tfTerraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # google_firebase_project.default will be created + resource "google_firebase_project" "default" { + display_name = (known after apply) + id = (known after apply) + project = "terraform-friendlychat-codelab" + project_number = (known after apply) } # google_project.default will be created + resource "google_project" "default" { + auto_create_network = true + id = (known after apply) + labels = { + "firebase" = "enabled" } + name = "Terraform FriendlyChat Codelab" + number = (known after apply) + project_id = "terraform-friendlychat-codelab" + skip_delete = (known after apply) } # google_project_service.firebase will be created + resource "google_project_service" "firebase" { + disable_on_destroy = false + id = (known after apply) + project = "terraform-friendlychat-codelab" + service = "firebase.googleapis.com" } # google_project_service.serviceusage will be created + resource "google_project_service" "serviceusage" { + disable_on_destroy = false + id = (known after apply) + project = "terraform-friendlychat-codelab" + service = "serviceusage.googleapis.com" } Plan: 4 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes # <----
적용하지 않고 변경사항을 미리보기만 해야 하는 경우 terraform plan
명령어를 대신 사용할 수 있습니다.
변경사항 확인
Terraform 실행이 완료되면 다음 명령어를 실행하여 사용 설정된 모든 Terraform 프로비저닝된 리소스 및 서비스의 상태를 검사할 수 있습니다.
terraform show
다음은 인쇄된 결과의 예입니다. 상태에 프로젝트와 관련된 값이 포함됩니다.
# google_firebase_project.default:
resource "google_firebase_project" "default" {
display_name = "Terraform FriendlyChat Codelab"
id = "projects/terraform-friendlychat-codelab"
project = "terraform-friendlychat-codelab"
project_number = "000000000"
}
# google_project.default:
resource "google_project" "default" {
auto_create_network = true
id = "projects/terraform-friendlychat-codelab"
labels = {
"firebase" = "enabled"
}
name = "Terraform FriendlyChat Codelab"
number = "000000000"
project_id = "terraform-friendlychat-codelab"
}
# google_project_service.firebase:
resource "google_project_service" "firebase" {
disable_on_destroy = false
id = "terraform-friendlychat-codelab/firebase.googleapis.com"
project = "terraform-friendlychat-codelab"
service = "firebase.googleapis.com"
}
# google_project_service.serviceusage:
resource "google_project_service" "serviceusage" {
disable_on_destroy = false
id = "terraform-friendlychat-codelab/serviceusage.googleapis.com"
project = "terraform-friendlychat-codelab"
service = "serviceusage.googleapis.com"
}
또는 Firebase Console에서 프로젝트를 확인하여 프로젝트가 생성되었는지 확인할 수 있습니다.
5. Terraform을 통해 Firebase 앱 등록
Firebase를 사용하려면 Firebase 프로젝트에 앱의 각 플랫폼 변형을 등록해야 합니다. 이 Codelab에서는 실제 앱을 사용하여 Terraform을 통해 프로비저닝하는 항목을 테스트하고 상호작용합니다. 이 앱은 웹 앱이므로 새로 만든 Firebase 프로젝트에 Firebase 웹 앱을 등록하도록 Terraform에 지시해야 합니다.
웹 앱을 등록하는 블록 추가
Firebase 프로젝트에 웹 앱을 등록하려면 main.tf
파일에 다음 리소스 블록을 추가합니다.
웹 앱에 자체 display_name
를 지정해야 합니다. 이 이름은 Firebase 인터페이스 내에서만 사용되며 최종 사용자에게는 표시되지 않습니다.
main.tf
...
# Create a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "default" {
provider = google-beta
project = google_firebase_project.default.project
display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
deletion_policy = "DELETE"
}
구성 적용
- 새 리소스를 프로비저닝하려면
main.tf
파일(web
여야 함)과 동일한 디렉터리의 루트에서 다음 명령어를 실행합니다.terraform apply
이 명령어를 실행해도 새 Google Cloud 프로젝트가 다시 생성되지는 않습니다. Terraform은 지정된 프로젝트 ID의 프로젝트가 이미 존재하는 것을 감지하고 프로젝트의 현재 상태를.tf
파일의 상태와 비교하여 발견된 사항을 변경합니다. - 인쇄된 작업 계획을 검토합니다. 모든 항목이 예상대로 표시되면
yes
을 입력하고 Enter 키를 눌러 작업을 승인합니다.
변경사항 확인
다음 명령어를 실행하여 새로 프로비저닝된 리소스의 상태를 검사할 수 있습니다.
terraform show
또는 Firebase Console에서 앱을 확인하여 앱이 프로젝트에 성공적으로 등록되었는지 확인할 수 있습니다. 프로젝트 설정으로 이동한 후 내 앱 섹션까지 아래로 스크롤합니다.
6. Firebase 인증 설정
인증은 앱에서 중요한 부분입니다. 최종 사용자가 Google 계정으로 웹 앱에 로그인할 수 있도록 허용하려면 Firebase 인증을 사용 설정하고 Google 계정으로 로그인 방법을 설정하면 됩니다.
이 Codelab에서는 Firebase 인증을 설정하는 두 가지 옵션을 제공합니다.
- 옵션 1 (권장): Console에서 Firebase 인증을 설정합니다. GCIP가 필요하지 않습니다.
- 이 옵션을 사용하면 새 프로젝트를 Cloud Billing 계정과 연결할 필요가 없습니다.
- 옵션 2: Google Cloud Identity Platform (GCIP) API를 사용하여 Terraform을 통해 Firebase 인증을 설정합니다.
- 이 옵션을 사용하려면 새 프로젝트를 Cloud Billing 계정과 연결해야 합니다. GCIP에서는 프로젝트가 Blaze 요금제를 사용해야 하기 때문입니다.
옵션 1: Firebase Console을 사용하여 인증 설정
Firebase Console을 사용하여 Firebase 인증을 설정하기 위해 프로젝트에서 Blaze 요금제를 사용하지 않아도 됩니다.
Firebase 인증을 설정하고 Google 계정으로 로그인하는 방법은 다음과 같습니다.
- Firebase Console의 왼쪽 패널에 있는 빌드 섹션을 찾습니다.
- 인증, 시작하기를 차례로 클릭한 다음 로그인 방법 탭을 클릭합니다 (또는 직접 이동하려면 여기를 클릭하세요).
- 새 제공업체 추가를 클릭하고 추가 제공업체 섹션에서 Google을 선택합니다.
- 사용 설정 전환 버튼을 활성화합니다.
- 앱의 공개 이름을
FriendlyChat
과 같이 설정합니다(전 세계적으로 고유할 필요는 없음). - 드롭다운 메뉴에서 프로젝트 지원 이메일을 선택한 다음 저장을 클릭합니다.
- Google이 사용 설정된 로그인 제공업체로 표시됩니다.
옵션 2: Google Cloud Identity Platform (GCIP) API를 사용하여 Terraform을 통해 인증 설정
Terraform을 통해 Firebase 인증을 설정하려면 GCIP API를 사용해야 합니다. 즉, 프로젝트에서 Blaze 요금제를 사용해야 합니다. Cloud Billing 계정을 프로젝트에 연결하여 Blaze 요금제를 사용하도록 Firebase 프로젝트를 업그레이드합니다.
Terraform을 통한 결제 사용 설정
- Cloud Billing 계정이 없는 경우 먼저 Google Cloud 콘솔에서 새 계정을 만듭니다. 이때 결제 계정 ID를 기록해 둡니다. 결제 계정 ID는 프로젝트와 연결된 결제 계정 ID의 결제 페이지에서 확인할 수 있습니다.
- Terraform을 통해 프로젝트에서 결제를 사용 설정하려면
billing_account
속성을main.tf
파일(
main.tf
)의 기존... # Create a new Google Cloud project. resource "google_project" "default" { provider = google-beta.no_user_project_override name = "<PROJECT_NAME_OF_YOUR_PROJECT>" project_id = "<PROJECT_ID_OF_YOUR_PROJECT>" billing_account = "<YOUR_BILLING_ACCOUNT_ID>" # Add this line with your Cloud Billing account ID # Required for the project to display in any list of Firebase projects. labels = { "firebase" = "enabled" } } ...
google_project
리소스에 추가합니다.
Terraform을 통해 Firebase 인증 및 Google 계정으로 로그인 사용 설정
- GCIP로 Firebase 인증을 프로비저닝하려면
main.tf
파일에 다음 리소스 블록을 추가합니다.
main.tf... # Enable the Identity Toolkit API. resource "google_project_service" "auth" { provider = google-beta project = google_firebase_project.default.project service = "identitytoolkit.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Create an Identity Platform config. # Also, enable Firebase Authentication using Identity Platform (if Authentication isn't yet enabled). resource "google_identity_platform_config" "auth" { provider = google-beta project = google_firebase_project.default.project # For example, you can configure to auto-delete anonymous users. autodelete_anonymous_users = true # Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication. depends_on = [ google_project_service.auth, ] }
- Google 계정으로 로그인을 사용 설정하려면 OAuth 클라이언트가 있어야 합니다. API 및 서비스 섹션을 방문하여 이 설정을 수행합니다.
- 이 프로젝트의 클라이언트 ID를 처음 만드는 것이므로 OAuth 동의 화면을 구성해야 합니다.
- OAuth 동의 화면 페이지를 열고 방금 만든 프로젝트를 선택합니다.
- 사용자 유형을 외부로 설정한 다음 만들기를 클릭합니다.
- 다음 화면에서 다음을 완료한 후 저장 및 계속을 클릭합니다.
- 앱의 공개 앱 이름을
FriendlyChat
과 같이 설정합니다 (전역적으로 고유하지 않아도 됨). - 드롭다운 메뉴에서 사용자 지원 이메일을 선택합니다.
- 개발자 연락처 정보에 사용할 이메일을 입력합니다.
- 앱의 공개 앱 이름을
- 다음 화면에서 다음을 완료합니다.
- 범위 페이지에서 기본값을 수락한 다음 저장 후 계속을 클릭합니다.
- 테스트 사용자 페이지에서 기본값을 수락한 다음 저장하고 계속하기를 클릭합니다.
- 요약을 검토한 후 대시보드로 돌아가기를 클릭합니다.
- 다음 단계에 따라 사용자 인증 정보 페이지에서 OAuth 클라이언트를 설정합니다.
- 사용자 인증 정보 만들기를 클릭하고 OAuth 클라이언트 ID를 선택합니다.
- 애플리케이션 유형 드롭다운에서 웹 애플리케이션을 선택합니다.
- Name 필드에 앱 이름을 입력합니다 (예:
FriendlyChat
). 전역적으로 고유하지 않아도 됩니다. - 다음을 설정하여 앱의 URL이 이 OAuth 클라이언트를 사용하도록 허용합니다.
- 승인된 자바스크립트 원본에서 URI 추가를 클릭하고
https://<PROJECT_ID>.firebaseapp.com
을 입력합니다. 여기서<PROJECT_ID>
는main.tf
에서 설정한 프로젝트 ID입니다. - 승인된 리디렉션 URI에서 URI 추가를 클릭하고
https://<PROJECT_ID>.firebaseapp.com/__/auth/handler
를 입력합니다. 여기서<PROJECT_ID>
은main.tf
에서 설정한 프로젝트 ID입니다.
- 승인된 자바스크립트 원본에서 URI 추가를 클릭하고
- 저장을 클릭합니다.
- OAuth 클라이언트 ID 및 클라이언트 보안 비밀번호를 사용하여 Google 계정으로 로그인을 사용 설정하려면
main.tf
파일에 다음 블록을 추가합니다.
main.tf... variable "oauth_client_secret" { type = string description = "OAuth client secret. For this codelab, you can pass in this secret through the environment variable TF_VAR_oauth_client_secret. In a real app, you should use a secret manager service." sensitive = true } resource "google_identity_platform_default_supported_idp_config" "google_sign_in" { provider = google-beta project = google_firebase_project.default.project enabled = true idp_id = "google.com" client_id = "<YOUR_OAUTH_CLIENT_ID>" client_secret = var.oauth_client_secret depends_on = [ google_identity_platform_config.auth ] }
구성 적용
- 구성에 따라 인증을 설정하려면
main.tf
파일(web
여야 함)과 동일한 디렉터리의 루트에서 다음 명령어를 실행합니다.export TF_VAR_oauth_client_secret="<YOUR_OAUTH_CLIENT_SECRET>"
terraform apply
terraform apply
를 실행해도 새 Google Cloud 프로젝트가 다시 생성되지는 않습니다. Terraform은 지정된 프로젝트 ID를 사용하는 프로젝트가 이미 있음을 감지하고 프로젝트의 현재 상태를.tf
파일에 있는 상태와 비교합니다. 그런 다음 발견되는 모든 변경사항을 적용합니다. - 인쇄된 작업 계획을 검토합니다. 모든 항목이 예상대로 표시되면
yes
을 입력하고 Enter 키를 눌러 작업을 승인합니다.
변경사항 확인
- Firebase Console의 왼쪽 패널에서 빌드 섹션을 찾습니다.
- 인증을 클릭한 다음 로그인 방법 탭을 클릭합니다 (또는 직접 이동하려면 여기를 클릭).
- Google이 사용 설정된 로그인 제공업체로 표시됩니다.
7. Firestore 데이터베이스 및 보안 규칙 설정
이 Codelab의 웹 앱에서는 Firestore 데이터베이스에 최종 사용자 간 메시지를 저장합니다.
- 필요한 API를 사용 설정하고 데이터베이스 인스턴스를 프로비저닝하려면
main.tf
파일에 다음 리소스 블록을 추가합니다.
main.tf... # Enable required APIs for Cloud Firestore. resource "google_project_service" "firestore" { provider = google-beta project = google_firebase_project.default.project for_each = toset([ "firestore.googleapis.com", "firebaserules.googleapis.com", ]) service = each.key # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Provision the Firestore database instance. resource "google_firestore_database" "default" { provider = google-beta project = google_firebase_project.default.project name = "(default)" # See available locations: # https://firebase.google.com/docs/firestore/locations location_id = "<NAME_OF_DESIRED_REGION>" # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, # authentication, and Firebase Security Rules. type = "FIRESTORE_NATIVE" concurrency_mode = "OPTIMISTIC" depends_on = [ google_project_service.firestore ] }
<NAME_OF_DESIRED_REGION>
을 데이터베이스를 배치할 리전으로 변경합니다.
프로덕션 앱을 개발할 때는 대부분의 사용자와 가깝고 Cloud Functions와 같은 다른 Firebase 서비스와 동일한 리전에 위치하는 것이 좋습니다. 이 Codelab에서는us-east1
(사우스캐롤라이나)를 사용하거나 가장 가까운 리전 (Cloud Firestore 위치 참고)을 사용할 수 있습니다.- Firebase에서 액세스할 수 있는 모든 Firestore 데이터베이스 인스턴스는 Firebase 보안 규칙으로 보호되어야 합니다.
이 Codelab의 샘플 코드는web
디렉터리의 루트에서 찾을 수 있는firestore.rules
파일에 보안 Firestore 규칙 세트를 제공합니다. - 다음 리소스 블록을 사용하여
main.tf
파일에 추가하여 다음을 실행합니다.- 로컬
firestore.rules
파일에서 Firebase 보안 규칙의 규칙 세트를 만듭니다. - Firestore 인스턴스의 규칙 세트를 출시합니다.
firebase deploy --only firestore:rules
.
main.tf
를 실행하는 것과 동일한 기능을 수행합니다.... # Create a ruleset of Firestore Security Rules from a local file. resource "google_firebaserules_ruleset" "firestore" { provider = google-beta project = google_firebase_project.default.project source { files { name = "firestore.rules" # Write security rules in a local file named "firestore.rules". # Learn more: https://firebase.google.com/docs/firestore/security/get-started content = file("firestore.rules") } } # Wait for Firestore to be provisioned before creating this ruleset. depends_on = [ google_firestore_database.default, ] } # Release the ruleset for the Firestore instance. resource "google_firebaserules_release" "firestore" { provider = google-beta name = "cloud.firestore" # must be cloud.firestore ruleset_name = google_firebaserules_ruleset.firestore.name project = google_firebase_project.default.project # Wait for Firestore to be provisioned before releasing the ruleset. depends_on = [ google_firestore_database.default, ] lifecycle { replace_triggered_by = [ google_firebaserules_ruleset.firestore ] } }
- 로컬
terraform apply
를 실행하여 Firestore 데이터베이스를 프로비저닝하고 보안 규칙을 배포합니다.- 데이터베이스가 프로비저닝되고 보안 규칙이 배포되었는지 확인합니다.
- Firebase Console의 왼쪽 패널에 있는 빌드 섹션을 찾습니다.
- Firestore 데이터베이스 섹션으로 이동한 다음 규칙 탭을 클릭합니다.
8. Cloud Storage 버킷 및 보안 규칙 설정
이 Codelab의 웹 앱에서는 최종 사용자 간에 공유된 이미지를 Cloud Storage 버킷에 저장합니다.
- 필요한 API를 사용 설정하고 Cloud Storage 기본 버킷을 프로비저닝하려면 다음 리소스 블록을
main.tf
파일에 추가합니다.
프로젝트의 기본 Cloud Storage 버킷은 Google App Engine을 통해 프로비저닝되며 Firestore 데이터베이스와 동일한 위치에 있어야 합니다. 자세한 내용은 App Engine 위치를 참고하세요.
프로젝트에 여러 버킷을 만들려면google_storage_bucket
리소스를 사용하여 프로비저닝합니다(이 Codelab에는 표시되지 않음).
main.tf... # Enable required APIs for Cloud Storage for Firebase. resource "google_project_service" "storage" { provider = google-beta project = google_firebase_project.default.project for_each = toset([ "firebasestorage.googleapis.com", "storage.googleapis.com", ]) service = each.key # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Provision the default Cloud Storage bucket for the project via Google App Engine. resource "google_app_engine_application" "default" { provider = google-beta project = google_firebase_project.default.project # See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location # This will set the location for the default Storage bucket and the App Engine App. location_id = "<NAME_OF_DESIRED_REGION_FOR_DEFAULT_BUCKET>" # Must be in the same location as Firestore (above) # Wait until Firestore is provisioned first. depends_on = [ google_firestore_database.default ] } # Make the default Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules. resource "google_firebase_storage_bucket" "default-bucket" { provider = google-beta project = google_firebase_project.default.project bucket_id = google_app_engine_application.default.default_bucket }
- Firebase에 액세스할 수 있는 모든 Cloud Storage 버킷은 Firebase 보안 규칙으로 보호되어야 합니다.
이 Codelab의 샘플 코드는storage.rules
파일에서 안전한 Firestore 규칙 집합을 제공합니다. 이 규칙은web
디렉터리의 루트에서 확인할 수 있습니다. main.tf
파일을 다음 리소스 블록과 함께 추가하여 다음 작업을 실행합니다.- 로컬 파일에서 Firebase 보안 규칙의 규칙 세트를 만듭니다.
- 스토리지 버킷의 규칙 집합을 출시합니다.
firebase deploy --only storage
.
main.tf를 실행하는 것과 동일한 작업을 실행합니다.... # Create a ruleset of Cloud Storage Security Rules from a local file. resource "google_firebaserules_ruleset" "storage" { provider = google-beta project = google_firebase_project.default.project source { files { # Write security rules in a local file named "storage.rules". # Learn more: https://firebase.google.com/docs/storage/security/get-started name = "storage.rules" content = file("storage.rules") } } # Wait for the default Storage bucket to be provisioned before creating this ruleset. depends_on = [ google_firebase_storage_bucket.default-bucket, ] } # Release the ruleset to the default Storage bucket. resource "google_firebaserules_release" "default-bucket" { provider = google-beta name = "firebase.storage/${google_app_engine_application.default.default_bucket}" ruleset_name = "projects/${google_firebase_project.default.project}/rulesets/${google_firebaserules_ruleset.storage.name}" project = google_firebase_project.default.project lifecycle { replace_triggered_by = [ google_firebaserules_ruleset.storage ] } }
terraform apply
를 실행하여 기본 Cloud Storage 버킷을 프로비저닝하고 보안 규칙을 배포합니다.- 버킷이 프로비저닝되었고 보안 규칙이 배포되었는지 확인합니다.
- Firebase Console의 왼쪽 패널에 있는 빌드 섹션을 찾습니다.
- 저장용량 섹션으로 이동한 다음 규칙 탭을 클릭합니다.
9. 로컬에서 앱 실행
이제 처음으로 웹 앱을 실행할 준비가 되었습니다. Firebase 호스팅 에뮬레이터를 사용하여 로컬에서 앱을 제공합니다.
- 새 터미널 창을 열고
web
디렉터리에서 다음 Firebase CLI 명령어를 실행하여 에뮬레이터를 시작합니다.firebase emulators:start --project=<PROJECT_ID>
- 브라우저에서 CLI에서 반환된 로컬 URL(일반적으로
http://localhost:5000
)로 웹 앱을 엽니다.
아직 작동하지 않는 FriendlyChat 앱의 UI가 표시됩니다. 앱이 아직 Firebase에 연결되지 않았지만 이 Codelab의 다음 단계를 완료하면 연결됩니다.
이 Codelab의 다음 단계에서와 같이 웹 앱을 변경할 때마다 브라우저를 새로고침하여 이러한 변경사항으로 로컬 URL을 업데이트합니다.
10. Firebase 설치, 구성, 초기화
앱에서 Firebase를 사용하려면 Firebase SDK 및 Firebase 프로젝트의 Firebase 구성이 필요합니다.
이 Codelab의 샘플 코드는 이미 앱에서 다양한 Firebase 제품을 사용하는 데 필요한 모든 종속 항목과 필수 함수가 포함된 작동하는 앱입니다. 이미 완료된 내용을 확인하려면 web/package.json
및 web/src/index.js
를 살펴보세요.
샘플 코드는 거의 완성되었지만 앱을 실행하려면 Firebase SDK를 설치하고, 빌드를 시작하고, 앱에 Firebase 구성을 추가하고, 마지막으로 Firebase를 초기화하는 등 몇 가지 작업을 더 해야 합니다.
Firebase SDK 설치 및 webpack 빌드 시작
앱 빌드를 시작하려면 몇 가지 명령어를 실행해야 합니다.
- 새 터미널 창을 엽니다.
web
디렉터리의 루트에 있는지 확인합니다.npm install
를 실행하여 Firebase SDK를 다운로드합니다.npm update
를 실행하여 종속 항목을 업데이트합니다.npm run start
를 실행하여 webpack을 시작합니다.
이제 Codelab의 나머지 부분에서 webpack이 소스 코드를 계속 빌드합니다.
앱에 Firebase 구성 추가
또한 Firebase SDK가 사용할 Firebase 프로젝트를 알 수 있도록 Firebase 구성을 앱에 추가해야 합니다.
이 Codelab에서는 Firebase 구성을 가져오는 두 가지 옵션을 사용할 수 있습니다.
- 옵션 1: Firebase Console에서 Firebase 구성을 가져옵니다.
- 옵션 2: Terraform을 통해 Firebase 구성을 가져옵니다.
옵션 1: Firebase Console에서 구성을 가져와 코드베이스에 추가
- Firebase Console에서 프로젝트 설정으로 이동합니다.
- 내 앱 카드까지 아래로 스크롤한 다음 웹 앱을 선택합니다.
- Firebase SDK 스니펫 창에서 구성을 선택한 다음 구성 스니펫을 복사합니다.
- 구성을 앱의
web/src/firebase-config.js
파일에 붙여넣습니다.
firebase-config.js... const config = { apiKey: "<API_KEY>", authDomain: "<PROJECT_ID>.firebaseapp.com", projectId: "<PROJECT_ID>", storageBucket: "<PROJECT_ID>.appspot.com", messagingSenderId: "<SENDER_ID>", appId: "<APP_ID>", measurementId: "<G-MEASUREMENT_ID>", }; ...
옵션 2: Terraform을 통해 구성을 가져와 코드베이스에 추가
또는 Terraform을 통해 Firebase 구성을 CLI의 출력 값으로 가져올 수 있습니다.
main.tf
파일에서google_firebase_web_app
리소스 블록 (프로젝트에 웹 앱을 등록한 블록)을 찾습니다.- 블록 바로 뒤에 다음 블록을 추가합니다.
main.tf... data "google_firebase_web_app_config" "default" { provider = google-beta project = google_firebase_project.default.project web_app_id = google_firebase_web_app.default.app_id } output "friendlychat_web_app_config" { value = { projectId = google_firebase_project.default.project appId = google_firebase_web_app.default.app_id apiKey = data.google_firebase_web_app_config.default.api_key authDomain = data.google_firebase_web_app_config.default.auth_domain storageBucket = lookup(data.google_firebase_web_app_config.default, "storage_bucket", "") messagingSenderId = lookup(data.google_firebase_web_app_config.default, "messaging_sender_id", "") measurementId = lookup(data.google_firebase_web_app_config.default, "measurement_id", "") } } ...
data
블록과output
블록은 인프라를 어떤 식으로든 수정하기 위한 것이 아니므로 다음 명령어만 실행하면 됩니다.- 웹 앱의 Firebase 구성을 디렉터리의 Terraform 상태로 로드하려면 다음 명령어를 실행합니다.
terraform refresh
- Firebase 구성 값을 출력하려면 다음 명령어를 실행합니다.
terraform output –json
다음은 구성의 출력 예입니다. 출력된 출력에는 프로젝트 및 앱의 값이 포함됩니다.{ "friendlychat_web_app_config": { "sensitive": false, "type": [ "object", { "apiKey": "string", "appId": "string", "authDomain": "string", "measurementId": "string", "messagingSenderId": "string", "projectId": "string", "storageBucket": "string" } ], "value": { "apiKey": "<API_KEY>", "appId": "<APP_ID>", "authDomain": "<PROJECT_ID>.firebaseapp.com", "measurementId": "<G-MEASUREMENT_ID>", "messagingSenderId": "<SENDER_ID>", "projectId": "<PROJECT_ID>", "storageBucket": "<PROJECT_ID>.appspot.com" } } }
- 웹 앱의 Firebase 구성을 디렉터리의 Terraform 상태로 로드하려면 다음 명령어를 실행합니다.
value
맵 내에서 값을 복사합니다.- 다음과 같이 이러한 값 (구성)을 앱의
web/src/firebase-config.js
파일에 붙여넣습니다.
firebase-config.js... const config = { apiKey: "<API_KEY>", appId: "<APP_ID>", authDomain: "<PROJECT_ID>.firebaseapp.com", measurementId: "<G-MEASUREMENT_ID>", messagingSenderId: "<SENDER_ID>", projectId: "<PROJECT_ID>", storageBucket: "<PROJECT_ID>.appspot.com", }; ...
앱에서 Firebase 초기화
마지막으로 Firebase를 초기화하려면 앱의 web/src/index.js
파일에 다음을 추가합니다.
...
const firebaseAppConfig = getFirebaseConfig();
initializeApp(firebaseAppConfig);
앱 사용해 보기
이제 Firebase에 대한 모든 구성이 완료되었으므로 웹 앱을 사용해 볼 수 있습니다.
- 앱을 제공하는 브라우저를 새로고침합니다.
- 이제 Google 계정으로 로그인하여 채팅에 메시지를 게시할 수 있습니다. 이미지 파일이 있는 경우 업로드할 수도 있습니다.
11. 환경 간 구성 복제
Terraform은 유사하게 구성된 여러 인프라를 관리하는 데 탁월합니다 (예: 프로덕션 프로젝트와 유사한 스테이징 Firebase 프로젝트 설정).
이 Codelab에서는 스테이징 환경으로 사용할 두 번째 Firebase 프로젝트를 만듭니다.
기존 구성을 복제하여 이 스테이징 프로젝트를 만드는 방법에는 두 가지가 있습니다.
- 옵션 1: Terraform 구성의 사본을 만듭니다.
이 옵션은 복제된 프로젝트가 소스 프로젝트와 얼마나 다를 수 있는지에 대한 유연성을 최대한 제공합니다. - 옵션 2:
for_each
를 사용하여 구성을 재사용합니다.
각 프로젝트가 크게 다르지 않아야 하며 모든 프로젝트에 변경사항을 한 번에 적용하려는 경우 이 옵션을 사용하면 코드를 더 많이 재사용할 수 있습니다.
옵션 1: Terraform 구성 사본 만들기
이 옵션은 표시 이름과 스테이징된 출시가 다른 앱을 사용하는 등 복제된 프로젝트가 소스 프로젝트와 얼마나 다른지에 대해 가장 유연한 방법을 제공합니다.
web
디렉터리의 루트에서main_staging.tf
라는 새 Terraform 구성 파일을 만듭니다.main.tf
파일에서 모든 리소스 블록(terraform
및provider
블록 제외)을 복사한 다음main_staging.tf
파일에 붙여넣습니다.- 그런 다음
main_staging.tf
에서 각 복제된 리소스 블록을 수정하여 스테이징 프로젝트에서 작동하도록 해야 합니다.- 리소스 라벨: 충돌을 방지하기 위해 새 이름을 사용합니다. 예를 들어
resource "google_project" "default"
를resource "google_project" "staging"
로 바꿉니다. - 리소스 참조: 각각을 업데이트합니다. 예를 들어
google_firebase_project.default.project
를google_firebase_project.staging.project
으로 업데이트합니다.
main_staging.tf
파일의 전체 구성을 확인할 수 있습니다.web/terraform-checkpoints/replicate-config/main_staging-copypaste.tf
이 구성을 사용하려면 다음을 실행해야 합니다.main_staging-copypaste.tf
에서 구성을 복사한 다음main_staging.tf
파일에 붙여넣습니다.main_staging.tf
파일에서 다음을 실행합니다.google_project
리소스 블록에서name
속성,project-id
속성, Terraform을 통해 인증을 설정한 경우billing_account
속성을 원하는 값으로 업데이트합니다.google_firebase_web_app
리소스 블록에서display_name
속성을 자체 값으로 업데이트합니다.google_firestore_database
및google_app_engine_application
리소스 블록에서location_id
속성을 원하는 값으로 업데이트합니다.
# Create a new Google Cloud project. resource "google_project" "staging" { provider = google-beta.no_user_project_override name = "<PROJECT_NAME_OF_STAGING_PROJECT>" project_id = "<PROJECT_ID_OF_STAGING_PROJECT" # Required if you want to set up Authentication via Terraform billing_account = "<YOUR_BILLING_ACCOUNT_ID>" # Required for the project to display in any list of Firebase projects. labels = { "firebase" = "enabled" } } # Enable the required underlying Service Usage API. resource "google_project_service" "staging_serviceusage" { provider = google-beta.no_user_project_override project = google_project.staging.project_id service = "serviceusage.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Enable the required underlying Firebase Management API. resource "google_project_service" "staging_firebase" { provider = google-beta.no_user_project_override project = google_project.staging.project_id service = "firebase.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Enable Firebase services for the new project created above. resource "google_firebase_project" "staging" { provider = google-beta project = google_project.staging.project_id # Wait until the required APIs are enabled. depends_on = [ google_project_service.staging_serviceusage, google_project_service.staging_firebase, ] } # Create a Firebase Web App in the new project created above. resource "google_firebase_web_app" "staging" { provider = google-beta project = google_firebase_project.staging.project display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>" deletion_policy = "DELETE" }
- 리소스 라벨: 충돌을 방지하기 위해 새 이름을 사용합니다. 예를 들어
terraform apply
를 실행하여 새 '스테이징' Firebase 프로젝트와 모든 리소스를 프로비저닝하고 서비스를 사용 설정합니다.- 이전과 같이 Firebase Console에서 모든 항목이 예상대로 프로비저닝되고 사용 설정되었는지 확인합니다.
옵션 2: for_each
로 구성 재사용
각 프로젝트가 크게 다르지 않아야 하고 변경사항을 모든 프로젝트에 한 번에 전파하려는 경우 이 옵션은 더 많은 코드 재사용을 제공합니다. Terraform 언어의 for_each
메타 인수를 사용합니다.
main.tf
파일을 엽니다.- 복제할 각 리소스 블록에 다음과 같이
for_each
메타 인수를 추가합니다.
main.tf
이 Codelab의 GitHub 저장소에서# Create new Google Cloud projects. resource "google_project" "default" { provider = google-beta.no_user_project_override name = each.value # Create a unique project ID for each project, with each ID starting with <PROJECT_ID>. project_id = "<PROJECT_ID>-${each.key}" # Required if you want to set up Authentication via Terraform billing_account = "<YOUR_BILLING_ACCOUNT_ID>" # Required for the projects to display in any list of Firebase projects. labels = { "firebase" = "enabled" } for_each = { prod = "<PROJECT_NAME_OF_PROD_PROJECT>" staging = "<PROJECT_NAME_OF_STAGING_PROJECT>" } } # Enable the required underlying Service Usage API. resource "google_project_service" "serviceusage" { provider = google-beta.no_user_project_override for_each = google_project.default project = each.value.project_id service = "serviceusage.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Enable the required underlying Firebase Management API. resource "google_project_service" "firebase" { provider = google-beta.no_user_project_override for_each = google_project.default project = each.value.project_id service = "firebase.googleapis.com" # Don't disable the service if the resource block is removed by accident. disable_on_destroy = false } # Enable Firebase services for each of the new projects created above. resource "google_firebase_project" "default" { provider = google-beta for_each = google_project.default project = each.value.project_id depends_on = [ google_project_service.serviceusage, google_project_service.firebase, ] } # Create a Firebase Web App in each of the new projects created above. resource "google_firebase_web_app" "default" { provider = google-beta for_each = google_firebase_project.default project = each.value.project # The Firebase Web App created in each project will have the same display name. display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>" deletion_policy = "DELETE" } # NOTE: For this codelab, we recommend setting up Firebase Authentication # using the Firebase console. However, if you set up Firebase Authentication # using Terraform, copy-paste from your main.tf the applicable blocks. # Make sure to add the `for_each` meta-argument into each block. # Copy-paste from your main.tf file the applicable resource blocks # for setting up Cloud Firestore (including rules) and # for setting up Cloud Storage for Firebase (including rules). # Make sure to add the `for_each` meta-argument into each block.
for_each
메타 인수를 사용하는main.tf
파일의 전체 구성을 확인할 수 있습니다.web/terraform-checkpoints/replicate-config/main-foreach.tf
이 구성을 사용하려면 다음을 실행해야 합니다.main-foreach.tf
에서 구성을 복사한 후main.tf
파일에 붙여넣습니다.main.tf
파일에서 다음을 수행합니다.google_project
리소스 블록에서name
속성,project-id
속성, (Terraform을 통해 인증을 설정한 경우)billing_account
속성을 자체 값으로 업데이트합니다.google_firebase_web_app
리소스 블록에서display_name
속성을 자체 값으로 업데이트합니다.google_firestore_database
및google_app_engine_application
리소스 블록에서location_id
속성을 원하는 값으로 업데이트합니다.
- 이 구성을 바로 적용하는 대신 Terraform이 기존 인프라와 비교하여 이 구성을 어떻게 해석하는지에 관한 몇 가지 사항을 이해하고 수정하는 것이 중요합니다.
- 현재
for_each
를 사용하는 이 구성을 적용하면 리소스 주소는 다음과 같이 표시됩니다.
그러나 이 Codelab의 첫 번째 부분에서 만든 기존 프로젝트는 Terraform에 다음과 같이 표시됩니다.google_project.default["prod"] google_project.default["staging"] google_firebase_project.default["prod"] google_firebase_project.default["staging"] google_firebase_web_app.default["prod"] google_firebase_web_app.default["staging"]
google_project.default google_firebase_project.default google_firebase_android_app.default
terraform plan
를 실행하여 현재 상태에 따라 Terraform이 어떤 작업을 수행할지 확인합니다.
출력에 Terraform이 이 Codelab의 첫 번째 부분에서 만든 프로젝트를 삭제하고 새 프로젝트 두 개를 만든 것으로 표시됩니다. 이는 Terraform이 주소google_project.default
의 프로젝트가 새 주소google_project.default["prod"]
로 이동되었다는 것을 모르기 때문입니다.- 이 문제를 해결하려면
terraform state mv
명령어를 실행합니다.terraform state mv "google_project.default" "google_project.default[\"prod\"]"
- 마찬가지로 다른 모든 리소스 블록을 수정하려면
main.tf
파일의google_firebase_project
,google_firebase_web_app
, 기타 모든 리소스 블록에 대해terraform state mv
를 실행합니다. - 이제
terraform plan
를 다시 실행하면 Terraform에서 이 Codelab의 첫 번째 부분에서 만든 프로젝트를 삭제한다고 표시되지 않습니다.
- 현재
terraform apply
를 실행하여 새 '스테이징'을 프로비저닝합니다. Firebase 프로젝트와 모든 리소스를 추가하고 서비스를 사용 설정합니다.- 이전과 같이 Firebase Console에서 모든 항목을 확인하여 모든 항목이 예상대로 프로비저닝되고 사용 설정되었는지 확인합니다.
12. 보너스 단계: 스테이징 및 프로덕션 앱 배포
- 앱의 코드베이스에서
firebase-config.js
를 변경하여 대신 스테이징 프로젝트의 Firebase 구성을 사용합니다.
Firebase 구성을 가져와 앱에 추가하는 방법을 다시 확인하려면 이 Codelab의 이전 단계인 앱에 Firebase 구성 추가를 참고하세요. web
디렉터리의 루트에서 다음 명령어를 실행하여 스테이징 Firebase 프로젝트에 앱을 배포합니다.firebase deploy --only hosting --project=<STAGING_PROJECT_ID>
firebase deploy
의 출력에 출력된 URL을 통해 브라우저에서 스테이징 앱을 엽니다. 로그인하여 메시지를 보내고 이미지를 업로드해 보세요.
앱을 Firebase 프로젝트에 배포하면 에뮬레이션된 리소스가 아닌 실제 Firebase 리소스가 사용됩니다. 스테이징 앱과 상호작용하면 Firebase Console의 스테이징 프로젝트에 데이터와 이미지가 표시됩니다.- 스테이징에서 앱을 테스트한 후
firebase-config.js
를 프로덕션 프로젝트의 Firebase 구성(이 Codelab에서 만든 첫 번째 프로젝트)을 사용하도록 다시 변경합니다. web
디렉터리의 루트에서 다음 명령어를 실행하여 프로덕션 Firebase 프로젝트에 앱을 배포합니다.firebase deploy --only hosting --project=<PRODUCTION_PROJECT_ID>
firebase deploy
의 출력에 출력된 URL을 통해 브라우저에서 프로덕션 앱을 엽니다. 로그인하고, 메시지를 보내고, 이미지를 업로드해 보세요.
Firebase Console의 프로덕션 프로젝트에 데이터와 이미지가 표시되는 것을 확인할 수 있습니다.- 이 Codelab의 두 앱과의 상호작용을 완료하면 Firebase에서 앱을 게재하지 못하도록 중지할 수 있습니다. 각 프로젝트에 대해 다음 명령어를 실행합니다.
firebase hosting:disable --project=<STAGING_PROJECT_ID>
firebase hosting:disable --project=<PRODUCTION_PROJECT_ID>
13. 수고하셨습니다.
지금까지 Terraform을 사용하여 실시간 채팅 웹 애플리케이션을 구성했습니다. 또한 스테이징과 프로덕션을 위한 별도의 Firebase 프로젝트를 만들어 개발 환경을 위한 권장사항을 따랐습니다.
학습한 내용
- Terraform CLI를 사용하여 클라우드 리소스 관리
- Terraform을 사용하여 Firebase 제품(인증, Firestore, Cloud Storage, 보안 규칙) 구성
- Firebase 로컬 에뮬레이터 도구 모음을 사용하여 로컬에서 웹 앱 실행 및 테스트
- 웹 앱에 Firebase 가져오기
- Terraform을 사용하여 여러 환경에 구성 복제
Firebase 및 Terraform에 관한 자세한 내용은 문서를 참고하세요. Terraform을 지원하는 모든 Firebase 제품의 목록, 일반적인 사용 사례를 위한 샘플 Terraform 구성, 유용한 문제 해결 및 FAQ를 확인할 수 있습니다.