FastAPI에서 multipart/form-data 형식의 파일을 수신할 때, 데이터 타입으로 단순한 bytes를 사용할 수도 있고 FastAPI 내장 객체인 UploadFile을 사용할 수도 있습니다.
Spring Boot의 MultipartFile과 유사한 이 UploadFile은 단순한 데이터 수신용 객체가 아닙니다. 특히 대용량 다중 파일 업로드 시 서버 자원을 효율적으로 관리하기 위한 핵심 로직을 포함하고 있습니다. 왜 UploadFile을 사용해야 하는지, 그 내부 동작 원리와 기술적 배경을 살펴보겠습니다.
bytes 수신의 한계와 OOM(Out Of Memory) 위험만약 파일 수신 파라미터를 files: List[bytes]로 선언한다면, 클라이언트가 전송한 파일 데이터는 즉시 서버의 RAM에 전량 적재됩니다.
예를 들어 사용자가 10MB 크기의 사진 10장을 업로드할 경우, 순간적으로 100MB의 메모리가 할당됩니다. 이러한 다중 업로드 요청이 동시에 100건만 유입되어도 서버 메모리 사용량은 10GB를 초과하게 되며, 결국 서버가 버티지 못하고 다운되는 OOM(Out Of Memory) 장애가 발생합니다.
UploadFile은 위와 같은 메모리 폭발을 방지하기 위해, 내부적으로 파이썬의 SpooledTemporaryFile 클래스를 기반으로 한 스풀링 전략을 사용합니다.
이러한 메커니즘 덕분에 1GB 크기의 대용량 동영상이 업로드되더라도 서버의 실제 메모리 점유율은 1MB 수준으로 통제됩니다. 즉, 수십 MB 단위의 다중 파일 트래픽이 발생해도 백엔드 서버의 리소스를 일관되고 안전하게 유지할 수 있습니다.
디스크로 스풀링된 데이터라도, UploadFile 객체가 제공하는 표준 인터페이스를 통해 병목 현상 없이 효율적으로 다룰 수 있습니다. FastAPI의 비동기 아키텍처와 맞물려 다음과 같은 핵심 기능들을 제공합니다.
① 파일 메타데이터 속성
객체 내부에 파일 정보가 매핑되어 있어 별도의 파싱 없이 즉시 접근 가능합니다.
file.filename: 전송된 원본 파일명 (예: screenshot.png)file.content_type: 파일의 MIME 타입 (예: image/jpeg)file.size: 파일의 총 바이트(Byte) 크기② 표준 비동기 파일 I/O 메서드
await file.read(): 스풀링된(메모리+디스크) 실제 파일 데이터를 바이트 스트림으로 읽어 들입니다. 비동기 처리되므로 메인 스레드가 블로킹되지 않습니다.await file.seek(0): 스트림 커서를 맨 처음으로 되돌려 여러 번의 반복 읽기를 지원합니다.await file.close(): 처리가 끝난 후, 디스크에 기록되었던 임시 파일 찌꺼기들을 즉각 삭제하여 서버 스토리지를 확보합니다. (엔드포인트 요청이 종료되면 프레임워크가 자동으로 회수하기도 합니다.)FastAPI의 UploadFile은 단순한 데이터 wrapper가 아니라, 대용량 파일 처리를 위한 메모리 자동 관리(Spooling)와 비동기 입출력 기능이 통합된 안전장치입니다. 다중 파일 처리 엔드포인트 설계 시 리소스 최적화를 위해 반드시 적용해야 하는 필수 규격입니다.