핵심 요약
- 클로드코드 세션에게 유튜브 업로드 도구를 맡겨 2026년 8월 27일 첫 업로드 뒤로 음악 채널의 업로드와 예약 공개를 스크립트로 돌리고 있습니다. 업로드, 세 언어 메타데이터, 썸네일, 상태 조회를 나눈 파이썬 스크립트이고 표준 라이브러리만 씁니다.
- 코드보다 계정에서 더 많이 막혔습니다. 동의 화면에서 채널을 잘못 골라 다른 채널로 올라갔고, 테스트 상태 앱의 갱신 토큰은 7일 뒤 만료됐습니다. 앱을 프로덕션으로 게시하려면 홈페이지와 개인정보처리방침 주소가 필요했는데 콘솔 배너는 그 사실을 알려 주지 않았습니다.
- 예약 공개는 비공개 영상에만 걸립니다. 공식 문서는
status.publishAt을 privacyStatus 가 private 일 때만 받는다고 적고 있습니다(출처: Videos resource, 2026-09-23 확인). 그래서 도구의 기본값을 비공개로 두었습니다. - 2026년 9월 기준 업로드 쿼터는 예전 글과 다릅니다. videos.insert 는 전용 버킷에서 호출당 1유닛, 하루 100회가 기본입니다. 메타 수정은 50유닛, 썸네일은 약 50유닛이고 나머지 메서드 합산 한도는 하루 10,000유닛입니다(출처: Videos: insert, 2026-09-23 확인).
- 전송이 끊겼다고 실패한 것이 아니었습니다. 실패로 보고 다시 올렸다가 같은 영상이 두 개가 됐고, 그 뒤로 끊기면 서버에 받은 지점을 먼저 묻도록 고쳤습니다.
문제 정의: 클로드코드에 맡길 일과 사람이 할 일
클로드코드로 유튜브 업로드를 자동화하려는 분이 먼저 알아야 할 것은 코드보다 계정과 권한 쪽이 오래 걸린다는 점입니다. 음악 채널을 여러 개 운영하면 반복 작업은 거의 업로드 쪽에 몰립니다. 영상 파일을 올리고, 영어·한국어·일본어 제목과 설명을 넣고, 썸네일을 바꾸고, 공개 시각을 거는 일입니다. 스튜디오 화면에서 손으로 하면 한 편에 여러 화면을 오가야 하고, 예약이 쌓이면 무엇이 언제 나가는지 놓칩니다.
이 구간을 클로드코드 세션에게 맡겼습니다. 곡 생성은 사람 손 구간으로 남겼습니다. 그 이유는 수노 저작권과 상업적 이용을 확인한 글에 적었습니다. 이 글은 다운로드한 곡이 영상으로 조립된 뒤, 채널에 예약 공개로 걸리기까지의 기록입니다.
역할은 이렇게 나뉘었습니다. 세션은 스크립트 작성, 업로드, 메타데이터와 썸네일 적용, 예약, 업로드 뒤 되읽기 대조를 맡았습니다. 사람은 동의 화면에서 계정을 고르고 허용하는 클릭, 15분 넘는 영상을 위한 계정 인증, 스튜디오에서만 되는 확인과 삭제를 맡았습니다. 모든 날짜와 사건은 작업 저장소의 업데이트 기록에서 옮겼습니다.
클로드코드 사용법: 규칙은 문서에, 판단은 되읽기로
클로드코드 사용법에서 가장 효과가 있었던 것은 세션마다 같은 규칙을 읽게 한 것입니다. 저장소의 CLAUDE.md 에 지켜야 할 선을 적었고, 세션은 작업을 시작할 때 이 파일을 읽습니다. 업로드 도구에 들어간 규칙은 세 가지였습니다.
- 표준 라이브러리만 씁니다. 구글 클라이언트 라이브러리 없이 OAuth 설치형 흐름과 재개 가능 업로드를 직접 구현했습니다. 의존성이 없어서 다른 맥이나 무인 러너로 옮겨도 그대로 돕니다.
- 기본은 비공개입니다. 공개하려면 옵션을 명시해야 합니다. 저작권 소유권 주장 확인 전에 실수로 공개되는 것을 막으려는 선이었고, 예약 공개와도 맞아떨어졌습니다.
- 세 언어는 현지화 필드로 넣습니다. 설명란에 세 언어를 이어 붙이지 않습니다. 이어 붙이면 제목은 영어 그대로이고 설명만 세 배로 길어집니다.
두 번째 습관은 세션의 "완료" 보고를 믿지 않고 API 로 되읽게 한 것입니다. 업로드가 끝나면 채널, 공개 상태, 예약 시각, 현지화 언어를 다시 조회해 의도와 대조합니다. 뒤에 나오는 사고 대부분이 이 되읽기에서 드러났습니다.
스크립트 네 개가 영상 한 편을 처리하는 순서

