재개 가능한 업로드

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 헤더의 두 번째 숫자보다 1이 더 큽니다. 이전 예에서 Range 헤더 값은 0-999999이므로 후속 재개된 업로드의 첫 번째 바이트는 1000000입니다.

    • LAST_BYTE: 업로드하는 바이너리 파일의 마지막 바이트의 0부터 시작하는 숫자 색인입니다. 일반적으로 파일의 마지막 바이트입니다. 예를 들어 파일 크기가 3000000바이트인 경우 파일의 마지막 바이트는 2999999입니다.

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

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

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

    따라서 Range 헤더의 마지막 바이트가 999999이면 업로드를 재개하기 위한 요청의 첫 번째 바이트는 바이트 1000000이어야 합니다. 두 숫자 모두 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 2048)를 전송하고 있음을 나타냅니다.

아래 예는 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단계에 설명된 절차에 따라 업로드를 완료합니다. 하지만 파일의 나머지 부분을 업로드하려고 하지 말고 업로드를 재개하는 지점부터 단위를 계속 업로드합니다. 업로드 상태를 확인하여 파일 업로드를 재개할 위치를 확인하세요. 서버가 이전 요청에서 전송한 바이트를 모두 받았거나 전혀 받지 않았다고 가정하지 마세요.

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