재개 가능한 업로드

Google API의 재개 가능한 업로드 프로토콜을 사용하면 동영상을 더 안정적으로 업로드할 수 있습니다. 이 프로토콜은 네트워크 중단 또는 기타 전송 실패 후 업로드 작업을 재개할 수 있게 해주므로, 네트워크 오류가 발생할 때 시간과 대역폭을 절약할 수 있습니다.

특히 다음과 같은 경우 재개 가능한 업로드를 사용하면 유용합니다.

  • 용량이 큰 파일을 전송하는 경우
  • 네트워크가 중단될 가능성이 높은 경우
  • 휴대기기와 같은 대역폭이 낮거나 인터넷 연결이 불안정한 기기에서 업로드를 시작하는 경우

이 가이드에서는 재개 가능한 업로드 절차를 사용하여 동영상을 업로드하기 위해 애플리케이션에서 생성하는 HTTP 요청의 순서를 설명합니다. 이 가이드는 재개 가능한 업로드에 대한 기본적인 지원을 제공하는 Google API 클라이언트 라이브러리를 사용할 수 없는 개발자를 주요 대상으로 합니다. YouTube Data API - 동영상 업로드 가이드에서는 재개 가능한 업로드 절차를 사용하여 동영상을 업로드하기 위해 Python용 Google API 클라이언트 라이브러리를 사용하는 방법을 설명합니다.

참고: HTTPS 로깅이 사용 설정된 Google API 클라이언트 라이브러리 중 하나를 사용하여 재개 가능한 업로드 또는 기타 API 작업에 대한 일련의 요청을 확인할 수도 있습니다. 예를 들어 Python에 HTTP 트레이스를 사용 설정하려면 httplib2 라이브러리를 사용합니다.

httplib2.debuglevel = 4

1단계 - 재개 가능한 세션 시작

재개 가능한 동영상 업로드를 시작하려면 다음 URL로 POST 요청을 보냅니다. URL에서 part 매개변수 값을 요청에 적합한 값으로 설정합니다. 매개변수 값은 설정 중인 속성이 포함된 부분을 식별하며 API 응답에 포함하려는 부분도 식별합니다. 요청 URL의 매개변수 값은 URL로 인코딩되어야 합니다.

https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=PARTS

