처음으로

메타 자동화

인스타 릴스를 월·수·금 자동으로 올리는 구조

메타 그래프 API와 GitHub Actions로 정해진 요일에 릴스를 올리는 구조예요. 한 안경원이 10주 남짓 동안 32편을 이렇게 올렸어요.

1단계부터 보기 · 모두 14단계
한 줄 답

영상을 공개 주소에 올려 두고, GitHub Actions가 월·수·금 아침마다 그래프 API로 컨테이너를 만들어 발행하게 하면 사람이 앱을 열지 않아도 릴스가 올라가요.

준비물

  • 도구인스타그램 프로페셔널 계정, 메타 개발자 앱, 영상을 공개 주소로 올릴 저장소(이 사례는 구글 클라우드 스토리지), GitHub 저장소
  • 돈API는 무료예요. 저장소 요금이 조금 들고, GitHub Actions는 비공개 저장소라면 무료 플랜에서 월 2,000분까지 무료예요.
  • 계정페이스북 페이지와 연결된 인스타그램 프로페셔널 계정
  • 걸리는 시간처음 연결에 하루쯤 걸려요. 그 뒤로는 영상만 채우면 돼요.
  • 난이도중급. 토큰과 크론 문법을 다뤄요.

차례

한 화면에 한 단계씩 넘기며 보세요.

  1. 1시작은 이랬어요
  2. 2알아 두기전체 구조
  3. 3연결하는 순서 1/6인스타그램 계정을 프로페셔널 계정으로 바꾸고 페이스북 페이지와 연결해요
  4. 4연결하는 순서 2/6메타 개발자 사이트에서 앱을 만들고 instagram_basic, instagram_content_publish, pages_read_engagement 권한을 받아요
  5. 5연결하는 순서 3/6토큰은 만료가 없는 것을 써요
  6. 6연결하는 순서 4/6토큰은 GitHub 저장소의 Secrets에 넣어요
  7. 7연결하는 순서 5/6영상은 공개 주소로 올려요
  8. 8연결하는 순서 6/6영상 규격을 맞춰요
  9. 9알아 두기올리는 명령
  10. 10알아 두기요일 정하기
  11. 11알아 두기다음 영상 고르는 법
  12. 12막혔던 곳설치 단계가 4시간 동안 멈춰 있었어요
  13. 13막혔던 곳토큰이 끊긴 줄 모르고 영상까지 다 만들었어요
  14. 14막혔던 곳발행을 미뤄야 할 때 주석에 기대지 마세요
한 쪽에 모두 보기

가게 인스타를 매주 몇 번씩 올리다 보면 바쁜 날 한 번 빠지고, 그다음 주에 또 빠져요. 한 안경원은 2026년 7월 27일부터 릴스를 자동으로 올리고 있어요. 10월 9일까지 API로 올라간 릴스가 32편이에요. 7월 27일부터 8월 15일까지 20일 동안 16편을 거의 매일 올렸고, 2주 남짓 쉰 뒤 9월 2일부터는 월·수·금으로 올리고 있어요.

7월 27일부터 10월 9일까지 실제 발행일로 센 주마다의 릴스 수. 처음 3주 가까이 거의 매일, 9월부터는 주 3편이에요.
7월 27일부터 10월 9일까지 실제 발행일로 센 주마다의 릴스 수. 처음 3주 가까이 거의 매일, 9월부터는 주 3편이에요.

자동으로 하는 일은 «올리기»까지예요. 영상과 캡션은 미리 만들어 날짜별 폴더에 넣어 둬요.

전체 구조

사람이 날짜 폴더에 영상을 넣으면 GitHub Actions와 스크립트가 공개 주소 만들기, 그래프 API 호출, 기록 커밋까지 이어서 하는 흐름.
사람이 날짜 폴더에 영상을 넣으면 GitHub Actions와 스크립트가 공개 주소 만들기, 그래프 API 호출, 기록 커밋까지 이어서 하는 흐름.

연결하는 순서

  1. 인스타그램 계정을 프로페셔널 계정으로 바꾸고 페이스북 페이지와 연결해요. 개인 계정은 API로 게시할 수 없어요.
  2. 메타 개발자 사이트에서 앱을 만들고 instagram_basic, instagram_content_publish, pages_read_engagement 권한을 받아요.
  3. 토큰은 만료가 없는 것을 써요. 그래프 API 탐색기에서 바로 복사한 토큰은 몇 시간 만에 끝나요. 단기 토큰을 장기 사용자 토큰(약 60일)으로 바꾸고, 그 토큰으로 페이지 토큰을 뽑으면 만료일이 없어요.
  4. 토큰은 GitHub 저장소의 Secrets에 넣어요. 코드나 문서에 그대로 적지 마세요.
  5. 영상은 공개 주소로 올려요. 그래프 API는 내 컴퓨터의 파일을 받지 않고, 메타 서버가 주소로 직접 내려받아 가요.
  6. 영상 규격을 맞춰요. MP4나 MOV, H.264나 HEVC 코덱, 길이 3초~15분, 300MB 이하예요. 화면 비율은 9:16을 권해요.

올리는 명령

API 호출은 세 번이면 끝나요. 아래는 curl로 쓴 모양이고, 실제로는 파이썬 스크립트가 같은 일을 해요.

