실무에서 업로드 중 끊긴거를 대용량 파일 업로드시 어케하나?
네, 정확합니다! 시스템의 생명 주기를 아주 날카롭게 꿰뚫어 보셨네요.
현재 우리가 구현한 구조에서는 인코더 서버(14002번 포트, media-encoder) 컨테이너가 다운되거나 재시작(restart)되면, 그 즉시 진행 중이던 FFmpeg 인코딩 프로세스도 강제로 종료(뚝 끊김)됩니다.
어떤 컨테이너가 다운되느냐에 따라 발생하는 현상과, 이를 실무(Netflix급)에서는 어떻게 방어하는지 깔끔하게 정리해 드릴게요.
1. 인코더 서버(media-encoder)가 다운될 경우
인코딩은 파이썬 내부에서 asyncio.create_subprocess_exec로 FFmpeg 프로그램을 실행한 것입니다. 따라서 인코더 서버가 죽으면 다음 3가지 문제가 터집니다.
인코딩 찌꺼기 파일 발생: 1080p, 720p 등을 만들다가 멈췄기 때문에, 폴더 안에는 쓰다 만 몇 개의
.ts청크 파일과 비어있는master.m3u8만 덩그러니 남게 됩니다.유령 데이터(Zombie)화: 메인 백엔드 서버(14001)는 인코더 서버가 죽었는지 살았는지 알 길이 없습니다. 따라서 DB의
is_active상태는 영원히0 (⏳ 화질 최적화 중...)으로 멈춰버립니다. 유저는 평생 이 영상을 볼 수 없게 되죠.
2. 메인 백엔드 서버(api)가 다운될 경우
재미있는 점은, 파일 업로드가 끝나고 인코딩이 시작된 후에 메인 백엔드 서버가 다운되더라도 인코더 서버는 아무 일 없다는 듯 끝까지 100% 인코딩을 완료합니다. 두 서버가 도커 안에서 격리되어 있기 때문입니다.
하지만 결과는 실패: 인코더가 100% 변환을 끝내고 메인 서버에 "나 다 했어!" 하고 웹훅(PATCH)을 쏘려고 보니까 메인 서버가 죽어있습니다. 결국 통신 에러(
Connection Refused)가 나고, DB의is_active는 여전히0으로 남게 됩니다.
🏛️ 실무(인프런, 넷플릭스)에서는 이 문제를 어떻게 해결할까?
대용량 영상을 다루는 서비스에서는 인코딩 서버가 언제든 다운되거나(OOM 에러 등) 불시에 재부팅될 수 있다고 가정하고 시스템을 설계합니다. 크게 2가지 방어벽을 세웁니다.
① 태스크 큐 (Task Queue: Celery + Redis / RabbitMQ)
현재 우리는 FastAPI가 메모리에서 대기열을 관리하는 BackgroundTasks를 쓰고 있습니다. 서버가 꺼지면 이 대기열도 증발하죠.
실무에서는 Celery 같은 전문 대기열 시스템을 씁니다. 인코딩 명령을 Redis라는 안전한 메모리 창고에 보관해 두고, 인코더 서버가 꺼졌다 켜지면 창고에서 "아까 하다가 원본 파일만 남고 멈춘 작업"을 다시 꺼내서 자동으로 처음부터 재인코딩을 수행합니다.
② 배치(Batch) 프로그램 / 헬스 체크 스크립트
메인 백엔드 서버에 주기적으로 도는 감시 프로그램(스케줄러)을 만듭니다.
"어? 이 영상은 업로드된 지 30분이 지났는데도 여전히 상태가
is_active = 0 (인코딩 중)이네? 인코더가 뻗었었나 보다. 상태를인코딩 실패로 변경하고 관리자에게 알림을 보내자!"
💡 현재 프로토타입 단계에서의 대처법
지금 개발 중인 단계에서는 인코더 서버를 재시작하거나 다운시켰을 때 멈춘 영상이 있다면, 그냥 관리자 페이지에서 해당 영상을 한 번 더 업로드하시는 게 가장 깔끔합니다. 새로운 DB ID로 폴더가 새로 파지면서 인코딩이 다시 처음부터 정상 작동할 것입니다!
댓글
댓글 쓰기