요청 본문을 video 리소스로 설정합니다. 다음 HTTP 요청 헤더도 설정합니다.

  • Authorization: 요청의 승인 토큰입니다.
  • Content-Length – 요청 본문에 제공된 바이트 수입니다. 단위 분할된 전송 인코딩을 사용하는 경우 이 헤더를 제공할 필요가 없습니다.
  • Content-Type: 값을 application/json; charset=UTF-8로 설정합니다.
  • X-Upload-Content-Length – 후속 요청에서 업로드할 바이트 수입니다. 값은 업로드하는 파일의 크기로 설정합니다.
  • x-upload-content-type: 업로드하는 파일의 MIME 유형입니다. 모든 동영상 MIME 유형 (video/*) 또는 MIME 유형 application/octet-stream의 파일을 업로드할 수 있습니다.

다음 예는 동영상 업로드를 위한 재개 가능한 세션을 시작하는 방법을 보여줍니다. 요청은 video 리소스의 snippetstatus 부분에 속성을 설정하고 가져옵니다. 또한 리소스의 contentdetails 부분에 있는 속성도 검색합니다.

post /upload/youtube/v3/videos?uploadType=resumable&part=parts http/1.1
host: www.googleapis.com
authorization: bearer auth_token
content-length: content_length
content-type: application/json; charset=utf-8
x-upload-content-length: x_upload_content_length
X-Upload-Content-Type: X_UPLOAD_CONTENT_TYPE

video resource

다음 예는 인증 토큰을 제외하고 이러한 모든 값이 채워진 POST 요청을 보여줍니다. 이 예에서 categoryId 값은 동영상 카테고리에 해당합니다. 지원되는 카테고리 목록은 API의 videoCategories.list 메서드를 사용하여 검색할 수 있습니다.

POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer AUTH_TOKEN
Content-Length: 278
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Length: 3000000
X-Upload-Content-Type: video/*

{
  "snippet": {
    "title": "My video title",
    "description": "This is a description of my video",
    "tags": ["cool", "video", "more keywords"],
    "categoryId": 22
  },
  "status": {
    "privacyStatus": "public",
    "embeddable": True,
    "license": "youtube"
  }
}

Step 2 - Save the resumable session URI

요청이 성공하면 API 서버가 200(OK) HTTP 상태 코드로 응답하며, 응답에는 재개 가능한 세션의 URI를 지정하는 Location HTTP 헤더가 포함됩니다. 동영상 파일을 업로드할 때 이 URI를 사용합니다.

다음 예는 1단계의 요청에 대한 샘플 API 응답을 보여줍니다.

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
Content-Length: 0

3단계 - 동영상 파일 업로드

API 응답에서 세션 URI를 추출한 후 해당 위치에 실제 동영상 파일 콘텐츠를 업로드해야 합니다. 요청 본문은 업로드하는 동영상의 바이너리 파일 콘텐츠입니다. 다음 예는 요청 형식을 보여줍니다.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: CONTENT_LENGTH
Content-Type: CONTENT_TYPE

BINARY_FILE_DATA

요청은 다음과 같은 HTTP 요청 헤더를 설정합니다.

  • Authorization: 요청의 승인 토큰입니다.
  • Content-Length: 업로드하는 파일의 크기입니다. 이 값은 1단계의 X-Upload-Content-Length HTTP 요청 헤더와 같은 값이어야 합니다.
  • Content-Type: 업로드하는 파일의 MIME 유형입니다. 이 값은 1단계의 X-Upload-Content-Type HTTP 요청 헤더와 같은 값이어야 합니다.

4단계 - 업로드 절차 완료

요청으로 인해 다음 시나리오 중 하나가 발생하게 됩니다.

  • 업로드가 완료되었습니다.

    API 서버가 HTTP 201(Created) 응답 코드로 응답합니다. 응답 본문은 만든 video 리소스입니다.

  • 업로드에 실패했지만 재개할 수 있습니다.

    다음과 같은 경우 업로드를 재개할 수 있습니다.

    • 애플리케이션과 API 서버 간의 연결이 끊어져 요청이 중단되었습니다. 이 경우 API 응답을 받지 않습니다.

    • API 응답은 다음 5xx 응답 코드를 지정합니다. 이러한 응답 코드를 받은 후 업로드를 재개할 때 코드에서 지수 백오프 전략을 사용해야 합니다.

      • 500~Internal Server Error
      • 502~Bad Gateway
      • 503~Service Unavailable
      • 504~Gateway Timeout

    업로드를 재개하려면 아래의 업로드 상태 확인업로드 재개 안내를 따르세요. 재개 가능한 각 세션 URI는 수명이 제한되어 있으며 결국에는 만료됩니다. 따라서 세션 URI를 받는 즉시 재개 가능한 업로드를 시작하거나 중단이 발생한 후 빠른 시간 내에 중단된 업로드를 재개하는 것이 좋습니다.

  • 업로드가 영구적으로 실패했습니다.

    업로드에 실패한 경우 응답에 실패의 원인을 설명하는 오류 응답이 포함되어 있습니다. 영구적으로 실패한 업로드의 경우 API 응답에 위에 나열된 코드가 아닌 4xx 응답 코드 또는 5xx 응답 코드가 포함됩니다.

    만료된 세션 URI를 사용하여 요청을 전송하면 서버에서 404 HTTP 응답 코드 (Not Found)를 반환합니다. 이 경우 재개 가능한 새 업로드를 시작하고 새 세션 URI를 가져온 후 새 URI를 사용하여 업로드를 처음부터 시작해야 합니다.

4.1단계: 업로드 상태 확인

중단된 재개 가능한 업로드의 상태를 확인하려면 2단계에서 검색했고 3단계에서도 사용한 업로드 URL에 빈 PUT 요청을 전송합니다. 요청에서 Content-Range 헤더 값을 bytes */CONTENT_LENGTH로 설정합니다. 여기서 CONTENT_LENGTH는 업로드하는 파일의 크기입니다.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 0
Content-Range: bytes */CONTENT_LENGTH

4.2단계: API 응답 처리

업로드가 이미 완료된 경우 업로드 성공 또는 실패 여부에 관계없이 API는 업로드가 처음 완료되었을 때 전송했던 것과 동일한 응답을 반환합니다.

하지만 업로드가 중단되었거나 아직 진행 중인 경우 API 응답에 HTTP 308(Resume Incomplete) 응답 코드가 포함됩니다. 응답에서 Range 헤더는 성공적으로 업로드된 파일의 바이트 수를 지정합니다.

  • 헤더 값의 색인은 0에서 생성됩니다. 따라서 헤더 값이 0-999999이면 파일의 처음 1,000,000바이트가 업로드되었음을 나타냅니다.
  • 아직 업로드된 항목이 없는 경우 API 응답에 Range 헤더가 포함되지 않습니다.

아래 샘플 응답은 재개 가능한 업로드와 관련된 API 응답의 형식을 보여줍니다.

308 Resume Incomplete
Content-Length: 0
Range: bytes=0-999999

API 응답에 Retry-After 헤더도 포함되어 있으면 이 헤더의 값을 사용하여 업로드를 재개할 시기를 결정합니다.

4.3단계: 업로드 재개

업로드를 재개하려면 2단계에서 캡처한 업로드 URL에 다른 PUT 요청을 전송합니다. 요청 본문을 아직 업로드되지 않은 동영상 파일의 일부분과 관련된 바이너리 코드로 설정합니다.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: REMAINING_CONTENT_LENGTH
Content-Range: bytes FIRST_BYTE-LAST_BYTE/TOTAL_CONTENT_LENGTH

PARTIAL_BINARY_FILE_DATA

다음과 같은 HTTP 요청 헤더를 설정해야 합니다.

  • Authorization: 요청의 승인 토큰입니다.

  • Content-Length – 아직 업로드되지 않은 콘텐츠의 크기(바이트)입니다. 파일의 나머지 부분을 업로드하는 경우 TOTAL_CONTENT_LENGTH 값에서 FIRST_BYTE 값을 빼면 이 값을 계산할 수 있습니다. 두 값 모두 Content-Range 헤더에 사용됩니다.

  • Content-Range: 업로드 중인 파일의 일부입니다. 헤더 값은 다음 세 가지 값으로 구성됩니다.

    • FIRST_BYTE – 업로드를 재개하는 바이트 번호의 0 기반 숫자 색인입니다. 이 값은 이전 단계에서 검색한 Range 헤더의 두 번째 숫자보다 숫자 하나 큽니다. 이전 예에서 Range 헤더 값은 0-999999이므로 후속 재개 업로드의 첫 번째 바이트는 1000000입니다.

    • LAST_BYTE – 업로드하는 바이너리 파일의 마지막 바이트와 관련된 0을 기준으로 한 숫자 색인입니다. 일반적으로 파일의 마지막 바이트입니다. 예를 들어 파일 크기가 3000000바이트인 경우 파일의 마지막 바이트는 2999999가 됩니다.

    • TOTAL_CONTENT_LENGTH: 동영상 파일의 총 크기(바이트)입니다. 이 값은 원본 업로드 요청에 지정된 Content-Length 헤더와 동일합니다.

    참고: 비연속 바이너리 파일 블록은 업로드할 수 없습니다. 비연속 블록을 업로드하려고 하면 나머지 바이너리 콘텐츠가 전혀 업로드되지 않습니다.

    따라서 재개된 업로드에서 업로드된 첫 번째 바이트는 YouTube에 성공적으로 업로드된 마지막 바이트의 다음 바이트여야 합니다. 4.2단계Range 헤더에 관한 설명을 참고하세요.

    따라서 Range 헤더의 마지막 바이트가 999999이면 업로드 재개 요청의 첫 번째 바이트는 1, 000,000바이트여야 합니다. 두 번호 모두 0부터 시작하는 색인을 사용합니다. 999999바이트 이하 (바이트 중복) 또는 1000001바이트 이상 (바이트 건너뛰기)에서 업로드를 재개하려고 하면 바이너리 콘텐츠가 업로드되지 않습니다.

파일을 단위별로 업로드하세요.

네트워크 중단 시 전체 파일을 업로드하고 업로드를 재개하려고 시도하는 대신, 애플리케이션에서 파일을 청크로 나누고 일련의 요청을 전송하여 단위를 순서대로 업로드합니다. 이 접근 방식은 거의 필요하지 않으며, 성능에 영향을 미치는 추가 요청이 필요하므로 실제로 권장되지 않습니다. 하지만 매우 불안정한 네트워크에 진행 상태 표시기를 표시하려는 경우에는 유용할 수도 있습니다.

파일을 단위별로 업로드하는 방법은 이 가이드의 앞부분에서 설명한 4단계 절차와 거의 동일합니다. 하지만 파일이 분할되어 업로드되면 파일 업로드를 시작하기 위한 요청 (위의 3단계) 및 업로드 재개 요청 (위의 4.3단계) 모두 Content-LengthContent-Range 헤더 값을 다르게 설정합니다.

  • Content-Length 헤더 값은 요청이 전송하는 청크 파일의 크기를 지정합니다. 청크 파일 크기에 적용되는 다음 제한 사항을 참조하세요.

    • 단위 크기는 256KB의 배수여야 합니다. 전체 파일 크기는 256KB의 배수가 아닐 수도 있기 때문에 마지막 청크 파일에는 이 제한사항이 적용되지 않습니다. 청크 파일이 클수록 더 효율적입니다.

    • 청크 파일 크기는 업로드 순서의 각 요청에 대해 동일해야 하며, 마지막 청크 파일의 크기를 지정하는 마지막 요청은 예외입니다.

  • Content-Range 헤더는 요청이 업로드하는 파일의 바이트를 지정합니다. 이 값을 설정할 때 4.3단계의 Content-Range 헤더 설정에 관한 안내를 확인하세요.

    예를 들어 값이 bytes 0-524287/2000000인 경우 요청이 2, 000,000바이트인 파일에서 첫 524,288바이트 (256 x 2,048)를 전송한다는 의미입니다.

아래 예는 2,000,000바이트 파일을 분할하여 업로드하는 일련의 요청 중 첫 번째 요청의 형식을 보여줍니다.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 524888
Content-Type: video/*
Content-Range: bytes 0-524287/2000000

{bytes 0-524287}

최종 요청 이외의 요청이 성공하면 API 서버에서 308(Resume Incomplete) 응답을 보냅니다. 응답 형식은 위의 4.2단계: API 응답 처리에 설명된 것과 같습니다.

API 응답의 Range 헤더에 반환된 범위 중 큰 값을 사용하여 다음 단위의 시작 위치를 결정합니다. 전체 파일이 업로드될 때까지 4.3단계: 업로드 재개에 설명된 대로 PUT 요청을 계속 보내 다음 파일 청크를 업로드합니다.

전체 파일이 업로드되면 서버는 201 HTTP 응답 코드 (Created)로 응답하고 새로 만든 동영상 리소스의 요청된 부분을 반환합니다.

요청이 중단되거나 애플리케이션이 5xx 응답 코드를 받으면 4단계에 설명된 절차에 따라 업로드를 완료합니다. 파일의 나머지 부분을 업로드하려고 시도하는 대신 업로드를 재개하는 지점부터 단위를 계속 업로드하세요. 업로드 상태를 확인하여 파일 업로드를 재개할 위치를 결정해야 합니다. 서버가 이전 요청에서 전송한 바이트를 모두 받았거나 전혀 받지 않았다고 가정하지 마세요.

참고: 또한 업로드된 청크 파일 간의 활성 업로드 상태를 요청할 수도 있습니다. (업로드 항목은 상태를 검색할 수 있기 전에는 중단되지 않습니다.)