Aspire 구성
이 스킬을 사용해야 하는 경우
다음과 같은 경우 이 스킬을 사용하세요:
- Aspire 기반 리포지토리에서 AppHost 리소스를 애플리케이션 구성에 연결할 때
- 프로덕션 구성이 Aspire 외부에서도 투명하고 이식 가능하도록 보장해야 할 때
- 애플리케이션 코드에서 Aspire 클라이언트/서비스 검색 패키지를 사용하지 않아야 할 때
- 앱 코드 경로를 변경하지 않고 개발/테스트를 위한 기능 토글을 설계할 때
핵심 원칙
-
AppHost가 Aspire 인프라 패키지를 소유함
- Aspire 호스팅 패키지는 AppHost에만 속합니다.
- 앱 프로젝트는 Aspire 클라이언트/서비스 검색 패키지를 참조해서는 안 됩니다.
-
명시적 구성만 사용
- AppHost는 리소스 출력을 명시적인 구성 키(환경 변수)로 변환해야 합니다.
- 앱 코드는
IOptions<T>또는Configuration에만 바인딩됩니다.
-
프로덕션 동등성과 투명성
- AppHost가 주입하는 모든 값은 Aspire 없이도 프로덕션에서 환경 변수 또는 구성 파일로 표현 가능해야 합니다.
- 불투명한 서비스 검색 및 암시적 구성을 피하세요.
구성 흐름
AppHost 리소스 -> WithEnvironment(...) -> 앱 구성 키 -> 앱의 IOptions<T>
AppHost는 Aspire 리소스를 명시적인 앱 설정으로 변환할 책임이 있습니다. 애플리케이션은 Aspire 클라이언트나 서비스 검색을 직접 사용하지 않습니다.
AppHost 패턴 (명시적 매핑)
예제: 데이터베이스 + Blob 스토리지
// AppHost/Program.cs
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var db = postgres.AddDatabase("appdb");
var minio = builder.AddContainer("minio", "minio/minio")
.WithArgs("server", "/data")
.WithHttpEndpoint(targetPort: 9000, name: "http")
.WithHttpEndpoint(targetPort: 9001, name: "console")
.WithEnvironment("MINIO_ROOT_USER", "minioadmin")
.WithEnvironment("MINIO_ROOT_PASSWORD", "minioadmin");
var api = builder.AddProject<Projects.MyApp_Api>("api")
.WithReference(db, "Postgres")
.WithEnvironment("BlobStorage__Enabled", "true")
.WithEnvironment("BlobStorage__ServiceUrl", minio.GetEndpoint("http"))
.WithEnvironment("BlobStorage__AccessKey", "minioadmin")
.WithEnvironment("BlobStorage__SecretKey", "minioadmin")
.WithEnvironment("BlobStorage__Bucket", "attachments")
.WithEnvironment("BlobStorage__ForcePathStyle", "true");
builder.Build().Run();
핵심 사항
WithReference(db, "Postgres")는ConnectionStrings__Postgres를 명시적으로 설정합니다.- 모든 외부 종속성은 명시적인 구성 키를 통해 표현됩니다.
- API 프로젝트는
Configuration값만 읽습니다.
앱 코드 패턴 (Aspire 클라이언트 없음)
애플리케이션 코드는 옵션에 바인딩되고 SDK를 직접 초기화합니다. Aspire 클라이언트 패키지나 서비스 검색에 절대 의존하지 않습니다.
// Api/Program.cs
builder.Services
.AddOptions<BlobStorageOptions>()
.BindConfiguration("BlobStorage")
.ValidateDataAnnotations()
.ValidateOnStart();
builder.Services.AddSingleton<IBlobStorageService>(sp =>
{
var options = sp.GetRequiredService<IOptions<BlobStorageOptions>>().Value;
return new S3BlobStorageService(options); // 명시적 옵션만 사용
});
앱에 Aspire 클라이언트 패키지(또는 AddServiceDiscovery)를 추가하지 마십시오.
이러한 것은 오케스트레이션 관련 사항이므로 AppHost에 남아 있어야 합니다.
기능 토글 및 테스트 재정의
토글을 구성에 유지하고 AppHost와 테스트 픽스처를 통해 제어하세요. 이렇게 하면 개발/테스트와 프로덕션 구성 간의 동등성이 유지됩니다.
// AppHost: 구성 재정의를 통해 테스트에서 지속성 비활성화
var config = builder.Configuration.GetSection("App")
.Get<AppHostConfiguration>() ?? new AppHostConfiguration();
if (!config.UseVolumes)
{
postgres.WithDataVolume(false);
}
api.WithEnvironment("BlobStorage__Enabled", config.EnableBlobStorage.ToString());
DistributedApplicationTestingBuilder에 구성 재정의를 전달하는 패턴은 skills/aspire/integration-testing/SKILL.md를 참조하세요.
수행/금지 목록
수행
- 모든 Aspire 리소스 출력을 명시적인 구성 키로 매핑하세요
- 모든 인프라 설정에 대해 유효성 검사와 함께
IOptions<T>를 사용하세요 - Aspire 호스팅 패키지를 참조하는 유일한 위치로 AppHost를 유지하세요
- AppHost가 주입하는 모든 값이 프로덕션 환경 변수로 설정될 수 있는지 확인하세요
금지
- 애플리케이션 프로젝트에서 Aspire 클라이언트/서비스 검색 패키지를 참조하지 마세요
- 프로덕션에서 미러링할 수 없는 불투명한 서비스 검색에 의존하지 마세요
- Aspire 전용 추상화 뒤에 구성을 숨기지 마세요
관련 스킬
skills/aspire/service-defaults/SKILL.mdskills/aspire/integration-testing/SKILL.mdskills/akka/aspire-configuration/SKILL.md