
.NET에서 Microsoft.Extensions.AI를 사용하여 공급자 독립적인(Provider-Agnostic) AI 애플리케이션 구축하기
요약
Microsoft.Extensions.AI를 사용하여 특정 AI 공급자에 종속되지 않는 .NET 애플리케이션 구축 방법을 소개합니다. IChatClient와 같은 공통 추상화 인터페이스를 활용해 Azure OpenAI, OpenAI, Ollama 등 다양한 모델을 유연하게 교체하며 사용할 수 있는 설계 패턴을 다룹니다.
핵심 포인트
- Microsoft.Extensions.AI를 통한 AI 서비스 추상화 구현
- 특정 SDK 의존성을 제거하여 공급자 독립적(Provider-Agnostic) 설계 가능
- IChatClient 및 IEmbeddingGenerator 인터페이스 활용
- 애플리케이션 코드의 테스트 용이성 및 유지보수성 향상
서론 (Introduction)
이전 기사에서 우리는 ASP.NET Core를 사용하여 보안이 강화된 AI 준비형 채팅 API를 구축했습니다. 우리는 IAiChatService라는 커스텀 인터페이스를 사용했고, Azure OpenAI 할당량 없이도 프로젝트를 실행할 수 있도록 로컬 MockAiChatService를 구현했습니다.
그것은 좋은 첫 단계였습니다.
이 기사에서는 다음 단계로 나아가 Microsoft.Extensions.AI를 사용하여 Microsoft의 공식 AI 추상화(Abstraction) 접근 방식을 사용할 것입니다.
주요 목표는 간단합니다:
비즈니스 코드가 특정 AI 공급자 SDK에 직접적으로 의존하지 않는 AI 애플리케이션을 구축하는 것입니다.
Azure OpenAI, OpenAI, Ollama, GitHub Models 또는 기타 공급자에 밀접하게 결합(Tightly coupled)된 애플리케이션 코드를 작성하는 대신, IChatClient와 같은 공통 추상화(Abstraction)를 대상으로 구축할 수 있습니다.
이를 통해 애플리케이션이 더 깔끔해지고, 테스트하기 쉬워지며, 나중에 변경하기가 더 용이해집니다.
공급자 독립적인(Provider-Agnostic) AI 설계가 중요한 이유
많은 엔터프라이즈 애플리케이션에서 AI 공급자는 시간이 지남에 따라 변경될 수 있습니다.
오늘날 애플리케이션은 다음과 같은 것을 사용할 수 있습니다:
로컬 개발을 위한 Mock AI 서비스
내일은 다음과 같은 것을 사용할 수 있습니다:
Azure OpenAI
나중에는 다음과 같은 것을 사용할 수 있습니다:
OpenAI
로컬 모델 (Local model)
GitHub Models
기타 OpenAI 호환 엔드포인트 (OpenAI-compatible endpoint)
만약 컨트롤러(Controller)나 비즈니스 서비스가 특정 SDK에 직접 의존한다면, 공급자를 변경하는 것이 어려워집니다.
나쁜 설계:
ChatController
|
v
Azure OpenAI SDK 직접 사용
더 나은 설계:
ChatController
|
v
IChatClient
|
v
AI 공급자 구현 (AI Provider Implementation)
이 지점이 바로 Microsoft.Extensions.AI가 유용해지는 부분입니다.
Microsoft.Extensions.AI란 무엇인가?
Microsoft.Extensions.AI는 .NET 애플리케이션의 AI 서비스를 위한 공통 추상화(Abstractions)를 제공합니다.
다음과 같은 추상화가 포함됩니다:
IChatClient
IEmbeddingGenerator
ChatMessage
ChatResponse
ChatOptions
Microsoft.Extensions.AI.Abstractions 패키지는 IChatClient 및 IEmbeddingGenerator를 포함한 핵심 교환 유형(Exchange types)을 제공합니다. LLM 클라이언트를 제공하는 모든 .NET 라이브러리는 IChatClient를 구현할 수 있으므로, 이를 사용하는 코드가 더 쉽게 통합될 수 있습니다.
중요한 아이디어는 다음과 같습니다:
애플리케이션 코드는 특정 공급자(Provider)의 SDK에 직접 의존하는 것이 아니라, 추상화(Abstractions)에 의존해야 합니다.
우리가 구축할 것
우리는 IChatClient를 사용하는 ASP.NET Core Web API를 구축할 것입니다.
로컬 개발을 위해, 커스텀 MockChatClient를 생성할 것입니다.
흐름은 다음과 같습니다:
컨트롤러(Controller)는 IChatClient 뒤에 어떤 공급자가 있는지 알 필요가 없습니다.
프로젝트 설정
새로운 ASP.NET Core Web API 프로젝트를 생성합니다.
dotnet new webapi -n ProviderAgnosticAi.Api
cd ProviderAgnosticAi.Api
필요한 패키지를 추가합니다:
dotnet add package Microsoft.Extensions.AI.Abstractions
dotnet add package Swashbuckle.AspNetCore
향후 OpenAI 호환 구현을 위해 다음 패키지들도 추가할 수 있습니다:
_dotnet add package Microsoft.Extensions.AI.OpenAI
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity
_
이 글에서는 모의(Mock) IChatClient를 사용하여 프로젝트를 로컬에서 실행 가능한 상태로 유지할 것입니다.
권장 프로젝트 구조
ProviderAgnosticAi.Api
│
├── Controllers
│ └── ChatController.cs
│
├── Models
│ ├── ChatRequestDto.cs
│ └── ChatResponseDto.cs
│
├── Services
│ ├── MockChatClient.cs
│ ├── IProviderAgnosticChatService.cs
│ └── ProviderAgnosticChatService.cs
│
└── Program.cs
요청 모델(Request Model) 생성
다음 파일을 생성합니다:
Models/ChatRequestDto.cs
namespace ProviderAgnosticAi.Api.Models;
public class ChatRequestDto;
...
이 모델은 사용자 입력을 나타냅니다.
응답 모델(Response Model) 생성
다음 파일을 생성합니다:
Models/ChatResponseDto.cs
namespace ProviderAgnosticAi.Api.Models;
public class ChatResponseDto;
...
Provider 필드는 어떤 구현체가 응답을 생성했는지 식별하는 데 도움을 줍니다.
로컬 개발 시에는 다음과 같이 표시됩니다:
MockChatClient
나중에는 Azure OpenAI 또는 OpenAI 기반의 클라이언트가 표시될 수 있습니다.
Mock IChatClient 생성하기
이제 Microsoft의 IChatClient에 대한 모의 구현체(mock implementation)를 생성합니다.
다음 파일을 생성하세요:
Services/MockChatClient.cs
using Microsoft.Extensions.AI;
namespace ProviderAgnosticAi.Api.Services;
...
이 모의 클라이언트(mock client)를 사용하면 Azure OpenAI 할당량(quota) 없이도 애플리케이션을 테스트할 수 있습니다.
애플리케이션 서비스 인터페이스 생성하기
다음 파일을 생성하세요:
Services/IProviderAgnosticChatService.cs
using ProviderAgnosticAi.Api.Models;
namespace ProviderAgnosticAi.Api.Services;
...
이 서비스는 컨트롤러(controller)를 깔끔하게 유지해 줍니다.
애플리케이션 서비스 구현체 생성하기
다음 파일을 생성하세요:
Services/ProviderAgnosticChatService.cs
using Microsoft.Extensions.AI;
using ProviderAgnosticAi.Api.Models;
...
이 서비스는 IChatClient에 의존합니다.
구현체가 무엇인지에 대해서는 신경 쓰지 않습니다:
MockChatClient
Azure OpenAI 클라이언트
OpenAI 클라이언트
로컬 모델 클라이언트
이것이 공급자 독립적(provider-agnostic) 설계의 주요 이점입니다.
API 컨트롤러 생성하기
다음 파일을 생성하세요:
Controllers/ChatController.cs
using Microsoft.AspNetCore.Mvc;
using ProviderAgnosticAi.Api.Models;
using ProviderAgnosticAi.Api.Services;
...
컨트롤러는 애플리케이션 서비스와만 통신합니다.
애플리케이션 서비스는 IChatClient와 통신합니다.
이를 통해 관심사의 깔끔한 분리(separation of concerns)가 이루어집니다.
Program.cs 업데이트하기
Program.cs를 다음 내용으로 교체하세요:
using Microsoft.Extensions.AI;
using ProviderAgnosticAi.Api.Services;
...
API 실행 및 테스트
애플리케이션을 실행합니다:
dotnet run
Swagger를 엽니다:
https://localhost:/swagger
엔드포인트(endpoint)를 테스트합니다:
POST /api/provider-agnostic-chat
요청(Request):
{
"userMessage": "What is provider-agnostic AI design in .NET?"
}
예상 응답(Expected response):
{
"success": true,
"answer": "Provider-agnostic AI design means your application depends on an abstraction like IChatClient, instead of directly depending on one AI provider SDK.",
"provider": "MockChatClient",
"errorMessage": null
}
다른 요청을 테스트합니다:
{
"userMessage": "Microsoft.Extensions.AI란 무엇인가요?"
}
예상 응답:
{
"success": true,
"answer": "Microsoft.Extensions.AI는 IChatClient 및 IEmbeddingGenerator와 같은 공통 추상화 (abstractions)를 제공하여, .NET 애플리케이션이 익숙한 의존성 주입 (dependency injection) 패턴을 사용하여 AI 서비스를 통합할 수 있도록 합니다.",
"provider": "MockChatClient",
"errorMessage": null
}
Microsoft.Extensions.AI가 엔터프라이즈 아키텍처에서 차지하는 위치
공급자 독립적인 (provider-agnostic) AI 아키텍처는 다음과 같은 모습일 수 있습니다:
이 패턴은 다음과 같은 경우에 유용합니다:
- 개발 중에 Azure 할당량 (quota)을 사용할 수 없는 경우
- 팀에서 로컬 테스트를 원하는 경우
- 조직이 나중에 모델 공급자를 변경할 수 있는 경우
- 단위 테스트 (unit tests)에서 AI 응답을 모킹 (mock)하고 싶은 경우
- 로깅 (logging) 및 텔레메트리 (telemetry)를 중앙 집중화하고 싶은 경우
- 깔끔한 의존성 주입 (dependency injection)을 원하는 경우
보안 및 엔터프라이즈 고려 사항
추상화 (abstractions)를 사용할 때에도 여전히 엔터프라이즈 제어 기능이 필요합니다.
권장 실무 사항:
프론트엔드에서 AI 공급자 (AI providers)를 직접 호출하지 마세요.
ASP.NET Core API 뒤에서 AI 접근을 유지하세요.
소스 코드에 공급자 키 (provider keys)를 저장하지 마세요.
개발 및 테스트를 위해 로컬 모의 공급자 (local mock providers)를 사용하세요.
운영 환경의 비밀 정보 (production secrets)에는 Azure Key Vault 또는 관리 ID (Managed Identity)를 사용하세요.
모델을 호출하기 전에 사용자 입력을 검증하세요.
민감한 정보가 포함된 경우 전체 프롬프트 (prompts)를 로깅하는 것을 피하세요.
모델 사용량, 지연 시간 (latency), 그리고 오류를 추적하세요.
비용 제어를 위해 속도 제한 (rate limiting)을 추가하세요.
기업 특화된 답변을 위해 RAG (Retrieval-Augmented Generation)를 사용하세요.
Microsoft.Extensions.AI는 추상화 (abstraction)를 도와주지만, 아키텍처, 보안, 그리고 거버넌스 (governance)는 여전히 신중하게 설계되어야 합니다.
결론
이 글에서 우리는 ASP.NET Core와 Microsoft.Extensions.AI를 사용하여 공급자 독립적인 (provider-agnostic) AI API를 구축했습니다.
주요 설계 원칙은 다음과 같습니다:
애플리케이션 코드는 특정 공급자의 SDK에 직접 의존하는 것이 아니라, AI 추상화 (AI abstractions)에 의존해야 합니다.
IChatClient를 사용함으로써, 우리의 애플리케이션은 테스트하기가 더 쉬워지고, 확장하기가 더 쉬워지며, 나중에 다른 공급자로 전환하기가 더 쉬워집니다.
로컬 개발을 위해 우리는 다음을 사용했습니다:
MockChatClient
운영 환경에서는 나중에 이를 Azure OpenAI 기반의 구현체로 교체할 수 있습니다.
이러한 접근 방식은 클린 아키텍처 (clean architecture), 의존성 주입 (dependency injection), 로컬 테스트, 공급자 유연성, 그리고 장기적인 유지보수성을 지원하기 때문에 엔터프라이즈 개발자에게 유용합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기

