DeepSeek의 Response API는 OpenAI의 Responses와 다릅니다. 파서(Parser)의 실수 하나가
요약
DeepSeek의 API는 OpenAI의 Chat Completions와 호환되지만, /responses API와는 다르므로 주의가 필요합니다. 특히 reasoning_content 필드를 명시적으로 파싱하지 않으면 모델의 사고 과정을 놓칠 수 있습니다.
핵심 포인트
- DeepSeek는 /chat/completions 레이어에서 OpenAI와 호환됨
- reasoning_content 필드를 파싱해야 사고(Thinking) 출력을 얻을 수 있음
- DeepSeek V4 모델 ID(flash, pro) 사용 권장 및 기존 모델 지원 중단 예정
개발자들이 "DeepSeek response API"와 "OpenAI Responses API"를 마치 같은 의미인 것처럼 사용하는 것을 계속 보게 됩니다.
그렇지 않습니다.
이 작은 명칭 실수는 통합(Integration)이 제대로 작동하는 것처럼 보이게 만들면서, 응답에서 가장 중요한 필드인 reasoning_content를 조용히 누락시킬 수 있습니다.
저는 DeepSeek V4 문서와 실시간 TokenMix 모델 카탈로그를 확인하는 데 시간을 보냈습니다. 실질적인 답변은 간단합니다:
DeepSeek는 Chat Completions 레이어에서는 OpenAI와 호환됩니다. 하지만 OpenAI /responses와 호환된다고 문서화되어 있지는 않습니다.
요약 (TL;DR)
- 아니요, DeepSeek의 응답 프로토콜은 OpenAI의
/responsesAPI가 아닙니다. 그것은/chat/completions입니다. - 중요한 추가 필드는
choices[0].message.reasoning_content입니다. - 만약 당신의 래퍼(Wrapper)가
message.content만 파싱(Parsing)한다면, DeepSeek의 사고(Thinking) 출력을 잃을 수 있습니다. - DeepSeek V4는 이제
deepseek-v4-flash및deepseek-v4-pro를 사용하며, 기존의deepseek-chat및deepseek-reasoner이름은 지원 중단(Deprecation)될 예정입니다. - TokenMix는 하나의 OpenAI 호환 기본 URL(Base URL)을 통해 DeepSeek V4 Flash 및 Pro를 지원하며, 실시간 카탈로그에 추론(Reasoning), 스트리밍(Streaming), JSON, 도구(Tools), 구조화된 출력(Structured Output), 프롬프트 캐싱(Prompt Caching)이 표시되어 있습니다.
실제로 무엇이 바뀌었나
DeepSeek V4는 모델 명명 방식의 변화를 가져왔습니다.
기존의 사고 모델은 다음과 같았습니다:
| 기존 모델 이름 | 사람들이 가정했던 것 |
|---|---|
deepseek-chat | 일반 채팅 |
deepseek-reasoner | 추론 모델 |
새로운 V4 모델 ID는 다음과 같습니다:
| 새로운 모델 | 권장 읽기 방식 |
|---|---|
deepseek-v4-flash | 더 저렴하고 처리량이 높은 V4 |
deepseek-v4-pro | 더 강력한 추론/코딩 V4 |
DeepSeek의 문서에 따르면, 기존의 deepseek-chat 및 deepseek-reasoner 이름은 호환성을 위한 별칭(Alias)이며 2026-07-24 15:59 UTC에 지원 중단될 예정입니다.
즉, 저는 기존의 이름들을 기반으로 새로운 프로덕션 코드를 작성하지 않을 것입니다.
중요한 응답 객체 (Response Object)
OpenAI Chat Completions에 익숙하다면, 이것이 친숙하게 보일 것입니다:
{
"choices": [
{
...
함정은 대부분의 기본적인 래퍼(Wrapper)들이 오직 다음과 같이 처리한다는 점입니다:
answer = response.choices[0].message.content
이렇게 하면 최종 답변(final answer)을 얻을 수 있습니다.
하지만 사고 과정(thinking output)은 얻을 수 없습니다.
어떤 제품들에게는 이것으로 충분할 수도 있습니다. 하지만 디버깅(debugging), 평가(evals), 에이전트 추적(agent traces), 그리고 도구 워크플로우(tool workflows)를 위해서는 충분하지 않습니다.
내가 사용할 파서 (Parser)
나는 DeepSeek 응답을 명시적으로 파싱할 것입니다:
def parse_deepseek_response(response):
choice = response.choices[0]
message = choice.message
...
이것은 화려한 방식이 아닙니다. 최소한의 안전한 파서(safe parser)입니다.
핵심은 사용자에게 사고의 사슬(chain of thought)을 보여주는 것이 아닙니다. 디버깅, 평가, 그리고 도구 호출(tool-call)의 연속성에 영향을 미치는 필드들을 소리 없이 놓치는 것을 방지하는 것이 목적입니다.
도구 호출(Tool-call) 시의 주의사항
이 부분은 절대 간과해서는 안 됩니다.
DeepSeek의 사고 모드(thinking-mode) 문서는 일반적인 멀티턴 채팅(multi-turn chat)과 도구 호출 워크플로우(tool-call workflows)를 구분합니다.
일반적인 멀티턴 대화의 경우, 이전의 사고의 사슬(chain-of-thought) 콘텐츠를 다시 전달할 필요가 없습니다.
하지만 도구 호출이 포함된 경우, DeepSeek는 도구 호출 이후의 중간 reasoning_content가 다음 요청 시 반드시 다시 전달되어야 한다고 명시합니다.
이는 범용적인 OpenAI 래퍼(wrapper)가 매우 지루한 방식으로 실패할 수 있음을 의미합니다:
reasoning_content를 수신합니다.role과content만 저장합니다.- 사용자의 도구를 호출합니다.
- 추론(reasoning) 필드 없이 다음 요청을 보냅니다.
- 모델의 도구 워크플로우가 컨텍스트(context)를 잃어버립니다.
이것은 항상 시스템을 충돌(crash)시키는 버그는 아닙니다. 그저 에이전트의 성능을 떨어뜨릴 뿐입니다.
결정 트리 (Decision tree)
무엇을 구현할지 결정하는 나의 방식은 다음과 같습니다:
def deepseek_integration_plan(app):
if app["uses_old_model_names"]:
return "Migrate from deepseek-chat/deepseek-reasoner to deepseek-v4-flash or deepseek-v4-pro."
...
나는 이 트리가 가장 큰 잘못된 선택(false choice)을 피하게 해주기 때문에 좋아합니다.
질문은 "DeepSeek가 OpenAI와 호환되는가?"가 아닙니다.
질문은 "당신은 어떤 호환 계층(compatibility layer)에 의존하고 있는가?"가 되어야 합니다.
TokenMix의 관점: 하나의 엔드포인트, 하지만 여전히 필드를 파싱하라
TokenMix는 OpenAI 호환 베이스 URL(base URL)을 통해 DeepSeek를 노출합니다:
현재 라이브 카탈로그(catalog) 목록은 다음과 같습니다:
| 모델 (Model) | 추론 (Reasoning) | JSON | 도구 (Tools) | 스트리밍 (Streaming) | 프롬프트 캐시 (Prompt cache) |
| --- | --- | --- | --- | --- | --- |
| `deepseek/deepseek-v4-flash` | yes | yes | yes | yes | yes |
| `deepseek/deepseek-v4-pro` | yes | yes | yes | yes | yes |
이는 OpenAI, Claude, Gemini, Qwen, GLM 및 기타 모델과 함께 DeepSeek를 하나의 엔드포인트(endpoint)를 통해 라우팅(route)할 수 있기 때문에 유용합니다.
하지만 동일한 주의 사항이 남아 있습니다:
OpenAI 호환 라우팅(routing)은 요청을 전달할 뿐입니다.
정확한 파싱(parsing)은 여전히 사용자의 몫입니다.
## 1분 만에 끝내는 비용 계산
비용에 관한 내용 또한 오해하기 쉽습니다.
DeepSeek의 직접 가격 책정은 캐시 히트(cache-hit) 입력, 캐시 미스(cache-miss) 입력, 그리고 출력 토큰(output tokens)을 구분합니다.
TokenMix는 자사 엔드포인트를 통한 라우팅에 대한 카탈로그 요율을 게시합니다.
예를 들어, 제가 확인한 실시간 TokenMix 카탈로그 요율을 사용하면 다음과 같습니다:
| 모델 (Model) | 입력 / 1M | 출력 / 1M |
| --- | --- | --- |
| DeepSeek V4 Flash | $0.132353 | $0.264706 |
| DeepSeek V4 Pro | $0.419118 | $0.838235 |
따라서 10M 입력 / 2M 출력 작업량의 비용은 대략 다음과 같습니다:
Flash = 10 * 0.132353 + 2 * 0.264706 = $1.85
Pro = 10 * 0.419118 + 2 * 0.838235 = $5.87
이로 인해 Flash는 대량 작업(high-volume tasks)을 위한 명백한 첫 번째 선택지가 됩니다.
저는 실제 평가(evals)에서 Flash가 실패하는 경우에만 Pro 비용을 지불할 것입니다.
## 프로덕션 환경에서 제가 할 일
만약 제가 이번 주에 DeepSeek V4를 배포한다면, 다음과 같이 할 것입니다:
- 새로운 코드에서 오래된 모델 이름을 사용하는 것을 중단합니다.
- `content`, `reasoning_content`, `tool_calls`, `finish_reason`, 그리고 `usage`를 파싱(parse)합니다.
- 사고 모드(thinking-mode) 도구 워크플로우에서 `reasoning_content`를 보존합니다.
- 명시적인 프롬프트 지침(prompt instructions) 및 검증(validation)이 있는 경우에만 JSON 모드를 사용합니다.
- 캐시 히트/미스(cache hit/miss) 토큰을 별도로 추적합니다.
- Flash로 시작하고, 실패하는 작업에 대해서만 Pro로 격상(escalate)합니다.
- DeepSeek를 유일한 백엔드(backend)로 만드는 대신 라우터(router) 뒤에 배치합니다.
마지막 포인트가 중요합니다.
하나의 엔드포인트가 폴백(fallback)의 필요성을 없애주는 것은 아닙니다.
그저 폴백을 덜 고통스럽게 만들 뿐입니다.
## 공개 사항 (Disclosure)
만약 DeepSeek, OpenAI, Claude, Gemini, Qwen, GLM 및 기타 모델들을 하나의 OpenAI 호환 엔드포인트(endpoint) 뒤에서 사용하고 싶다면, 그것이 대략 [TokenMix](https://tokenmix.ai)가 수행하는 역할입니다. 공개 사항 (Disclosure): 저는 연구 측면에서 일하고 있습니다. 전체 인용된 상세 분석 내용은 [원본 기사](https://tokenmix.ai/blog/deepseek-response-api-protocol-2026)에서 확인할 수 있습니다.
## 결론 (Bottom line)
DeepSeek의 응답 호환성은 실재하지만, OpenAI의 Responses API와는 다릅니다.
이를 Chat Completions 호환성에 DeepSeek 전용 필드가 추가된 것으로 취급하십시오. `reasoning_content`를 의도적으로 파싱(parse)하고, V4 모델 ID로 마이그레이션(migrate)하며, 일반적인 래퍼(wrapper)가 추론(reasoning), 도구(tools), 평가(evals)에 필요한 데이터를 조용히 삭제하도록 방치하지 마십시오.
OpenAI 호환 래퍼가 `reasoning_content`나 캐시 사용량(cache usage)과 같은 제공업체 전용 필드를 누락시키는 것을 본 적이 있습니까? 어떻게 처리하셨나요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기