ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [OpenAI][Responses API] Chat Completions 레거시를 Responses로 옮길 때 previous_response_id와 도구 호출 로그를 어떤 순서로 바꾸나
    기타개발지식/풀스택개발 2026. 7. 11. 20:24

    IT 리서치 노트

    [OpenAI][Responses API] Chat Completions 레거시를 Responses로 옮길 때 previous_response_id와 도구 호출 로그를 어떤 순서로 바꾸나

    기존 Chat Completions 통합을 Responses로 옮길 때 많은 팀이 endpoint만 바꾸고 끝내려 한다. 하지만 2026년 7월 11일 기준 OpenAI 공식 문서를 다시 보면, 실제 변화는 세 겹이다. migration guide는 messages를 typed items로 다시 매핑하라고 하고, conversation state guide는 previous_response_id 같은 상태 전략을 고르라고 하며, TypeScript reference는 response.output에서 message만 남기도록 추려 내면 reasoning·tool-call items가 빠져 다음 요청이 실패할 수 있다고 경고한다. 이 글은 그래서 이전 transcript 구조를 어떻게 줄이고, previous_response_id와 도구 호출 로그를 어떤 순서로 바꾸는 편이 실무적으로 맞는지 정리한 것이다.

    1. 개요

    결론부터 말하면 Chat Completions에서 Responses로 옮길 때는 endpoint 전환보다 먼저 상태 전략과 tool item 로그 구조를 분리해서 생각하는 편이 맞다. 간단한 multi-turn continuation은 previous_response_id로 옮기고, 애플리케이션 감사 로그는 function_call·function_call_output 같은 typed item 기준으로 다시 적는 것이 가장 안전하다. assistant text만 저장하던 레거시 transcript 방식은 Responses에서 너무 많은 운영 정보를 잃는다.

    즉 migration의 핵심은 '어디까지 OpenAI에 맡기고, 어디까지 애플리케이션이 계속 기록할지'를 다시 자르는 일이다. 이미 Responses API 허브 글이 왜 새 통합 출발점을 Responses로 두는지 설명했다면, 이번 글은 그다음 단계인 실제 이행 순서를 다룬다.

    2. 어디서 실제로 막히는가

    현장에서 먼저 꼬이는 지점은 네 가지다. 첫째, endpoint만 /v1/responses로 바꾸고 기존 messages 중심 로그를 그대로 유지한다. 둘째, previous_response_id를 쓸지 manual replay를 할지 정하지 않은 채 레거시 transcript 저장소를 반쯤 남겨 둔다. 셋째, response.output에서 message text만 따로 보관해 reasoning item과 tool-call item을 잃는다. 넷째, 도구 호출 복기 로그를 assistant 응답 한 덩어리 안에 계속 묶어 둔다.

    OpenAI 문서를 붙여 읽으면 왜 위험한지 보인다. migration guide는 messages가 input/output items로 갈라진다고 설명한다. conversation state guide는 previous_response_id가 multi-turn 상태 공유 경로라고 말한다. TypeScript reference는 message만 남기면 required reasoning 또는 tool-call items가 빠져 다음 요청이 실패할 수 있다고 경고한다. 즉 레거시 transcript는 단순히 낡은 저장 형식이 아니라, Responses가 요구하는 item 단위 정보 일부를 잃어버리는 저장 형식이 된다.

    그래서 먼저 정해야 할 것은 transcript 전체를 계속 직접 쥘지, continuation은 previous_response_id에 맡기고 애플리케이션은 감사 로그만 남길지다. tool use가 있는 앱이라면 후자가 더 단순할 때가 많다. OpenAI가 prior response context를 이어 받게 하고, 애플리케이션은 어떤 tool이 호출됐고 어떤 function_call_output이 돌아왔는지를 별도로 남기는 구조가 운영 비용이 낮다.

    • 증상: endpoint는 바꿨는데 운영 로그는 여전히 messages 문자열 중심이다.
    • 실패: response.output에서 assistant text만 남기도록 추려 item 타입을 잃는다.
    • 막힘: previous_response_id와 manual replay의 책임 범위를 섞는다.
    • 누락: function_call, function_call_output을 감사 로그에서 별도 필드로 분리하지 않는다.
    질문 먼저 정할 것 이유
    문맥을 누가 잇나 previous_response_id vs manual replay state 저장 전략이 달라진다
    무엇을 기록하나 typed output items tool-call 복기를 위해 필요하다
    레거시를 어디까지 남기나 assistant text 저장 축소 여부 중복 저장과 누락 저장을 동시에 줄인다

    3. 실무에서 적용하는 순서

    가장 덜 꼬이는 순서는 다섯 단계다. 먼저 generation endpoint를 /v1/responses로 바꾼다. 두 번째로 multi-turn 기본 전략을 previous_response_id로 둘지, manual replay로 둘지 정한다. 세 번째로 응답 파서를 assistant text 중심에서 typed output item 중심으로 바꾼다. 네 번째로 function_call과 function_call_output을 감사 로그에 분리해서 남긴다. 마지막으로 레거시 transcript 저장소는 축소하거나 read-only 호환 계층으로만 남긴다.

    1. endpoint를 /v1/responses로 먼저 교체한다.
    2. 기본 상태 전략을 previous_response_id 또는 manual replay로 확정한다.
    3. 응답 파서를 output item 타입 기준으로 다시 쓴다.
    4. function_call과 function_call_output을 감사 로그에 별도 필드로 남긴다.
    5. 레거시 transcript 저장소는 축소하거나 read-only로만 둔다.

    이 순서가 실용적인 이유는 뒤 단계가 앞 단계를 되돌리지 않기 때문이다. previous_response_id를 기본값으로 두면 continuation은 OpenAI가 연결해 주고, 애플리케이션은 어떤 response id 체인이 이어졌는지와 어떤 tool item이 오갔는지만 기록하면 된다. 반대로 manual replay가 꼭 필요하다면 TypeScript reference가 말하듯 output items를 순서대로 보존해야 하므로, 더더욱 assistant text만 남기는 로그는 위험해진다.

    운영 메모 예시
    request_endpoint=/v1/responses
    state_strategy=previous_response_id
    response_chain=resp_121->resp_122->resp_123
    output_item_types=message,function_call,function_call_output
    tool_log_mode=typed_items
    legacy_transcript_mode=read_only_compat

    실행할 때는 먼저 현재 레거시 코드에서 tool call이 어디에 기록되는지 찾아 assistant message 직렬화 코드와 분리한다. 그다음 새 응답 파서가 item type을 보존하는지 확인하고, 마지막으로 previous_response_id 체인이 실패했을 때 fallback으로 full replay를 보낼지 운영 기준을 적어 둔다. 이 세 지점이 분리돼야 마이그레이션 이후 장애가 state 문제인지, replay 누락인지, tool 로그 누락인지 구분된다.

    • assistant text 직렬화 코드와 tool-call 직렬화 코드를 분리한다.
    • response id 체인과 output item 타입을 같은 로그에 남긴다.
    • manual replay가 필요한 경로만 별도 테스트로 남긴다.

    핵심은 previous_response_id가 모든 운영 문제를 대신 해결해 준다고 기대하지 않는 것이다. continuation은 쉽게 만들 수 있지만, tool-call 복기와 감사 로그는 typed item 기준으로 직접 정리해야 한다.

    4. 공식 문서와 예시 화면으로 확인하기

    첫 자료는 OpenAI migration guide의 Map Messages to Items 구간이다. 여기서는 Chat Completions의 messages 배열이 Responses에서는 input items와 output items로 나뉘고, reasoning·function_call·function_call_output 같은 타입이 별도 item으로 드러난다고 설명한다. 오늘 글의 핵심은 바로 이 구조 변화가 로그 구조 변화이기도 하다는 점이다.

    OpenAI migration guide는 Chat Completions messages를 Responses의 typed items 구조로 다시 매핑하라고 설명한다.
    OpenAI migration guide는 Chat Completions messages를 Responses의 typed items 구조로 다시 매핑하라고 설명한다.

    즉 마이그레이션은 endpoint만 바꾸는 작업이 아니다. 이전에는 assistant message 한 덩어리로 흘러가던 정보가 이제는 reasoning item, function_call item, function_call_output item으로 갈라지므로, 운영 로그도 같은 축으로 갈라야 한다.

    두 번째 자료는 같은 migration guide의 multi-turn conversations 구간이다. OpenAI는 여기서 상태 관리 선택지를 previous_response_id, prior output items replay, Conversations API로 나눈다. 레거시 코드를 옮길 때 먼저 결정해야 하는 것은 이 세 상태 전략 중 무엇을 기본값으로 둘지다.

    Responses 마이그레이션은 multi-turn 상태 관리를 previous_response_id, manual replay, Conversations API 중 하나로 다시 정리하게 만든다.
    Responses 마이그레이션은 multi-turn 상태 관리를 previous_response_id, manual replay, Conversations API 중 하나로 다시 정리하게 만든다.

    이 선택이 중요한 이유는 이후 tool-call 로그 구조를 어디에 남길지도 같이 결정되기 때문이다. previous_response_id를 기본값으로 두면 OpenAI가 prior response context를 연결해 주지만, 애플리케이션은 여전히 어떤 tool item이 오갔는지 자체 로그를 남겨야 한다.

    세 번째 자료는 conversation state guide의 previous_response_id 예시다. 이 페이지는 second response를 만들 때 previous_response_id=response.id를 넘기면 모델이 앞선 문맥을 이어 받는 흐름을 보여 준다. 즉 전체 transcript를 다시 쌓아 보내지 않아도 continuation 자체는 성립한다.

    conversation state guide는 previous_response_id로 응답 체인을 이어 가는 기본 continuation 패턴을 보여 준다.
    conversation state guide는 previous_response_id로 응답 체인을 이어 가는 기본 continuation 패턴을 보여 준다.

    하지만 여기서 끝내면 안 된다. 문맥 연결은 OpenAI 쪽 continuation 문제를 줄여 주는 장치이고, 도구 호출 감사 로그는 애플리케이션이 별도로 정리해야 하는 운영 문제다. 두 층을 섞으면 레거시 transcript 저장소를 줄였는데도 디버깅은 더 어려워질 수 있다.

    네 번째 자료는 TypeScript reference의 multi-turn conversations 경고다. OpenAI는 manual history를 관리할 때 response.output을 messages만 남기도록 필터링하면 required reasoning 또는 tool-call items가 사라져 다음 요청이 실패할 수 있다고 직접 적고 있다. 이 문장이 도구 호출 로그를 별도 타입으로 남겨야 하는 가장 직접적인 근거다.

    TypeScript reference는 response.output에서 message만 남기도록 추려 내면 reasoning·tool-call items가 빠져 다음 요청이 실패할 수 있다고 경고한다.
    TypeScript reference는 response.output에서 message만 남기도록 추려 내면 reasoning·tool-call items가 빠져 다음 요청이 실패할 수 있다고 경고한다.

    즉 레거시 로그에서 assistant text만 저장하던 습관은 Responses에서 위험해진다. replay를 OpenAI에 맡기든 직접 관리하든, 최소한 어떤 function_call과 function_call_output이 오갔는지는 타입을 유지한 채 추적해야 한다.

    실무에서는 이 전환을 순서표로 적어 두는 편이 가장 유용하다. endpoint 변경, 상태 전략 선택, tool item 로그 분리, 응답 파서 교체를 한 장으로 정리하면 레거시 제거 범위를 작게 유지할 수 있다.

    Chat Completions에서 Responses로 옮길 때 endpoint·상태·tool 로그를 분리한 마이그레이션 순서표다.
    Chat Completions에서 Responses로 옮길 때 endpoint·상태·tool 로그를 분리한 마이그레이션 순서표다.

    이 표처럼 보면 previous_response_id는 상태 연결 축이고, function_call item 로그는 운영 복기 축이라는 구분이 선명해진다. 이미 Responses API 상위 허브 글을 봤다면, 이번 표는 실제 코드 이행 순서를 더 좁히는 후속편이다.

    마지막 자료는 최소 운영 로그 예시다. 레거시 transcript와 달리 response id 체인, function_call item, function_call_output item, replay 방식을 별도 필드로 남겨 두면 다음 단계 문제가 훨씬 짧게 갈린다.

    previous_response_id와 tool-call item을 분리해 적는 Responses 운영 로그 예시다.
    previous_response_id와 tool-call item을 분리해 적는 Responses 운영 로그 예시다.

    이 구조를 잡아 두면 previous_response_id 상태 분기, function_call_output 검증, built-in tools 구성으로 같은 흐름을 이어 가기 쉽다.

    5. 주의사항과 리스크

    첫 번째 리스크는 endpoint만 바꾼 뒤 레거시 messages 로그를 그대로 두는 것이다. 두 번째 리스크는 previous_response_id를 쓰면서도 response.output item 타입을 잃는 것이다. 세 번째 리스크는 tool-call 감사 로그를 assistant text 문자열 안에 계속 묻어 두는 것이다.

    운영 전에 확인할 때는 최소한 state_strategy, response_chain, output_item_types, tool_log_mode, legacy_transcript_mode 다섯 칸을 같은 표에 남겨 두는 편이 좋다. 이 다섯 칸이 없으면 migration 성공과 운영 복기 성공을 같은 것으로 착각하기 쉽다.

    • previous_response_id는 continuation 축이다.
    • tool-call 로그는 typed item 축이다.
    • assistant text만 저장하는 레거시 습관은 Responses에서 위험하다.

    6. 결론

    Chat Completions 레거시를 Responses로 옮길 때는 endpoint 교체보다 state 전략과 tool-call 로그 구조 재설계가 더 중요하다. continuation은 previous_response_id로 단순화하고, 감사 로그는 function_call과 function_call_output 같은 typed item 기준으로 다시 적는 편이 가장 안전하다. 이렇게 해야 transcript는 줄고 복기 정보는 오히려 더 선명해진다.

    • endpoint, state, tool 로그를 서로 다른 단계로 나눈다.
    • previous_response_id와 typed item 로그를 함께 쓴다.
    • 레거시 transcript 저장은 축소하고 복기 정보는 강화한다.

    7. 참고 링크

    1. https://developers.openai.com/api/docs/guides/migrate-to-responses
    2. https://developers.openai.com/api/docs/guides/conversation-state
    3. https://developers.openai.com/api/reference/typescript/
    4. https://developers.openai.com/api/docs/guides/tools
Designed by Tistory.