블로그로 돌아가기

API & SDK가이드

openai-dotnet으로 하는 C# 첫 요청: 엔드포인트, 키, 응답

C# 콘솔 앱에서 첫 채팅 완료를 보내세요: 공식 OpenAI .NET 라이브러리에서 Endpoint를 설정하고, 환경 변수에서 키를 읽고, 응답과 종료 이유를 출력합니다.

작성자: CheapTokens Team 게시됨읽는 시간 4분

커버: CheapTokens 엔드포인트에 연결된 C#과 OpenAI .NET 라이브러리
이 페이지의 내용
  1. 필요한 것
  2. 콘솔 앱 만들기
  3. 코드, 한 줄씩
  4. 보여야 하는 것
  5. 기존 서비스 전환하기
  6. 요청 한 건의 비용
  7. 동작하지 않을 때

C#에서 CheapTokens로 요청을 보내려면 공식 OpenAI .NET 라이브러리를 그대로 사용하고 OpenAIClientOptions.Endpoint를 https://api.cheaptokens.dev/v1로 설정하세요. 전체 모델 id(예: deepseek-ai/DeepSeek-V4-Flash-0731)를 전달하고, 키는 환경 변수에서 읽으세요. ChatClient와 CompleteChat 호출은 OpenAI 예제와 정확히 동일하게 유지됩니다.

OpenAI와 통신하는 ASP.NET 서비스가 이미 있고, 나머지 코드는 건드리지 않은 채 다른 엔드포인트와 모델을 시험해 보고 싶다고 가정해 봅시다. 무언가를 연결하기 전에, 보통 문제가 되는 세 가지(키, 엔드포인트, 모델 id)를 작은 콘솔 앱에서 확인하세요. 여기서 만드는 것이 바로 그것입니다. 아래 세부 내용은 GitHub의 라이브러리 README(openai/openai-dotnet, 2026년 11월 5일 확인)와 CheapTokens 문서에서 가져왔습니다. 문서 페이지에도 같은 base URL이 있습니다.

필요한 것#

패키지 이름은 NuGet에서 OpenAI입니다. 2026년 11월 5일 기준 최신 안정 버전은 2.15.0입니다(변경 로그 항목 날짜는 11월 4일). .NET 8과 .NET Standard 2.0을 대상으로 하며, README에 따르면 모든 .NET Standard 2.0 애플리케이션에서 동작하므로 오래된 프로젝트도 괜찮습니다.

앱에는 세 가지 값이 들어갑니다:

  • base URL: https://api.cheaptokens.dev/v1 (OpenAI Chat Completions 호환);
  • 모델 id: deepseek-ai/DeepSeek-V4-Flash-0731. 전체 id를 사용하세요. 가격표의 짧은 이름은 허용되지 않습니다. DeepSeek-V4-Flash는 380K 컨텍스트 윈도우와 답변당 최대 32,768 출력 토큰을 가지며, 시간대와 관계없이 단일 가격입니다;
  • CheapTokens 계정의 API 키로, 환경 변수에 보관합니다. 저장 방법이 확실하지 않다면 API 키를 안전하게 저장하는 방법을 읽어 보세요.

콘솔 앱 만들기#

단계별로

프로젝트를 만들고 실행하기

콘솔 프로젝트 만들기

bash
dotnet new console -o FirstRequest
cd FirstRequest

패키지 추가하기

bash
dotnet add package OpenAI

키를 환경 변수에 넣기

bash 또는 zsh에서:

bash
export CHEAPTOKENS_API_KEY=your-key

Windows PowerShell에서:

powershell
$env:CHEAPTOKENS_API_KEY = "your-key"

코드를 붙여넣고 실행하기

Program.cs의 내용을 다음 섹션의 코드로 바꾼 뒤 dotnet run을 실행하세요.

콘솔 앱을 만들고 실행하는 다섯 개의 명령이 있는 터미널
다섯 개의 명령: 프로젝트 생성, 폴더 이동, 패키지 추가, 키 설정, 실행.

코드, 한 줄씩#

csharp
using System.ClientModel;
using OpenAI;
using OpenAI.Chat;

string? apiKey = Environment.GetEnvironmentVariable("CHEAPTOKENS_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
    Console.WriteLine("Set CHEAPTOKENS_API_KEY first.");
    return;
}

ChatClient client = new(
    model: "deepseek-ai/DeepSeek-V4-Flash-0731",
    credential: new ApiKeyCredential(apiKey),
    options: new OpenAIClientOptions
    {
        Endpoint = new Uri("https://api.cheaptokens.dev/v1")
    });

ChatCompletion completion = client.CompleteChat("Explain in two sentences what a token is.");

Console.WriteLine(completion.Content[0].Text);
Console.WriteLine($"finish_reason: {completion.FinishReason}");

