일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 웹개발포트폴리오
- Python
- 코딩 국비지원
- 엘리스 AI 트랙
- 와탭랩스
- 개발자 채용설명회
- 프레임워크vs라이브러리
- 블로그와 친해지기
- 인공지능모델학습
- 엘리스
- 코딩부트캠프
- 엘리스AI트랙
- 엘리스AI트랙데모데이
- 팀프로젝트
- after_this_request
- tempfile
- REACT
- 이미지처리프로젝트
- reactStrictMode
- 코딩배우기
- 코딩교육
- 코딩국비지원
- devmode
- 프로젝트마무리
- pymupdf
- 웹개발프로젝트
- aws_s3
- 부트캠프프로젝트발표
- fabricjs
- FLASK
Archives
- Today
- Total
자몽이 조아
[python,Flask]임시 파일 생성 및 처리 방식 비교 본문
반응형
파일을 생성하고 반환하는 방식은 웹 애플리케이션에서 자주 사용되는 패턴입니다. 현재 사용하고 있는 방식은 tempfile.mkdtemp()를 사용하여 임시 디렉토리를 만들고, 해당 디렉토리에 파일을 저장한 후 반환하는 구조입니다. 이 방법이 일반적으로 사용되는지, 그리고 대체 방법과 비교했을 때의 장단점을 정리해보겠습니다.
1. 현재 방식 (tempfile.mkdtemp())
✅ 장점
- 보안성 확보
- 임시 디렉토리를 생성하여 외부 접근을 방지할 수 있음.
- OS가 제공하는 임시 저장소를 사용하므로, 별도의 관리가 필요 없음.
- 다중 사용자 처리 가능
- 각 요청마다 별도의 디렉토리를 생성하므로, 여러 사용자가 동시에 요청해도 파일이 충돌할 가능성이 낮음.
- 자동 삭제 가능
- @after_this_request를 활용하여 응답이 끝난 후 파일을 삭제할 수 있음.
- 유연한 확장 가능
- 현재 로직을 조금 수정하면 여러 종류의 파일을 유동적으로 생성할 수 있음.
❌ 단점
- 디스크 I/O 부하 발생 가능
- 요청이 많아지면 임시 디렉토리와 파일을 계속 생성/삭제해야 하므로 디스크 I/O가 증가할 수 있음.
- 파일 삭제 실패 가능성
- @after_this_request를 사용하지만, 파일이 삭제되기 전에 서버가 중지되거나 오류가 발생하면 파일이 남을 가능성이 있음.
- Docker 컨테이너 환경에서 주의 필요
- 컨테이너 내부의 /tmp 디렉토리를 사용할 경우, 컨테이너가 삭제되면 파일도 사라지지만, 파일 정리가 안 되면 공간을 계속 차지할 수 있음.
2. 대체 방법
① 메모리 기반 파일 처리 (io.BytesIO)
io.BytesIO()를 활용하면 파일을 디스크에 저장하지 않고 메모리에서 직접 처리할 수 있습니다.
import io
from flask import send_file
@app.route('/generate-file/<file_id>', methods=['GET'])
def generate_pdf_api(file_id):
csv_path = get_csv_from_s3(file_id)
if not csv_path:
return jsonify({"error": "CSV file not found"}), 404
pdf_buffer = generate_excel_pdf_in_memory(csv_path)
if pdf_buffer is None:
return jsonify({"error": "PDF file was not generated"}), 500
return send_file(io.BytesIO(pdf_buffer), as_attachment=True, download_name="output.pdf", mimetype="application/pdf")
✅ 장점
- 디스크 I/O 부담 없음 → 파일을 생성할 필요 없이 메모리에서 바로 응답 가능.
- 속도 향상 → 작은 파일의 경우, 디스크에서 읽고 쓰는 속도보다 훨씬 빠름.
- 파일 삭제 관리가 필요 없음 → 파일을 저장하지 않으므로 @after_this_request로 파일을 삭제할 필요가 없음.
❌ 단점
- 메모리 사용량 증가 → 큰 파일을 생성할 경우, 서버 메모리를 과다하게 사용할 가능성이 있음.
- 재사용이 어려움 → 파일을 임시로 저장하지 않으므로, 다른 API에서 동일한 파일을 다시 사용하려면 다시 생성해야 함.
② 비동기 작업을 활용한 저장 방식 (Celery + Redis)
Flask 앱이 직접 파일을 생성하고 응답하는 대신, 비동기 작업 큐(Celery + Redis)를 활용하여 파일을 백그라운드에서 생성하고, 완료되면 사용자가 다운로드할 수 있도록 처리할 수도 있습니다.
from celery import Celery
from flask import jsonify
celery = Celery('tasks', broker='redis://localhost:6379/0')
@celery.task
def generate_pdf_task(file_id):
csv_path = get_csv_from_s3(file_id)
if not csv_path:
return None
pdf_path = generate_excel_pdf(csv_path)
return pdf_path
@app.route('/generate-file/<file_id>', methods=['GET'])
def generate_pdf_api(file_id):
task = generate_pdf_task.delay(file_id)
return jsonify({"task_id": task.id}), 202
@app.route('/get-file/<task_id>', methods=['GET'])
def get_file(task_id):
task = generate_pdf_task.AsyncResult(task_id)
if task.state == 'SUCCESS':
return send_file(task.result, as_attachment=True, download_name="output.pdf", mimetype="application/pdf")
elif task.state == 'PENDING':
return jsonify({"status": "Processing"}), 202
else:
return jsonify({"error": "File generation failed"}), 500
✅ 장점
- 비동기 처리 가능 → 서버가 파일을 바로 생성하는 것이 아니라, 백그라운드에서 처리한 후 사용자가 나중에 받을 수 있음.
- 확장성 뛰어남 → 사용자가 많아질 경우에도 Redis와 Celery를 활용해 로드 밸런싱 가능.
- 서버 부하 감소 → API 서버는 요청을 바로 응답하고, 파일 생성은 별도의 백그라운드 작업으로 수행됨.
❌ 단점
- 설치 및 관리 필요 → Celery와 Redis 설정이 필요하며, 운영이 복잡해질 수 있음.
- 즉시 다운로드 불가 → 사용자는 파일을 기다려야 하며, 다운로드 링크를 따로 받아야 함.
③ S3에 직접 저장 후 URL 반환
파일을 로컬에 저장하지 않고, AWS S3 같은 외부 스토리지에 직접 업로드한 후 URL을 반환할 수도 있습니다.
import boto3
from flask import jsonify
s3_client = boto3.client('s3')
def upload_to_s3(file_path, bucket_name, key):
s3_client.upload_file(file_path, bucket_name, key)
return f"https://{bucket_name}.s3.amazonaws.com/{key}"
@app.route('/generate-file/<file_id>', methods=['GET'])
def generate_pdf_api(file_id):
csv_path = get_csv_from_s3(file_id)
if not csv_path:
return jsonify({"error": "CSV file not found"}), 404
pdf_path = generate_excel_pdf(csv_path)
if pdf_path is None:
return jsonify({"error": "PDF file was not generated"}), 500
file_url = upload_to_s3(pdf_path, "my-bucket", f"generated_pdfs/{file_id}.pdf")
return jsonify({"file_url": file_url})
✅ 장점
- 파일 저장 관리가 필요 없음 → 로컬 파일을 저장하고 삭제할 필요 없이 S3에서 관리 가능.
- 확장성 뛰어남 → 클라우드 저장소를 사용하므로 파일 크기가 커져도 문제 없음.
- 비용 효율적 → 서버 스토리지를 차지하지 않고, S3에서 비용 효율적으로 저장 가능.
❌ 단점
- S3 설정 필요 → AWS 계정이 필요하고, 버킷 및 권한을 설정해야 함.
- 업로드 속도 영향 → 인터넷 업로드 속도에 따라 파일이 저장되는 시간이 달라질 수 있음.
3. 정리 및 결론
방법 | 장점 | 단점 | 추천 상황 |
tempfile.mkdtemp() | 보안성 높음, 다중 사용자 처리 가능 | 디스크 I/O 부하, 삭제 실패 가능성 | 일반적인 Flask API에서 임시 파일 생성 |
io.BytesIO() | 디스크 I/O 없음, 속도 빠름 | 큰 파일에서 메모리 부담 | 작은 파일을 빠르게 반환할 때 |
Celery + Redis | 비동기 처리 가능, 서버 부하 감소 | 설정이 복잡, 즉시 다운로드 불가 | 대량 요청을 처리해야 하는 경우 |
S3 저장 후 URL 반환 | 스토리지 관리 불필요, 확장성 뛰어남 | S3 설정 필요, 업로드 속도 영향 | 클라우드 환경에서 장기 보관이 필요할 때 |
현재 방법(tempfile.mkdtemp())도 널리 사용되지만, 파일 크기와 요청량이 증가할 경우 io.BytesIO() 또는 S3 저장 방식을 고려하는 것이 좋습니다.
반응형
Comments