개발자 가이드

Python으로 소셜 미디어 게시를 자동화하는 방법

스타트업의 콘텐츠 파이프라인을 구축하든, 클라이언트를 위한 게시를 자동화하든, SaaS 제품에 소셜 게시 기능을 통합하든, Python으로 쉽게 할 수 있습니다. 이 튜토리얼에서는 첫 번째 업로드부터 프로덕션 수준의 자동화 스크립트까지 모든 것을 안내합니다.

소셜 미디어 자동화에 Python을 사용하는 이유

Python은 자동화를 위한 최적의 언어입니다. 가독성이 뛰어나고, 방대한 에코시스템을 가지고 있으며, 스케줄에 따라 실행되는 스크립트에 적합합니다. 그리고 소셜 미디어에 프로그래밍 방식으로 게시할 때, Upload-Post 같은 API를 사용하는 대안은 각 플랫폼의 OAuth 통합을 직접 구축하는 것입니다. TikTok의 Content Posting API, Instagram의 Graph API, YouTube의 Data API 등을 각각 처리해야 하며, 모두 고유한 인증 플로우, 속도 제한, 특이사항이 있습니다.

소셜 미디어 포스팅 API를 사용하면 하나의 API 호출로 10개 플랫폼 전부에 게시됩니다. Python SDK가 이를 더욱 간단하게 만들어 줍니다.

환경 설정

1. SDK 설치

pip install upload-post

2. API 키 받기

app.upload-post.com에서 무료 계정을 만들고 API 키 대시보드에서 API 키를 생성하세요. 환경 변수로 저장하세요:

export UPLOAD_POST_API_KEY="your-api-key-here"

3. 소셜 계정 연결

Upload-Post 대시보드에서 프로필(예: "mybrand")을 만들고 TikTok, Instagram, YouTube 등 게시하려는 계정을 연결하세요. 프로필 이름이 코드에서 참조하는 값입니다.

첫 번째 업로드: 동영상 게시하기

import os
from upload_post import UploadPostClient

client = UploadPostClient(
    api_key=os.environ["UPLOAD_POST_API_KEY"]
)

response = client.upload_video(
    video_path="my-video.mp4",
    title="우리의 새로운 제품을 사용해 보세요",
    user="mybrand",
    platforms=["tiktok", "instagram", "youtube"]
)

if response["success"]:
    for platform, result in response["results"].items():
        if result["success"]:
            print(f"{platform}: {result['url']}")
        else:
            print(f"{platform}: upload failed")
else:
    print("Upload failed:", response)

이것이 작동하는 스크립트입니다. 실행하면 동영상이 3개 플랫폼에 게시됩니다. 이제 더 많은 기능을 추가해 보겠습니다.

사진과 캐러셀 게시하기

response = client.upload_photos(
    photos=["slide-1.jpg", "slide-2.jpg", "slide-3.jpg"],
    title="여름 컬렉션 룩북",
    description="모든 제품은 포르투갈에서 제작되었습니다. 바이오의 링크에서 쇼핑하세요.",
    user="mybrand",
    platforms=["instagram", "tiktok", "linkedin"]
)

print(response)

Instagram에서는 캐러셀 게시물이, TikTok에서는 슬라이드쇼가, 링크드인에서는 다중 이미지 게시물이 생성됩니다. 각 플랫폼이 선호하는 형식을 자동으로 적용합니다.

텍스트 콘텐츠 게시하기

텍스트 전용 게시물 (Twitter 스레드, LinkedIn 업데이트, Reddit 게시물 등)의 경우:

response = client.upload_text(
    title="우리는 API에 대한 대규모 업데이트를 배포했습니다. 변경된 내용은 다음과 같습니다...",
    user="mybrand",
    platforms=["x", "linkedin", "threads", "bluesky"]
)

print(response)

텍스트가 플랫폼의 글자 수 제한을 초과하면 API가 스마트하게 처리합니다. X에서는 280자 초과 시 자동으로 스레드가 됩니다. 스레드에서는 500자에서, Bluesky에서는 300자에서 분할됩니다.

