이 가이드에서는 Go 애플리케이션을 App Lifecycle Manager 기능 플래그와 통합하는 방법을 설명합니다. App Lifecycle Manager에서 관리하는 플래그를 평가하기 위해 flagd 프로바이더와 함께 OpenFeature SDK를 사용하는 방법을 알아봅니다. 이를 통해 Go 서비스에서 기능 가용성 및 동작을 동적으로 제어할 수 있습니다.
이 가이드에서는 다음 빠른 시작 중 하나를 완료하여 필요한 App Lifecycle Manager 리소스 (예: SaaS 제품, 단위 종류, 단위, 플래그, 출시)를 이미 설정했다고 가정합니다.
- 빠른 시작: App Lifecycle Manager (통합)로 기능 플래그 배포: App Lifecycle Manager로 애플리케이션 배포를 관리하는 경우
- 빠른 시작: 기능 플래그 독립형 사용: 애플리케이션 인프라를 독립적으로 관리하지만 기능 플래그 관리에 App Lifecycle Manager를 사용하려는 경우
기본 요건
시작하기 전에 다음 사항을 확인하세요.
- Go 설치됨: 버전 1.23 이상
- App Lifecycle Manager 기능 플래그 빠른 시작 완료:
- 통합 또는 독립형 기능 플래그 빠른 시작을 완료하여 대상 단위를 프로비저닝했습니다.
- 이 빠른 시작의 환경 변수 또는 값(예:
PROJECT_ID,LOCATION_1(단위의 리전),UNIT_ID,FLAG_KEY)이 있어야 합니다.
애플리케이션 기본 사용자 인증 정보 (ADC)에 대해 인증된
gcloud: Go 애플리케이션은 ADC를 사용하여 Google Cloud 서비스에 인증합니다. 로컬에서 실행하는 경우 (독립형 사용 또는 로컬 Docker 테스트) 환경에서 인증했는지 확인합니다.gcloud auth application-default loginIAM 권한: Go 애플리케이션을 실행하는 ID에는 플래그 구성을 읽기 위해프로젝트에 대한
roles/saasconfig.viewerIdentity and Access Management 역할이 필요합니다. Google Cloudgcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="user:YOUR_EMAIL_ADDRESS" \ --role="roles/saasconfig.viewer"YOUR_PROJECT_ID및YOUR_EMAIL_ADDRESS를 적절하게 바꿉니다.
주요 환경 변수 이해
Go 애플리케이션은 환경 변수를 사용하여 올바른 플래그 구성에 연결하고 원하는 플래그를 평가합니다.
FLAGD_SOURCE_PROVIDER_ID: App Lifecycle Manager 서비스에서 가져올 기능 플래그 구성을 지정합니다. 단위와 연결된FeatureFlagConfig의 전체 리소스 이름이어야 합니다.- 형식:
projects/PROJECT_ID/locations/LOCATION/featureFlagsConfigs/UNIT_ID - 예:
projects/my-gcp-project/locations/us-central1/featureFlagsConfigs/my-app-instance-01
- 형식:
Go 프로젝트 설정
애플리케이션을 실행하기 전에 모듈을 초기화하고 필요한 초기화 및 평가 로직을 추가합니다.
프로젝트 디렉터리 만들기:
mkdir go-featureflag-app cd go-featureflag-app go mod init go-featureflag-app애플리케이션 코드 만들기: 다음 콘텐츠로
main.go라는 파일을 추가하여 프로바이더를 초기화하고 플래그를 평가합니다.package main import ( "context" "fmt" "log" "os" flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg" "github.com/open-feature/go-sdk/openfeature" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/oauth" "google.golang.org/grpc/metadata" ) // GetNewFlagdProvider initializes a flagd provider configured for App Lifecycle Manager func GetNewFlagdProvider(ctx context.Context) (*flagd.Provider, error) { providerID := os.Getenv("FLAGD_SOURCE_PROVIDER_ID") if providerID == "" { return nil, fmt.Errorf("FLAGD_SOURCE_PROVIDER_ID environment variable is not set") } creds, err := oauth.NewApplicationDefault(ctx) if err != nil { return nil, err } // Interceptor to inject the Unit name into headers for regional routing routingInterceptor := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("name=%s", providerID)) ctx = metadata.NewOutgoingContext(ctx, md) return streamer(ctx, desc, cc, method, opts...) } options := []flagd.ProviderOption{ flagd.WithHost("saasconfig.googleapis.com"), flagd.WithPort(443), flagd.WithInProcessResolver(), flagd.WithProviderID(providerID), flagd.WithGrpcDialOptionsOverride([]grpc.DialOption{ grpc.WithTransportCredentials(credentials.NewTLS(nil)), grpc.WithPerRPCCredentials(creds), grpc.WithStreamInterceptor(routingInterceptor), }), } return flagd.NewProvider(options...) } // InitializeFeatureManagement registers the provider globally func InitializeFeatureManagement(ctx context.Context) error { provider, err := GetNewFlagdProvider(ctx) if err != nil { return err } openfeature.SetProvider(provider) return nil } func main() { ctx := context.Background() InitializeFeatureManagement(ctx); // 1. Get Client client := openfeature.NewClient("simple-api") // 2. Create Evaluation Context evalCtx := openfeature.NewEvaluationContext() // 3. Evaluate Flag // Default to false if evaluation fails isEnhanced, err := client.BooleanValue(context.Background(), "enhanced-search", false, evalCtx) if err != nil { log.Printf("Flag evaluation failed: %v", err) } // 4. Return response if isEnhanced { fmt.Println("Enhanced search feature is enabled.") } else { fmt.Println("Enhanced search feature is disabled.") } }go.mod 만들기: 특정 버전을 사용하면 안정성이 보장됩니다.
module go-featureflag-app go 1.23 require ( github.com/open-feature/go-sdk v1.15.1 github.com/open-feature/go-sdk-contrib/providers/flagd v0.3.0 google.golang.org/grpc v1.74.2 golang.org/x/oauth2 v0.22.0 )종속 항목 가져오기:
go mod tidy go mod download
Go 애플리케이션 실행
독립형 구성을 사용하여 로컬에서 또는 컨테이너로 배포하여 애플리케이션을 실행할 수 있습니다.
독립형 (로컬) 실행
환경 변수 설정:
export PROJECT_ID="your-gcp-project-id" export LOCATION_1="us-central1" export UNIT_ID="my-app-instance-01" export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}"애플리케이션 실행:
go run main.go
통합 (컨테이너화됨) 실행
Dockerfile 만들기:
FROM golang:1.23 as builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /go-featureflag-app . FROM gcr.io/distroless/static-debian11 WORKDIR / COPY --from=builder /go-featureflag-app /go-featureflag-app ENTRYPOINT ["/go-featureflag-app"]이미지를 빌드하고 푸시합니다.
export PROJECT_ID="your-gcp-project-id" docker build -t gcr.io/${PROJECT_ID}/my-go-app:latest . docker push gcr.io/${PROJECT_ID}/my-go-app:latest서비스 배포: 단위 청사진을 업데이트하여
gcr.io/${PROJECT_ID}/my-go-app:latest를 참조하고 App Lifecycle Manager 출시를 사용하여 새 출시 버전을 배포합니다.
플래그 변경사항 확인
애플리케이션이 실행된 후 플래그를 올바르게 평가하는지 확인합니다.
- 초기 값 관찰: 출력에서 초기 상태에 해당하는 값을 로깅하는지 확인합니다.
- App Lifecycle Manager에서 플래그 업데이트: Google Cloud 콘솔 또는
gcloud을 사용하여 플래그 동작을 수정합니다. - 업데이트된 값 확인: 로컬 컴파일을 다시 실행하거나 컨테이너 로그를 관찰하여 업데이트된 결과를 확인합니다.
다음 단계
- App Lifecycle Manager 기능 플래그 개요에서 개념에 관한 자세한 내용을 읽어보세요.
- 더 안전한 플래그 배포를 위해 App Lifecycle Manager 출시를 알아보세요.
- 기본 App Lifecycle Manager 개요를 검토하세요.