Streaming & Upload
Core의 callApiStream은 NDJSON 응답을 줄 단위 JSON으로 읽어 Observable에서 순서대로 emit합니다.
Core에서 callApiStream 직접 사용
서버가 NDJSON(한 줄에 JSON 하나)을 내려줄 때 callApiStream을 사용합니다. Accept header가 없으면 application/x-ndjson을 기본값으로 설정하며, 다른 media type이 필요하면 per-request headers로 덮어쓸 수 있습니다.
ts
export const streamEvents = () => {
return client.callApiStream<{
eventName: string;
content: unknown;
}>({
url: "/api/event/stream",
method: "get",
// headers: { Accept: "application/x-ndjson" },
});
};NDJSON 응답 형식
text
{"status":"STARTED","progress":0}
{"status":"PROGRESS","progress":35}
{"status":"PROGRESS","progress":80}
{"status":"DONE","progress":100}callApiStream은 줄바꿈을 기준으로 응답을 나누고 각 줄을 JSON.parse합니다. 표준 SSE의 data: frame 형식이 아니라 NDJSON을 기대합니다.
Observable 구독과 해제
tsx
const subscription = streamEvents().subscribe({
next: (event) => {
setProgress(event.content);
},
error: (error) => {
setErrorMessage(error.message);
},
complete: () => {
setRunning(false);
},
});
return () => subscription.unsubscribe();unsubscribe()하면 내부 ReadableStream reader도 취소됩니다. React effect나 작업 cleanup에서 구독을 해제하세요.
선택: 생성된 stream service 사용
OpenAPI generator를 사용하는 프로젝트에서는 stream endpoint에 대해 생성된 service가 callApiStream을 호출하도록 만들 수 있습니다. 화면에서는 일반 생성 service와 같은 방식으로 import하고 subscribe합니다.
tsx
const subscription = jobProgress({
path: { jobId },
}).subscribe({
next: (event) => {
setProgress(event.progress || 0);
},
error: (error) => {
setErrorMessage(error.message);
},
complete: () => {
setRunning(false);
},
});
return () => subscription.unsubscribe();uploadFile: 지정 URL에 파일 PUT
uploadFile.ts
tsservice.uploadFile({
file,
url: signedUploadUrl,
headers: {
"Content-Type": file.type || "application/octet-stream",
"If-None-Match": "*",
},
}).subscribe();