플랫폼별 파라미터 사용하기

title 파라미터가 모든 플랫폼의 기본 캡션을 설정하지만, 각 플랫폼별로 다른 문구를 원하는 경우가 많습니다. 플랫폼별로 커스터마이즈하는 방법은 다음과 같습니다:

import requests
import os

API_KEY = os.environ["UPLOAD_POST_API_KEY"]

with open("product-demo.mp4", "rb") as video:
    response = requests.post(
        "https://api.upload-post.com/api/upload",
        headers={"권한 부여": f"API 키 {API_KEY}"},
        files={"video": video},
        data={
            "user": "mybrand",
            "title": "Check this out",
            # Platform specific titles
            "tiktok_title": "관점: 당신의 제품이 스스로 판매됩니다 #ecommerce #dropshipping",
            "instagram_title": "새로운 출시. 조기 접근을 위한 링크는 바이오에 있습니다.",
            "youtube_title": "제품 데모 | 전체 리뷰",
            "youtube_description": "이 비디오에서는 작동 방식에 대해 정확히 보여드립니다...",
            "linkedin_title": "우리의 최신 제품 출시를 커뮤니티와 공유하게 되어 기쁩니다.",
            # Platform specific settings
            "platform[]": ["tiktok", "instagram", "youtube", "linkedin"],
            "privacy_level": "PUBLIC_TO_EVERYONE",
            "media_type": "REELS",
            "tags[]": ["product", "demo", "review"],
            "privacyStatus": "public",
        }
    )

print(response.json())

이 예제는 SDK 대신 requests 라이브러리를 직접 사용하여 모든 API 파라미터에 접근할 수 있습니다. 플랫폼별 모든 옵션은 전체 API 레퍼런스를 확인하세요.

나중을 위해 게시물 예약하기

from datetime import datetime, timedelta

# Schedule for tomorrow at 9 AM
tomorrow_9am = (datetime.now() + timedelta(days=1)).replace(
    hour=9, minute=0, second=0, microsecond=0
)

response = client.upload_video(
    video_path="tomorrows-content.mp4",
    title="좋은 아침! 피드를 위한 신선한 콘텐츠",
    user="mybrand",
    platforms=["tiktok", "instagram"],
    scheduled_date=tomorrow_9am.isoformat(),
    timezone="미국/뉴욕"
)

print(f"예약됨! 작업 ID: {response['job_id']}")
print(f"발행 예정: {response['scheduled_date']}")

최대 365일 후까지 예약할 수 있습니다. 스케줄링과 대기열 시스템에 대한 자세한 내용은 스케줄링 가이드를 참고하세요.

완전한 자동화 구축: 폴더 감시기

폴더에 새 동영상 파일이 추가되면 자동으로 업로드하는 실용적인 스크립트입니다. 공유 폴더에서 클라이언트 콘텐츠를 받는 에이전시에 적합합니다:

import os
import time
import json
from upload_post import UploadPostClient

client = UploadPostClient(
    api_key=os.environ["UPLOAD_POST_API_KEY"]
)

WATCH_FOLDER = "/path/to/content/inbox"
PROCESSED_FILE = "/path/to/content/processed.json"
CHECK_INTERVAL = 60  # seconds

def load_processed():
    if os.path.exists(PROCESSED_FILE):
        with open(PROCESSED_FILE) as f:
            return set(json.load(f))
    return set()

def save_processed(processed):
    with open(PROCESSED_FILE, "w") as f:
        json.dump(list(processed), f)

def upload_video(filepath):
    filename = os.path.basename(filepath)
    title = filename.rsplit(".", 1)[0].replace("-", " ").replace("_", " ")

    response = client.upload_video(
        video_path=filepath,
        title=title,
        user="mybrand",
        platforms=["tiktok", "instagram", "youtube"],
        add_to_queue=True,
        async_upload=True
    )
    return response

print(f"Watching {WATCH_FOLDER} for new videos...")

processed = load_processed()