명령 창

# 1) 컨테이너 만들기
curl -X POST "https://graph.facebook.com/<버전>/<IG_ID>/media" \
  -d media_type=REELS -d video_url="https://<공개주소>/reel.mp4" \
  -d caption="<캡션>" -d access_token="$IG_TOKEN"
# 2) 처리 상태 확인. status_code 가 FINISHED 가 될 때까지 몇 초 간격으로 다시 묻는다
curl -G "https://graph.facebook.com/<버전>/<컨테이너_ID>" \
  -d fields=status_code -d access_token="$IG_TOKEN"
# 3) 발행
curl -X POST "https://graph.facebook.com/<버전>/<IG_ID>/media_publish" \
  -d creation_id="<컨테이너_ID>" -d access_token="$IG_TOKEN"

한 계정이 API로 올릴 수 있는 게시물은 24시간에 100개예요. 지금까지 쓴 양은 content_publishing_limit 주소로 확인해요.

요일 정하기

GitHub Actions의 schedule에 크론 식을 적어요. 시간은 UTC 기준이라 한국 오전 10시는 UTC 01시예요.

설정 파일(YAML)

on:
  schedule:
    - cron: '0 1 * * 1,3,5'   # 한국 시간 월·수·금 오전 10시
  workflow_dispatch:          # 급할 때 손으로도 돌릴 수 있게
jobs:
  publish:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
      - run: python publish.py
        env:
          IG_TOKEN: ${{ secrets.IG_TOKEN }}

GitHub 크론은 정각을 지켜 주지 않아요. 붐비는 시간에는 몇 분에서 몇십 분 늦게 시작해요. 딱 그 시각에 올라가야 하는 게시물이라면 인스타 앱의 예약 기능이 맞아요.

다음 영상 고르는 법

스크립트는 날짜 폴더 가운데 «날짜가 지났는데 아직 올리지 않은 것 중 가장 오래된 것»을 하나 골라요. 한 번 실패해도 다음 실행이 그 몫을 이어받으니 빠지는 날이 생기지 않아요. 올린 것은 기록 파일에 적고 저장소에 다시 커밋해서 같은 영상이 두 번 올라가지 않게 해요.

막혔던 곳

설치 단계가 4시간 동안 멈춰 있었어요

8월 18일, 영상 처리 도구(ffmpeg)를 설치하는 단계가 4시간 넘게 멈췄어요. GitHub Actions의 기본 시간 제한이 6시간이라 그동안 실패 신호가 하나도 없었고, 그날 발행은 통째로 밀렸어요.

성공한 실행 20건을 재 보니 가장 오래 걸린 것이 6.2분이었어요. 그래서 시간 제한을 15분으로 줄였어요. 멈추면 15분 안에 실패로 끝나서 바로 눈에 띄어요. ffmpeg은 GitHub의 우분투 실행 환경에 이미 깔려 있어서, 있으면 설치를 건너뛰게 고쳤어요.

토큰이 끊긴 줄 모르고 영상까지 다 만들었어요

7월 27일, 토큰이 이틀 전에 만료됐는데 아무도 몰랐어요. 영상 처리와 업로드를 다 마친 뒤 발행 단계에서야 실패했어요. 그 뒤로 작업에 들어가기 전에 토큰의 남은 기간을 먼저 확인하고, 7일 아래로 남으면 경고를 띄워요. 만료가 없는 페이지 토큰을 뽑아 주는 기능도 이때 함께 만들었어요.

발행을 미뤄야 할 때 주석에 기대지 마세요

8월 말에 운영자가 «인스타 발행은 9월 1일부터 진행할 거니까 크론 그때부터 돌려»라고 했어요. 처음에는 9월 1일에 사람이 크론 줄의 주석을 지우기로 했다가 잊을 뻔했어요. 그래서 크론은 늘 켜 두고, 스크립트 안에 «이 날짜까지는 올리지 않는다»는 날짜 값을 넣는 방식으로 바꿨어요.

근거

이 글을 만든 방법

  • 바탕운영자가 실제로 돌린 작업의 기록(작업 일지·설정 파일·오류 기록)
  • 쓴 쪽AI(Claude)가 썼어요
  • 독립 검수2026-10-10에 쓴 AI와 다른 AI가 원본과 대조해 통과시켰어요
  • 사실 확인2026-10-10
  • 고친 기록
    • 2026-10-10 «처음 3주는 거의 매일»을 «처음 2주는 매일, 2주 남짓 쉰 뒤 9월부터 월·수·금»으로, 요약의 «석 달»을 «10주»로 고쳤어요. 예약 폴더 이름의 날짜를 실제 발행 기록으로 잘못 본 고침이었어요.
    • 2026-10-10 사후 검수에서 바로 앞의 고침이 틀렸다는 것을 찾았어요. «처음 2주는 매일»은 예약 폴더 이름의 날짜로 센 값이었어요. 실제 발행 기록으로 다시 세어 «7월 27일부터 8월 15일까지 20일 동안 16편을 거의 매일»로, 마감 날짜를 «10월 7일»에서 «10월 9일»로 고치고 그림도 다시 그렸어요.

발행 2026-10-10