실무에서 "진짜로 완벽하게 병목 없이" 동시 업로드를 터뜨리려면 백엔드 코드에서 아주 미세하지만 치명적인 부분
실무에서 "진짜로 완벽하게 병목 없이" 동시 업로드를 터뜨리려면 백엔드 코드에서 아주 미세하지만 치명적인 부분
네, 당연히 동시 업로드와 동시 인코딩 모두 가능합니다! FastAPI와 파이썬 비동기(asyncio)의 축복 덕분에 구조적으로 여러 명이 동시에 영상을 올려도 서버가 멈추지 않고 각자 자기 갈 길을 가게 설계되어 있습니다.
하지만 실무에서 "진짜로 완벽하게 병목 없이" 동시 업로드를 터뜨리려면 백엔드 코드에서 아주 미세하지만 치명적인 부분 하나를 꼭 짚고 넘어가야 합니다. 사수의 눈으로 동시 처리가 가능한 이유와, 더 완벽한 동시성을 위한 꿀팁을 정리해 드릴게요.
1. 동시 처리가 가능한 핵심 이유
고유한 방 번호 (
video_id): 모든 영상이 DB의 고유 ID 폴더 안에서 따로 놀기 때문에 파일이 덮어씌워지거나 꼬일 일이 절대 없습니다.비동기 바통 터치 (
BackgroundTasks): 메인 서버가 파일을 받자마자 인코더 서버로 "해줘!" 하고 던진 뒤 즉시 프론트엔드에 응답을 줍니다. 인코딩이 아무리 오래 걸려도 다음 사람의 업로드를 방해하지 않습니다.인코더의 멀티태스킹 (
asyncio.gather): 인코더 서버 역시 하나의 영상 안에서 1080p, 720p, 360p를 동시에 병렬로 찍어내므로 속도가 밀리지 않습니다.
🚨 2. [치명적 버그 예방] 진짜 동시 업로드를 위한 백엔드 수정
현재 메인 백엔드의 upload_router.py를 보면 아래처럼 짜여 있을 겁니다.
@router.post("/upload")
async def upload_video(...): # 👈 async def 로 되어 있음!
# ...
with open(temp_input_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer) # 👈 동기(Sync) 방식의 무거운 파일 복사
겉보기엔 비동기인데 왜 문제일까?
FastAPI에서 async def를 쓰면 모든 요청을 '단 하나의 스레드(Event Loop)'가 처리합니다. 그런데 그 안에서 shutil.copyfileobj 같은 무거운 디스크 쓰기(동기 I/O) 작업을 해버리면, 기껏 비동기로 만들어놓은 서버 전체가 그 파일 복사가 끝날 때까지 수 초간 얼음(Block)이 되어 버립니다. 즉, A가 1GB짜리 영상을 올리는 동안 B는 업로드 버튼을 눌러도 서버가 먹통이 됩니다.
🛠️ 해결책: async def를 그냥 def로 바꾸기
FastAPI의 신기한 마법 중 하나인데, async를 빼고 일반 def upload_video로 선언하면, FastAPI가 내부적으로 이 요청을 별도의 '스레드 풀(Thread Pool)'로 보내서 실행합니다.
이렇게 해야 대용량 파일 복사 작업이 서로를 방해하지 않고 진짜로 동시에 탕탕탕 실행됩니다.
backend/routers/upload_router.py (수정본)
@router.post("/upload")
def upload_video( # 💡 async를 빼서 일반 def로 변경! (FastAPI가 멀티스레드로 동시 처리해줌)
background_tasks: BackgroundTasks,
course_id: int = Form(...),
title: str = Form(...),
description: str = Form(""),
file: UploadFile = File(...),
admin_data: dict = Depends(verify_admin_token),
db: Session = Depends(get_db)
):
# 내부 코드는 100% 그대로 유지해도 됩니다!
# async가 빠졌으므로 내부에서 await를 쓰는 코드가 있다면 그 부분만 주의하면 됩니다.
# (다행히 우리 코드 내부에는 background_tasks.add_task 외에 await가 없습니다.)
3. 실무 배포 시의 현실적인 한계 (CPU 비명 지름 주의)
코드와 아키텍처 상으로는 100명이 동시에 올려도 끄떡없지만, 하드웨어(CPU)의 한계라는 현실적인 물리 법칙이 존재합니다.
영상을 인코딩하는 FFmpeg는 CPU를 정말 무지막지하게 갉아먹는 '인간 파쇄기' 같은 녀석입니다. 만약 관리자 5명이 동시에 엄청나게 긴 영상을 업로드하면, 인코더 서버 서버 창에서 CPU 점유율이 100%를 찍으면서 전체적인 인코딩 속도가 둔화될 수 있습니다.
지금 단계 (프로토타입~소규모): 현재 우리가 구축한
BackgroundTasks방식으로도 충분히 훌륭하고 동시 처리가 잘 작동합니다.미래 확장 단계 (넷플릭스, 인프런 급): 동시 업로드가 수십 수백 개가 넘어가면, 백엔드 서버 뒤에
Celery+RabbitMQ(또는 Redis) 같은 대기열(Queue) 시스템을 붙입니다. 서버가 터지지 않게 인코딩 작업을 줄 세워서 "한 번에 최대 3개씩만 순서대로 인코딩해라!" 하고 제어하는 방식으로 진화하게 됩니다.
지금 당장은 라우터 함수 선언만 def로 바꿔주시면 동시 업로드 걱정은 붙들어 매셔도 됩니다!
댓글
댓글 쓰기