Spring Boot에서 파일을 스트리밍(Stream) 방식으로 write할 때, 메모리에 올릴지 여부는 사용 방식에 따라 달라집니다. 하지만 일반적인 경우 스트리밍은 메모리 사용을 최소화하기 위한 기법으로, 전체 데이터를 메모리에 올리지 않고 일정 크기의 버퍼를 통해 점진적으로 처리합니다.
✅ 메모리에 올리지 않는 경우 (Streaming 방식)
Java에서 InputStream → OutputStream 형태로 데이터를 전달할 때 보통 다음처럼 사용합니다:
try (InputStream in = ...;
OutputStream out = new FileOutputStream("output.txt")) {
byte[] buffer = new byte[8192]; // 8KB 버퍼
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, bytesRead, 0);
}
}
이 방식은:
- 한 번에 일정 크기만 메모리에 올림
- 전체 파일을 메모리에 적재하지 않음 (메모리 친화적)
- 대용량 파일 처리에 적합
❌ 메모리에 올라가는 경우 (비효율적 처리 방식)
다음과 같이 전체 데이터를 한 번에 읽거나 쓸 경우, 전부 메모리에 올라가게 됩니다:
byte[] data = Files.readAllBytes(Paths.get("largefile.txt")); // 전체 메모리에 로딩
Files.write(Paths.get("output.txt"), data); // 한꺼번에 쓰기
이는:
- 메모리 부담이 큼
- 대용량 파일 처리에는 부적합
- OOM(OutOfMemoryError) 발생 가능
Spring Boot에서의 사용 예
Spring Boot에서는 일반적으로 StreamingResponseBody, FileCopyUtils, 또는 InputStreamResource 등을 통해 스트리밍을 지원합니다:
예: 클라이언트로 파일 스트리밍
@GetMapping("/download")
public ResponseEntity<StreamingResponseBody> downloadFile() throws IOException {
InputStream inputStream = new FileInputStream(new File("example.txt"));
StreamingResponseBody responseBody = outputStream -> {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=example.txt")
.body(responseBody);
}
위 방식은 실제로는 데이터를 조금씩 읽고 조금씩 쓰기 때문에 메모리에 전부 올라가지 않습니다.
결론
- Stream 방식으로 처리하면 메모리에 전체 파일이 올라가지 않습니다.
- 다만, 사용 방식에 따라 잘못 구성하면 전부 메모리에 올릴 수 있습니다.
- 특히 대용량 파일 처리 시에는 반드시
Buffered스트림이나StreamingResponseBody등을 사용해야 합니다.