이미지 여러 개를 처리할 때 높은 메모리 사용
이미지 여러 개를 처리할 때 높은 메모리 사용
이미지를 여러 개 처리할 때 메모리가 계속 늘어나는 문제를 해결하는 문서예요. include 옵션으로 요청/응답 본문 포함을 조절하면 돼요.
출처: 문서
본문
문제
generateText나 streamText를 이미지 여러 개와 함께 사용할 때(예: 루프나 배치 처리) 다음과 같은 현상이 생길 수 있어요:
- 메모리 사용량이 계속 늘어나고 줄어들지 않아요
- 애플리케이션이 결국 메모리 부족으로 죽어요
- 가비지 컬렉션 후에도 메모리가 회수되지 않아요
특히 experimental_download로 URL의 이미지를 처리하거나, base64로 인코딩된 이미지를 프롬프트로 보낼 때 이런 현상이 두드러져요.
배경
기본적으로 AI SDK는 단계(steps) 결과에 전체 요청 메시지와 요청/응답 본문을 포함해요. 이미지를 처리할 때 요청 메시지와 요청 본문에는 base64로 인코딩된 이미지 데이터가 들어갈 수 있는데, 이 데이터는 매우 클 수 있어요(이미지 하나를 base64로 인코딩하면 1MB 이상 될 수 있어요). 이미지 여러 개를 처리하면서 결과에 대한 참조를 계속 유지하면 이 데이터가 메모리에 쌓이게 돼요.
예를 들어 500KB 크기의 이미지 100개를 처리하면 요청 본문 데이터만 메모리에 약 50MB 이상 쌓일 수 있어요.
해결 방법
include 옵션을 사용해 요청 메시지 또는 요청/응답 본문 포함을 끌 수 있어요:
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = await generateText({
model: openai('gpt-6-astra'),
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image' },
{ type: 'file', mediaType: 'image', data: imageUrl },
],
},
],
// Request and response bodies are excluded by default.
include: {
requestBody: false,
responseBody: false,
},
});
옵션
include 옵션은 다음을 받아요:
requestBody:true로 설정하면 요청 본문을 단계 결과에 포함해요. base64 인코딩된 이미지가 주로 저장되는 곳이 요청 본문이에요. 기본값:false.generateText와streamText둘 다에서 사용 가능해요.requestMessages:true로 설정하면 요청 메시지를 단계 결과에 포함해요. 요청 메시지에는 이미지, 파일 같은 큰 메시지 콘텐츠가 담길 수 있어요. 기본값:false.generateText와streamText둘 다에서 사용 가능해요.rawChunks:true로 설정하면 스트림에 원본 프로바이더 청크를 포함해요. 기본값:false.streamText에서만 사용 가능해요.responseBody:true로 설정하면 응답 본문을 단계 결과에 포함해요. 기본값:false.generateText에서만 사용 가능해요.
언제 사용할까요
- 배치 이미지 처리: 루프에서 이미지 여러 개를 처리할 때
- 오래 실행되는 에이전트: 에이전트가 수명 동안 이미지를 많이 처리할 수 있을 때
- 메모리가 제한된 환경: 메모리가 부족한 환경에서 실행할 때
트레이드오프
본문 포함을 끄면:
result.request.body나result.response.body에 접근할 수 없어요requestMessages를 활성화하지 않는 한result.request.messages에 접근할 수 없어요- 원본 요청/응답을 검사할 수 없어 디버깅이 어려워질 수 있어요
- 로깅이나 디버깅을 위해 본문이 필요하다면, 다음 반복 전에 필요한 데이터를 미리 추출해 두는 걸 고려해 보세요
예시: 이미지 여러 개 처리하기
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const imageUrls = [
/* array of image URLs */
];
const results = [];
for (const imageUrl of imageUrls) {
const result = await generateText({
model: openai('gpt-6-astra'),
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image' },
{ type: 'file', mediaType: 'image', data: imageUrl },
],
},
],
include: {
requestBody: false,
},
});
// Only store the text result, not the full result object
results.push(result.text);
}
더 배우기
더 알아보기 (Learn more)
- Azure OpenAI 스트리밍이 느릴 때
- 클라이언트 컴포넌트에서의 Server Actions
- useChat/useCompletion 스트림 출력에 텍스트 대신 0:...이 나올 때
- Streamable UI 오류
- Tool Invocation 결과 누락 오류
- 배포했는데 스트리밍이 안 될 때
- 프록시를 거치면 스트리밍이 안 될 때
- Vercel에 배포할 때 타임아웃 발생
- 닫히지 않는 스트림
- useChat 스트림 파싱 실패
- Server Action Plain Objects 오류
- useChat 응답 없음
- useChat에서 커스텀 헤더, body, credentials가 동작하지 않을 때
- Zod와 AI SDK 5의 TypeScript 성능 문제
- useChat "An error occurred"
- useChat에서 어시스턴트 메시지 반복
- 스트림이 중단될 때 onEnd가 호출되지 않음
- 구조화된 출력으로 툴 호출
- 중단과 재개 가능한 스트림
- streamText가 조용히 실패할 때
- 스트리밍 상태는 표시되는데 텍스트가 안 나올 때
- useChat의 오래된 body 값
- onToolCall의 타입 오류
- 지원되지 않는 모델 버전 오류
- OpenAI에서 객체 생성 실패
- Missing Tool Results 오류
- 모델이 "LanguageModelV1" 타입에 할당 불가
- TypeScript 오류 "Cannot find namespace 'JSX'"
- React 오류 "Maximum update depth exceeded"
- Jest: 모듈 '@ai-sdk/rsc'을 찾을 수 없음
- 이미지 여러 개 처리 시 높은 메모리 사용