Django - Streaming 기초

코지클래식·2021년 10월 24일
0

장고에서 텍스트가 아닌 파일 (이미지, 동영상)을 브라우저로 전송할 때 알아야 하는 것들을 정리합니다. 업로드 하는 방법은 포함되지 않습니다.

1. 파일 읽기

파이썬에서 제공하는 파일을 읽는 방법을 사용합니다.

1. 파일 선택

파일을 선택하는 명령어 : open (파이썬 내장함수)


f = open('파일경로/파일명.확장자', [옵션])
  • 옵션에 'rb'를 넣어서 파일을 'bytes' 형태로 읽을 수 있습니다. 이는 텍스트가 아닌 파일 (이미지/동영상)을 읽을 때 사용하는 옵션입니다. (여러 옵션이 있음)
  • 뒤에 붙은 'rb'가 없으면 기본적으로 'utf-8'로 파일을 열게 됩니다 (기본 설정일 때). 이미지/동영상은 utf-8로 읽으려고하면 제대로 사용할 수 없습니다.

2. 파일 읽기

파일을 읽는 명령어 : read(), readline(), readlines()


f.read([읽으려고 최대 바이트 숫자])

f.readline([읽으려고 최대 바이트 숫자])

f.readlines([읽으려고 최대 바이트 숫자])
  • read를 옵션없이 호출하면, 파일을 "현재 위치" 부터 끝까지 읽어 값을 return합니다.

  • readline을 옵션없이 호출하면, "현재 위치"부터 \n으로 구분되는 줄의 끝 까지 파일을 읽어 값을 return합니다.

  • readlines를 옵션없이 호출하면, "현재 위치"부터 줄을 구분하면서 파일을 끝까지 읽어 값을 return 합니다.

  • read, readline, readlines를 사용하고난 후에는, 마지막으로 byte를 읽은 위치 = "현재위치"가 됩니다.

  • readline 메서드GNU readline 인터페이스 모듈과는 구분해야 합니다.

3. 위치 변경하기

위치를 변경하는 명령어 : seek

file.seek(offset, [기준점=0])
  • seek 명령어를 사용해서 파일을 읽는 "현재 위치"를 변경할 수 있습니다.

4. 데이터 전달하기

  • read()로 읽은 값을 HttpResponse로 응답하면 됩니다.

2. 브라우저와 호환하기

동영상을 재생할 때 Response Header에 포함된 Key/Value 샘플

'Content-Type' : 'video/mp4',
'Content-Length' : '41897339',
'Accept-Ranges' : 'bytes',
'Content-Range' : 'bytes 0-50000/41927339'

1. MIME

브라우저에서 데이터가 어떤 종류의 파일인지 알기 위해 헤더에 뭔가를 추가해 줘야만 합니다. 추가해줘야 하는 Key는 'content-type'이고, Values는 MIME라고 불리는 규칙에 의해 파일마다 다르게 지정되어 있습니다.
그러므로, 각 데이터와 함께 올바른 MIME 타입을 전송하도록, 서버가 정확히 설정하는 것이 중요합니다. 브라우저가 리소스를 내려받았을 때 해야 할 기본 동작이 무엇인지를 결정하기 위해서 MIME 타입이 꼭 필요합니다.

2. Content-length

서버에서 브라우저로 response를 보낼 때, 브라우저는 데이터가 제대로 전부 받았는지 확인하기 위해 'content-length'와 데이터의 길이(body)가 일치하는지 확인합니다.

'Content-Length'는 헤더에 들어있으며, 이는 우리가 response하는 데이터의 길이와 동일해야합니다.
보통은 자동으로 입력되지만, 없는 경우 우리가 직접 body에 들어가는 데이터의 길이를 확인해서 작성해줘야만 합니다.


! 여기까지만 해도 파일 자체를 보내거나 하는 동작은 할 수 있습니다.

3. Accept-Ranges

비디오를 전송하는 경우, 브라우저에서는 흔히 재생 스크롤의 가운데를 눌러서, '중간부터 다운로드' 라는 동작을 지원할 수 있습니다. 그러나 이는 모든 경우에 가능한 것이 아닙니다. 서버에서 "중간부터 다운로드 동작을 지원" 한다는 신호를 보내줘야합니다. 헤더에 'Accept-Ranges'라는 키값이 있을 때 이 신호가 보내집니다.
이 Accept-Ragnes의 Value는 범위를 정의하기 위해 사용될 수 있는 단위를 가리킵니다. 보통은 bytes를 사용합니다.

4. Content-Ranges

3번의 'Accept-Ragnes'가 있는 경우, 브라우저에서는 requset header에 'Range' 라는 KEY를 추가해 데이터의 범위를 요청 하는데, "Content-Ranges"는 이 요청이 제대로 응답되고 있음을 표시합니다. 즉, 데이터의 범위를 return해줍니다.

3. 중간정리

  • 우리는 이제 파일을 bytes 형태로 읽을 수 있습니다.
  • 파일을 중간부터 원하는 범위만큼 읽을 수 있습니다.
  • 브라우저에서 동영상이 동작하기 위해 꼭 필요한 Header의 KEY값들을 알게 되었습니다.

! 이 아래에 있는 내용은 정확하지 않고 환경마다 다를 수 있으므로, 사용에 주의가 필요합니다.

4. 효율성 증가

1. 데이터 자르기 (Chunk)

대용량의 데이터를 효율적으로 전송하기 위해서는, 데이터를 한번에 네트워크에 올리는 것보다 데이터를 잘게 쪼개어 보내는 것이 유리합니다.

2. 자르는 이유

그 이유는 많은 양의 데이터가 클라이언트에 전송되면, 전송이 완전히 처리되기 전까지 클라이언트는 아무런 동작을 할 수 없기 때문입니다.
조금 더 자세히 설명하면, 브라우저가 동작을 하기 위해서는 데이터가 제대로 왔는지 확인이 해야 합니다. 이는 위에 적은 Content-Length가 받은 데이터와 일치하는지 확인하는 작업입니다. 따라서 이 확인은 전송이 완료되어야 합니다.

또 네트워크에 중간에 오류가 발생해서 데이터에 결함이 발생한다면 재앙이 일어날 수 있습니다. 브라우저는 데이터의 결함이 있는 것만 알고 어디에 문제가 있는지 알 수 없으므로, 요청/응답을 없던 일로 치고 처음부터 다시 다운로드 받을 수도 있습니다. (키워드 : 트랜잭션)

3. 파이썬에서 동작시키기

파이썬에서 이렇게 파일을 잘라서 동작시키려면, 파일을 "일정 단위로 잘라서" Response를 보내어야 합니다. 이렇게 "일정 단위로 자르는" 동작은 파이썬의 여기저기에서 지원하는 동작입니다. 우리가 흔히 아는 리스트/배열이 "Iterable" 할 때 for문, while문을 사용할 수 있는 것과 같습니다.

파이썬에서는 파일을 이렇게 'Iterable'하게 만들어주는 내장 메서드를 지원합니다.

이 메서드를 사용하면 파이썬은 자동으로 파일을 chunk해서 response를 할 것입니다.

from wsgiref.util   import FileWrapper

return HttpReponse (FileWrapper(video_file), content_type='video/mp4'
profile
코지베어

0개의 댓글