while True:
    for filename in os.listdir(WATCH_FOLDER):
        if filename in processed:
            continue
        if not filename.lower().endswith((".mp4", ".mov")):
            continue

        filepath = os.path.join(WATCH_FOLDER, filename)
        print(f"New file detected: {filename}")

        try:
            result = upload_video(filepath)
            print(f"  Queued successfully: {result.get('job_id', 'done')}")
            processed.add(filename)
            save_processed(processed)
        except Exception as e:
            print(f"  Error: {e}")

    time.sleep(CHECK_INTERVAL)

이 스크립트를 백그라운드(또는 systemd 서비스)에서 실행하면, 누군가 폴더에 동영상을 넣을 때마다 연결된 모든 플랫폼에 자동으로 게시됩니다. 더 견고한 솔루션이 필요하다면 관리형 워크플로우로 n8n 또는 Make.com 사용을 고려해 보세요.

API 직접 사용하기 (SDK 없이)

SDK를 사용하지 않거나 더 세밀한 제어가 필요한 경우 requests 라이브러리를 직접 사용할 수 있습니다. SDK 업로드와 동일한 코드입니다:

import requests

API_KEY = "your-api-key-here"
API_URL = "https://api.upload-post.com/api/upload"

# Upload a video
with open("video.mp4", "rb") as f:
    response = requests.post(
        API_URL,
        headers={"권한 부여": f"API 키 {API_KEY}"},
        files={"video": ("video.mp4", f, "video/mp4")},
        data={
            "user": "mybrand",
            "title": "Python requests로 게시됨",
            "platform[]": ["tiktok", "instagram"],
        }
    )

print(response.status_code)
print(response.json())

API 키 검증

대량 배치를 실행하기 전에 키가 작동하는지 확인하고 플랜 한도를 점검하는 것이 좋습니다:

response = requests.get(
    "https://api.upload-post.com/api/uploadposts/me",
    headers={"권한 부여": f"API 키 {API_KEY}"}
)

data = response.json()
print(f"이메일: {data['email']}")
print(f"플랜: {data['plan']}")

오류 처리 모범 사례

프로덕션 스크립트를 만들 때 다음과 같은 일반적인 시나리오를 처리하세요:

import requests

def upload_with_retry(video_path, title, platforms, max_retries=3):
    for attempt in range(max_retries):
        try:
            with open(video_path, "rb") as f:
                response = requests.post(
                    "https://api.upload-post.com/api/upload",
                    headers={"권한 부여": f"API 키 {API_KEY}"},
                    files={"video": f},
                    data={
                        "user": "mybrand",
                        "title": title,
                        "platform[]": platforms,
                        "async_upload": "true",
                    },
                    timeout=120
                )

            if response.status_code == 200:
                return response.json()
            elif response.status_code == 429:
                # Rate limited, check usage
                usage = response.json().get("usage", {})
                print(f"Rate limited. Used {usage.get('count')}/{usage.get('limit')}")
                return None
            elif response.status_code == 401:
                print("Invalid API key")
                return None
            else:
                print(f"Attempt {attempt + 1} failed: {response.status_code}")

        except requests.exceptions.Timeout:
            print(f"Attempt {attempt + 1} timed out, retrying...")

    print(f"모든 {max_retries} 시도가 {video_path}에 대해 실패했습니다.")
    return None

업로드 기록 확인

업로드 기록을 조회하여 어떤 것이 처리되었는지 확인하거나 리포팅 대시보드를 만들 수 있습니다:

response = requests.get(
    "https://api.upload-post.com/api/uploadposts/history?page=1&limit=20",
    headers={"권한 부여": f"API 키 {API_KEY}"}
)

for entry in response.json()["history"]:
    status = "OK" if entry["success"] else "FAILED"
    print(f"[{status}] {entry['platform']} - {entry['post_title']} - {entry['post_url']}")

다음 단계

기본을 익혔으니, 다음에 만들어 볼 수 있는 것들을 소개합니다:

오늘부터 Python으로 자동화를 시작하세요

SDK를 설치하고, API 키를 받고, 5분 안에 첫 번째 동영상을 게시하세요. 무료 플랜에 월 10회 업로드가 포함됩니다.

pip install upload-post