MyShorts에서 만든 첫 영상을 YouTube에 올리는 기능을 붙이기로 했다. YPUB 패키지로 장면과 대사, 제목까지 정해 두고, Python 프로그램에서 Typecast 음성과 MP4를 생성하는 흐름은 이미 갖춰져 있었다. 이제 완성된 영상을 업로드하기만 하면 되는 단계였다.
내가 기대한 화면은 단순했다. 패키지와 제작 기록에 저장된 게시 정보를 기본값으로 불러오고, 수정할 것만 고친 뒤 업로드 버튼을 누르는 화면. 이미 한 번 결정한 내용을 다시 입력하게 만들 이유는 없었다. 그런데 첫 업로드 확인창을 열었을 때, 정작 자동화하려던 일이 사용자에게 돌아와 있었다.
업로드 기능이 아니라 입력 양식
영상 제목과 소개는 어느 정도 들어가 있었지만, 재생목록은 기본적으로 선택되지 않았고 아동 대상 여부와 합성·변경 콘텐츠 공개 여부도 직접 지정해야 했다. Typecast 음성에 대해서는 이용 조건을 확인했다는 체크박스까지 붙어 있었다. 블로그 URL이 없으면 없다는 사실을 따로 확인해야 했다. 더 이상했던 것은 최종 설명란이었다. 프로그램이 Typecast 출처와 BGM 정보 등을 모아 완성된 YouTube 설명을 보여 주면서, 그 전체 문구는 직접 수정할 수 없게 만들어 놓았다.
내가 바꾸고 싶은 설명은 못 바꾸는데, 이미 알고 있는 정보는 또 선택하라고 한다. 여기서 같은 질문을 여러 번 하게 됐다. 내가 YPUB를 만들 때 정한 제목과 카테고리, 실제 영상에 사용한 출연진과 BGM 정보는 어디로 간 걸까? 프로그램이 그 정보를 읽을 수 있는데 왜 사람이 다시 알려 줘야 할까?
문제의 시작은 Codex 이전
이번 개발은 내가 ChatGPT와 요구사항을 정리하고, 그 내용을 프롬프트로 만들어 Codex에 구현을 요청하는 방식이었다. 돌이켜보니 문제가 시작된 지점은 Codex가 아니라 ChatGPT가 작성한 작업 프롬프트의 스코프였다.
업로드에는 다양한 예외가 있다. 잘못된 재생목록에 게시해서는 안 되고, 필수 출처를 누락해서도 안 된다. 아동 대상이나 합성·변경 콘텐츠 공개 여부도 확인해야 한다. 이런 조건 자체는 필요하다. 그런데 프롬프트는 예외를 안전하게 처리하는 조건에 집중한 나머지, 가장 중요한 원칙을 분명하게 고정하지 못했다. 정상적인 경우에는 기존 데이터를 재사용하고, 정말 판단이 필요한 예외에만 사용자가 개입한다는 원칙이었다.
그 결과 Codex는 확인 항목과 체크박스를 충실히 만들어 냈다. 프롬프트만 보면 틀린 구현이라고 하기도 어려웠다. 내가 만들고 싶었던 사용 경험이 요구사항에서 빠져 있었으니까. 중간에는 로컬 AI협업 폴더와 YouTube AI 협업 재생목록을 서로 대체할 수 있는 것처럼 설명하는 일도 있었다. 두 가지는 애초에 목적이 다르다. 로컬 폴더는 제작물을 보관하는 카테고리이고, 재생목록은 영상을 업로드한 뒤 YouTube에서 분류하는 대상이다. 둘 다 필요하지만, 사용자가 양쪽을 매번 직접 연결해 줄 필요는 없었다.
이미 존재하는 데이터의 역할
요구사항을 다시 정리하면서 데이터의 출처를 분명하게 나눴다. YPUB의 JSON에는 승인된 영상 제목과 게시용 정보가 있고, manifest에는 이 영상이 속한 시리즈 정보가 있다. 실제 음성 출연진이나 BGM 사용 사실은 MP4 제작 보고서에서 확인하는 것이 맞다. 재생목록 ID는 패키지에 억지로 저장할 값이 아니라, 연결된 YouTube 채널에서 조회해 매칭해야 한다.
예를 들어 로컬 시리즈가 AI협업이고 현재 채널에 AI 협업이라는 재생목록이 하나 있다면, 공백 차이를 제외한 이름을 비교해 자동으로 선택할 수 있다. 실제로 연결된 채널에서 그 동작을 확인했다. 같은 이름의 후보가 여럿이거나 저장된 ID가 유효하지 않을 때만 사용자의 선택이 필요하다. Typecast 역시 제작 보고서에 출연진과 출처 정보를 가지고 있다면, 매번 이용 조건을 확인했다는 체크박스를 누르게 할 이유는 없다. 반복 체크박스는 제거하되, 영상 설명에 필요한 출연진과 출처 문구는 검증하도록 했다.
아동 대상과 합성·변경 콘텐츠 공개 설정에는 별도의 주의가 필요했다. 이것까지 JSON을 읽었다는 이유로 모든 영상에서 자동 판정할 수 있는 것은 아니다. 현재 EP01의 성격에 맞춰 기본 선택을 제안하되, 사용자가 실제 콘텐츠를 확인하고 변경할 수 있도록 했다. 특히 BGM의 저작자 표시 필요 여부와 AI 생성 음악 여부는 서로 다른 정보이므로 하나로 단정할 수 없다.
내가 요구한 것은 아무 확인도 하지 않는 프로그램이 아니라, 확인과 재입력을 구분하는 프로그램이었다.
최종본은 직접 선택하고, 설명은 직접 고치고
이 과정에서 모든 버튼을 없애려던 것은 아니다. 여러 버전의 MP4가 있다면 그중 무엇을 올릴지는 내가 직접 결정해야 한다. 그래서 최종본 확정 기능은 그대로 유지했다. 반면 최종본을 선택한 이후에는 제목, 카테고리, 출연진, BGM과 같은 기초 정보를 다시 설정할 이유가 없다. 특히 최종 설명란은 자동 생성만 해서는 부족했다. 내가 실제로 올릴 문장을 읽고 수정할 수 있어야 했다.
수정 후에는 최종 설명란을 직접 편집할 수 있게 됐다. 수정한 문구는 초안에 저장되어 창을 다시 열거나 정보를 재확인해도 유지되고, 실제 YouTube API에 전송하는 snippet.description과도 일치하도록 검증했다. 필수 Typecast·BGM 출처를 삭제하면 업로드는 차단된다.
자동 작성과 사용자의 최종 편집이 충돌하지 않게 한 것이다.