README는 "프록시 또는 자체 호스팅 OpenAI 호환 LLM"에 대해 이 패턴을 보여줍니다: 엔드포인트는 OpenAIClientOptions에, 키는 ApiKeyCredential에 들어갑니다(이는 System.ClientModel에 있으므로 첫 번째 using가 필요합니다). 맨 위의 검사는 우리가 추가한 것으로, 변수가 설정되지 않았을 때 명확한 메시지를 줍니다.

일반 문자열과 함께 쓰는 CompleteChat는 사용자 메시지 하나를 보내고 전체 답변을 기다립니다. 응답 텍스트는 completion.Content[0].Text에 있습니다. 종료 이유는 completion.FinishReason에 있습니다.

흐름: 환경 변수에서 키, Endpoint가 있는 ChatClient, CompleteChat, 텍스트와 FinishReason
키에서 출력된 답변까지 프로그램에서 일어나는 일.

보여야 하는 것#

토큰에 대한 짧은 설명과 종료 이유가 있는 줄이 나와야 합니다. 정상적으로 끝나면 Stop입니다(README는 FinishReason을 ChatFinishReason.Stop와 비교합니다). 답변의 문구는 실행할 때마다 달라집니다.

두 번째 줄이 읽어 볼 만한 줄입니다. README는 FinishReason을 ChatFinishReason.Stop(모델이 스스로 끝냄)와 ChatFinishReason.ToolCalls(모델이 도구를 호출하려 함)와 비교합니다. 일반 채팅에서 Stop이 아닌 값이 나오면 다른 이유로 답변이 끝난 것이며, 흔한 원인은 길이 제한입니다. 문장 중간에 끊긴 답변이 보인다면 이 글에서 finish_reason과 max_tokens을 설명합니다.

기존 서비스 전환하기#

서비스가 이미 OpenAI용 ChatClient를 만든다면 두 가지만 바꾸면 됩니다: 모델 문자열과 옵션입니다. 나머지 호출은 계속 동작합니다.

비교하기

같은 클라이언트, 바뀐 두 줄

변경 전

csharp
ChatClient client = new(
    model: "your-current-model",
    credential: new ApiKeyCredential(apiKey));

변경 후

csharp
ChatClient client = new(
    model: "deepseek-ai/DeepSeek-V4-Flash-0731",
    credential: new ApiKeyCredential(apiKey),
    options: new OpenAIClientOptions
    {
        Endpoint = new Uri("https://api.cheaptokens.dev/v1")
    });

짧은 요청에는 두 번째 옵션이 있습니다: zai-org/GLM-5.3-Flash(390K 컨텍스트, 최대 8,192 출력 토큰). model 문자열만 바꾸면 됩니다. 키로 사용할 수 있는 id 목록은 요청 한 번이면 얻을 수 있습니다. GET /v1/models로 모델 목록 보기를 참고하세요.

요청 한 건의 비용#

서비스가 하루 1,000건의 요청을 처리하고, 각 요청이 약 300 입력 토큰과 400 출력 토큰이라고 가정해 봅시다. 이런 요청 한 건은 DeepSeek-V4-Flash에서 $0.000045입니다. 아래 표는 같은 1,000건의 요청을 세 모델 모두에서 OpenRouter와 나란히 보여줍니다. 입력과 출력을 합산한 총액에서 DeepSeek-V4-Flash는 OpenRouter보다 저렴합니다. 현재 가격은 가격 페이지에 있고, DeepSeek 페이지에는 모델이 제공하는 기능이 나열되어 있습니다.

모델 요청당 1,000회 요청 OpenRouter, 1,000회 요청
GLM-5.3-Flash $0.000022 $0.022 $0.0433
DeepSeek-V4-Flash $0.000045 $0.0445 $0.077
MiniMax-M2.7 $0.000075 $0.075 $0.90

요청당 입력 300개 및 출력 400개 토큰입니다. 100만 토큰당 가격은 현재 기준이며 당사 요금제에 따라 함께 변경됩니다. OpenRouter 열은 동일한 작업량에 대한 참고 가격을 보여줍니다.

동작하지 않을 때#

  • 401. 키가 없거나 잘못되었습니다. 변수가 설정되어 있는지 출력하고(코드의 검사가 이를 수행합니다), dotnet run가 export(또는 $env:)을 실행한 것과 같은 터미널에서 시작되었는지 확인하세요. 변수는 해당 세션에만 존재합니다.
  • 404. 가장 흔한 원인은 모델 id입니다: 전체 deepseek-ai/DeepSeek-V4-Flash-0731 대신 짧은 이름을 썼거나, /v1 없이 엔드포인트를 썼거나(OpenAIClientOptions이 실제로 ChatClient에 전달되는지도 확인하세요). 자세한 내용은 API 401 또는 404: 잘못된 키, base URL 또는 모델 id에 있습니다.
  • error CS0246: The type or namespace name 'ApiKeyCredential' could not be found. Program.cs 맨 위에 using System.ClientModel; 줄이 빠졌습니다.

다른 언어로 같은 아이디어: openai-go를 사용한 Go 버전.