| 단계 | 하는 일 | 유튜브 API 호출 | 공식 쿼터 비용 |
|---|---|---|---|
| 1. 업로드 | 비공개로 올리고 예약 시각을 같이 보냄 | videos.insert (재개 가능 업로드) | 업로드 버킷 1유닛 |
| 2. 메타 | 영어 기본, 한국어·일본어 현지화, 태그 | videos.update | 50유닛 |
| 3. 썸네일 | 1280x720 이미지 적용 | thumbnails.set | 약 50유닛 |
| 4. 상태 | 처리 상태, 거부 사유, 예약 확인 | videos.list | 1유닛 |
쿼터 값은 2026년 9월 23일에 공식 문서 원문으로 확인했습니다(출처: YouTube Data API Overview, Videos: update, Thumbnails: set). 계산하면 영상 한 편이 일반 버킷에서 쓰는 양은 메타 50, 썸네일 약 50, 조회 몇 유닛으로 약 100유닛 남짓입니다. 하루 10,000유닛 한도와 업로드 100회 한도를 생각하면 개인 채널 몇 개로는 쿼터에 닿을 일이 없었습니다.
예전 글에서 업로드 한 번에 1,600유닛이 든다는 설명을 보셨다면 지금은 맞지 않습니다. 변경 이력에 따르면 2025년 12월 4일에 약 1600유닛에서 약 100유닛으로 바뀌었고, 2026년 6월 1일부터 videos.insert 와 search.list 가 각자의 쿼터 버킷으로 분리됐습니다(출처: Revision History, 2026-09-23 확인).
예약 공개는 업로드 순간에 겁니다
처음 만든 업로드 스크립트에는 예약 기능이 없었습니다. 비공개로 올려 두고 사람이 그날 공개하는 구조라 무인 운영에 맞지 않았고, 2026년 9월 6일에 --publish-at 옵션을 붙였습니다. 시각은 한국 시각으로 받고 UTC 로 바꿔 보냅니다.
KST = timezone(timedelta(hours=9))
when = datetime.strptime(args.publish_at, "%Y-%m-%dT%H:%M").replace(tzinfo=KST)
meta["status"]["privacyStatus"] = "private"
meta["status"]["publishAt"] = when.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
작업하는 맥의 시간대가 한국과 달라서 시간대를 상수로 고정했습니다. 예약 시각이 이미 지났으면 올리기 전에 멈춥니다.
메타 스크립트는 공개 범위를 건드리지 않습니다
메타 스크립트는 공개 범위 옵션을 주지 않으면 status 를 아예 보내지 않습니다. 2026년 9월 8일에 여러 영상의 설명란 링크를 한꺼번에 고친 뒤 되읽어 보니 예약 공개 시각 16건이 전부 그대로 남아 있었습니다. 공식 문서도 snippet 을 수정할 때 요청에 빠진 기존 값은 지워진다고 적고 있습니다(출처: Videos: update). 고칠 부분만 보내는 설계가 필요한 이유입니다.
실무 관점: 실제로 막힌 것 다섯 가지
동의 화면에서 채널을 잘못 골랐습니다
2026년 8월 27일 첫 업로드가 의도와 다른 브랜드 채널로 올라갔습니다. 구글 계정 하나 안에 브랜드 채널이 여럿 있으면 동의 화면에서 채널을 고르는 단계가 나오고, 거기서 고른 채널에 토큰이 묶입니다. 잘못 묶인 토큰으로는 원래 채널의 영상을 조회하면 403 이 납니다.
고친 방법은 세 가지입니다. 채널마다 프로필 이름을 따로 주고 토큰 파일을 나눴습니다. 발급 직후 channels.list mine=true 로 채널을 되읽어, 기대한 채널이 아니면 실패로 끝내고 토큰 파일을 지운 뒤 다시 받으라고 안내하게 했습니다. 동의 화면을 여는 방식도 바꿨습니다. 이 맥의 기본 브라우저는 다른 구글 계정의 프로필이라, 나중에 만든 토큰 발급 도구는 브라우저를 자동으로 열지 않고 주소만 찍습니다. 사람이 맞는 프로필의 크롬 창에 그 주소를 붙여 넣습니다.
테스트 상태 앱의 토큰은 7일이면 끝납니다
구글 문서는 외부 사용자 유형이면서 게시 상태가 "Testing" 인 프로젝트의 갱신 토큰이 7일 뒤 만료된다고 적고 있습니다(출처: Using OAuth 2.0, 2026-09-23 확인). 이대로면 예약 업로드가 매주 죽고 매주 사람이 다시 클릭해야 합니다. 2026년 9월 2일에 앱을 프로덕션으로 게시하고 토큰을 모두 다시 받았습니다. 게시 전에 받은 토큰은 게시 뒤에도 7일 만료를 그대로 따르므로 재발급이 필요했습니다.
게시 버튼이 한동안 회색이었습니다. 필수 칸 세 개(앱 이름, 지원 이메일, 개발자 연락처)와 범위를 채워도 "OAuth configuration is incomplete" 배너가 그대로였습니다. 홈페이지 주소와 개인정보처리방침 주소를 넣자 승인 도메인이 필수 칸이 됐고, 도메인까지 넣고 저장하니 배너가 사라지고 게시가 됐습니다. 구글의 앱 대상 도움말은 이 칸들을 게시 요건으로 적지 않습니다(출처: Manage App Audience, 2026-09-23 확인). 저희 콘솔에서는 그랬다는 기록입니다.
OAuth 클라이언트 유형과 콜백 버그
처음에 OAuth 클라이언트를 웹 앱 유형으로 만들었다가 되돌렸습니다. 웹 유형은 리다이렉트 주소를 콘솔에 미리 등록해야 해서, 임의 포트로 로컬 서버를 여는 스크립트와 맞지 않습니다. 데스크톱 앱 유형이어야 합니다. 지금은 스크립트가 웹 유형 파일을 받으면 올리기 전에 멈춥니다.
로컬 콜백 서버에서는 버그가 두 번 났습니다. 8월 27일에 브라우저가 같이 보내는 favicon 요청이 한 번만 받는 서버 자리를 차지했습니다. 그것을 고친 같은 날, 이번에는 이전 시도의 브라우저 탭이 옛 state 값을 들고 들어왔습니다. 둘 다 state 불일치로 튕겼고, 지금은 state 가 맞는 콜백만 받고 나머지는 무시하며 기다립니다.
끊긴 업로드를 실패로 보고 다시 올렸습니다
9월 6일 2GB 넘는 영상 파일이 전송 도중 시간 초과로 죽었습니다. 다음 날 같은 영상이 채널에 두 개 있는 것이 스튜디오에서 발견됐습니다. 파일은 서버에 다 올라갔는데 응답만 못 받은 것이었고, 영상 ID 를 모르니 존재를 모른 채 다시 올린 것입니다. 먼저 올라간 쪽은 12시간 넘게 처리 중 상태로 남아 있었습니다.
유튜브의 재개 가능 업로드는 끊긴 세션에 빈 PUT 과 Content-Range: bytes */<전체 크기> 를 보내 상태를 물을 수 있습니다. 308 응답의 Range 헤더가 서버가 받은 바이트 범위를 알려 주고, 이미 끝났으면 완료 응답이 옵니다(출처: Resumable Uploads, 2026-09-23 확인). 지금 스크립트는 끊기면 5초 쉬고 이 요청을 보내 받은 지점부터 이어 보내며, 최대 8번까지 시도합니다. 완료 응답이 오면 그 영상 ID 를 씁니다.
API 만으로는 안 되는 것들
이것들은 스크립트로 해결하지 못했습니다.
- 15분 제한: 9월 19일 1시간 8분짜리 영상의 첫 업로드가 "영상이 너무 김" 으로 처리 중단됐습니다. 유튜브 도움말은 기본 업로드 길이가 15분까지이고 인증된 계정만 그 이상 올릴 수 있다고 적고 있습니다(출처: YouTube Help, 2026-09-23 확인). 전화 인증 뒤 다시 올려 통과했고, 실패한 영상은 API 로 조회도 삭제도 되지 않아 스튜디오에서 지웠습니다.
- 태그 검증 차이: 9월 6일 videos.insert 가 invalidTags 로 거부한 태그 목록을 videos.update 는 그대로 받았습니다. 그래서 업로드는 태그 없이 하고 태그는 메타 단계에서 넣습니다. 태그는 처리 중에는 되읽기에 0개로 나오다가 처리가 끝난 뒤 보였습니다.
- 파일 교체: 올린 영상의 파일만 바꾸는 기능이 없어서, 새 파일을 비공개로 올리고 메타와 썸네일을 옮긴 뒤 필드 단위로 대조하고 옛 영상을 지웁니다.
- 소유권 주장 확인: 업로드 상태 API 는 처리 실패와 거부 사유는 보여 주지만, 저작권 소유권 주장은 스튜디오의 해당 탭에서 사람이 봅니다.
무인 러너가 실패하고도 종료 코드 0 을 남긴 일
업로드 도구와 같은 방식으로 짠 다른 무인 러너에서 교훈 하나를 얻었습니다. 쇼츠를 다른 플랫폼에 올리는 러너로, 맥의 launchd 가 셸 스크립트를 띄우고 그 안에서 헤드리스 클로드코드 세션이 발행을 진행합니다. 2026년 9월 22일 실행에서 세션은 발행에 필요한 값을 받지 못해 발행이 실패했다고 보고했습니다. 그런데 로그에 찍힌 세션의 종료 코드는 0 이었습니다.
종료 코드는 세션이 정상적으로 끝났다는 뜻이지 일이 끝났다는 뜻이 아닙니다. 다행히 러너는 발행 뒤 대기열 상태를 따로 찍고 있었고, 그 편의 틱톡 칸이 "없음" 으로 남아 있어서 실패를 알 수 있었습니다. 무인으로 돌리는 업로드라면 성공 판정은 종료 코드가 아니라 결과물 상태로 해야 합니다. 업로드 도구에서 되읽기를 마지막 단계로 둔 것도 같은 이유입니다.
자주 묻는 질문
API 로 올린 영상이 비공개로 묶이지는 않나요
공식 문서에는 2020년 7월 28일 이후 만든 미검증 API 프로젝트가 videos.insert 로 올린 영상은 비공개로 제한되고, 풀려면 감사를 받아야 한다는 문장이 있습니다(출처: Videos: insert, 2026-09-23 확인). 저희는 감사를 신청한 기록이 없는데 예약 공개분이 공개로 넘어간 것을 확인했습니다. 이 차이의 이유는 확인하지 못했으니, 처음 쓰실 때는 시험 영상 하나로 먼저 보시기를 권합니다.
유튜브 API 키만으로 업로드할 수 있나요
안 됩니다. 공개 데이터 조회는 API 키로 되지만 업로드와 수정은 채널 소유자의 OAuth 동의가 필요합니다. 한 번 동의하면 갱신 토큰으로 계속 돌고, 앱이 테스트 상태면 그 토큰이 7일 뒤 만료됩니다.
결론: 따라 만들 때 확인할 것
- OAuth 클라이언트는 데스크톱 앱 유형으로 만드십시오. 범위는 업로드만이면 youtube.upload 로 되지만, 메타와 현지화를 고치는 videos.update 는 이 범위로 부를 수 없어 youtube.force-ssl 을 더했습니다. 범위가 모자라면 토큰을 지우고 다시 동의받아야 합니다.
- 자동화할 계획이면 앱을 처음부터 프로덕션으로 게시하십시오. 테스트 상태 토큰은 7일이면 끝납니다. 게시 버튼이 회색이면 홈페이지, 개인정보처리방침, 승인 도메인 칸을 먼저 채워 보십시오.
- 토큰을 받은 직후 채널 이름을 되읽으십시오. 브랜드 채널이 여럿인 계정은 동의 화면에서 채널을 잘못 고르기 쉽습니다.
- 기본은 비공개, 공개는 publishAt 으로 거십시오. 예약은 비공개 영상에만 걸립니다.
- 끊긴 업로드는 다시 올리기 전에 세션 상태부터 물으십시오. 응답을 못 받았어도 파일은 이미 올라가 있을 수 있습니다.
- 15분 넘는 영상을 올릴 채널은 계정 인증부터 하십시오.
- 무인 실행의 성공은 종료 코드가 아니라 되읽은 상태로 판정하십시오.
이 글의 쿼터, 예약, 토큰 만료 값은 모두 2026년 9월 23일에 구글 공식 문서를 다시 열어 확인했습니다. 유튜브는 쿼터 체계를 2025년과 2026년에 연달아 바꿨으므로, 만들기 전에 원문을 한 번 더 확인하시기를 권합니다.
관련 글
- AI 코딩 도구 요금제 비교: 사용량을 숫자로 적어둔 곳은 한 곳뿐입니다: 이 도구를 짠 클로드코드를 포함해 코딩 도구 요금제의 사용량 표기를 비교한 글입니다.
출처
- YouTube Data API Overview (Quota usage) (Google for Developers, 확인 2026-09-23)
- Videos: insert (Google for Developers, 확인 2026-09-23)
- Videos: update (Google for Developers, 확인 2026-09-23)
- Videos (resource representation) (Google for Developers, 확인 2026-09-23)
- Thumbnails: set (Google for Developers, 확인 2026-09-23)
- YouTube Data API Revision History (Google for Developers, 확인 2026-09-23)
- Resumable Uploads (Google for Developers, 확인 2026-09-23)
- Using OAuth 2.0 to Access Google APIs (Google for Developers, 확인 2026-09-23)
- Manage App Audience (Google Cloud Platform Console Help, 확인 2026-09-23)
- Upload videos longer than 15 minutes (YouTube Help, 확인 2026-09-23)