실제로 재생해 보니 보인 문제
업로드 화면만 고친다고 끝나는 일은 아니었다. 실제로 제작한 MP4는 다른 YouTube 영상에 비해 음량이 작았다. 측정해 보니 약 -28.81 LUFS였고, 원본 Typecast WAV를 다시 합성하는 대신 FFmpeg의 2-pass loudnorm으로 최종 출력 음량을 맞추도록 변경했다. 이 문제도 실제 영상을 만들어 재생하지 않았다면 놓치기 쉬웠다. 다만 이번 작업에서 더 오래 붙잡고 있었던 문제는 인코딩 기술보다 이미 알고 있는 정보를 다시 입력시키는 업로드 화면이었다.
첫 번째 실제 업로드
2026년 10월 24일, 수정한 MyShorts에서 EP01을 업로드했다. 확인창에는 AI 협업 재생목록이 선택되어 있었고, 아동 대상은 아동용이 아님, 합성·변경 콘텐츠 공개는 해당하지 않음으로 표시됐다. 최종 설명도 직접 읽고 수정할 수 있었다. YouTube 업로드 시작을 누른 뒤 진행률이 100%에 도달했고, 프로그램은 업로드 성공과 Video ID, 재생목록 등록 완료를 표시했다. 처음 전송한 영상은 비공개 상태였다.
YouTube Studio에서도 실제 영상과 제목, 설명란이 등록된 모습을 확인할 수 있었다. 별도로 넣은 Typecast 출처 문구도 그대로 반영돼 있었다. 이후 Studio에서 게시 정보와 썸네일을 검토했다.

처음에는 영상 제작에 이어 업로드 API만 연결하면 되는 일이라고 생각했다. 막상 사용해 보니 중요한 것은 API 호출에 성공하는 것만이 아니었다. 내가 이미 결정해서 패키지에 기록해 둔 내용을, 게시할 때 또 결정하게 만들지 않는 것이다. MyShorts 첫 발행 EP01 - AI 협업의 시작, ChatGPT를 만나다
이번에 가장 많이 되돌린 것은 코드보다 요구사항이었다. 자동화의 범위를 제대로 정의하지 않으면, 프로그램은 알아서 일하는 대신 사용자에게 확인받을 항목만 계속 늘려 놓는다. 내가 원했던 MyShorts의 업로드 기능은 결국 그 반대였다.
