소셜 게시(Social publishing)
목적
출시 콘텐츠를 한 곳에서 예약하여 각 플랫폼의 공식 API를 통해 게시하고, 개인 계정을 브랜드에 잃거나 브랜드를 개인 계정에 잃지 않습니다. 여기서 사용하는 도구는 Postiz(오픈 소스, 자체 호스팅)이며, 플랫폼 단계는 다른 스케줄러에도 동일하게 적용됩니다.
사전 준비 사항
- 브랜드 계정이 이미 생성되어 있어야 함: Instagram 전문(professional) 계정, Threads 프로필(Instagram에서 파생), X 계정, 선택적으로 TikTok.
- Cloudflare에 등록된 도메인(터널 호스트명용), Docker Desktop, 게시 시간에 켜져 있는 머신(또는 소형 VPS).
- 브라우저에서 콘솔을 사용하는 경우
console-automation설정. - 콘텐츠 캘린더(아래 '캘린더' 참조).
플랫폼 현실(시작하기 전에 다시 확인하세요. 변경될 수 있음)
| 플랫폼 | 공식 경로 | 차단 요소 |
|---|---|---|
| Meta 앱 + Facebook 로그인, Facebook 페이지에 연결된 IG 전문 계정 | 새로운 Meta 앱은 '통합 로그인' Instagram 설정을 사용하며, 비즈니스 포트폴리오가 필요합니다. 이전 Instagram-로그인 전용 설정은 '새로운 앱에서는 사용할 수 없습니다'. 스토리는 일반 미디어로만 게시 가능: API를 통한 설문조사, 링크, 카운트다운 스티커는 불가능. | |
| Threads | Threads 사용 사례가 포함된 Meta 앱 | 앱 검토(App Review) 전까지 Threads 테스터 역할이 있는 계정만 연결 가능. 테스터는 Threads › 설정 › 계정 › 웹사이트 권한 › 초대에서 수락합니다. |
| X | 유료 API 액세스가 포함된 개발자 계정(현재 X API 가격 확인) | 결제 수단 필요, 지출 한도 설정 필요. |
| TikTok | 콘텐츠 게시 API(Content Posting API) | 감사(audit)를 통과하지 않은 앱은 비공개(private) 로만 게시 가능(감사에는 시간이 걸림). 새 계정은 전화 인증이 필요하며, 하나의 번호는 하나의 계정에만 등록 가능. |
| YouTube | 데이터 API 업로드 | 인증되지 않은 API 프로젝트는 규정 준수 감사(compliance audit) 전까지 비공개로 업로드됩니다. |
차단 요소를 고려하여 계획을 세우세요: 감사를 일찍 시작하고, 감사가 통과될 때까지 TikTok/YouTube는 네이티브(TikTok Studio, YouTube Studio 스케줄러)로 게시하거나 해당 플랫폼을 포기하세요.
절차
1. Postiz 자체 호스팅(Docker)
- 공식
postiz-docker-compose파일로 시작합니다.up전에:- 필요 없는 서비스는 제거하고, 머신에서 이미 사용 중인 포트를 바인딩하는 서비스는 제거합니다(업스트림 파일은 Temporal UI를
127.0.0.1:8080에 바인딩함). - Elasticsearch 제거: Temporal
ENABLE_ES=false및SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES=true로 설정(SQL 가시성 사용). Postiz는 키워드 속성 두 개만 등록합니다. Temporal이 ES와 함께 처음 시작된 경우 데이터베이스에 기본 텍스트 속성이 남아 있어 Postiz가 "cannot have more than 3 search attribute of type Text" 오류와 함께 실패합니다. 예약 전에 Temporal 데이터베이스 볼륨을 재생성하세요. - Postiz를
127.0.0.1에만 바인딩하고,MAIN_URL,FRONTEND_URL,NEXT_PUBLIC_BACKEND_URL은 공개 HTTPS 호스트명으로 설정합니다. - 비밀값(
JWT_SECRET, 터널 토큰, 앱 키)은 git에서 무시되는.env파일에 저장하고, 컴포즈 파일에서는${VAR}로 참조합니다. - 서비스별로
mem_limit/cpus를 추가합니다. Postiz는 프론트엔드, 백엔드, 오케스트레이터를 하나의 컨테이너에서 실행하며, 약 1.5GB를 사용하는 것을 관찰했습니다. 따라서 2GB 제한으로 한도 초과를 방지합니다. Windows에서는%USERPROFILE%\.wslconfig에서 WSL VM도 제한합니다(memory=4GB,processors=4,autoMemoryReclaim=gradual). 그런 다음wsl --shutdown하고 Docker Desktop을 다시 시작합니다.
- 필요 없는 서비스는 제거하고, 머신에서 이미 사용 중인 포트를 바인딩하는 서비스는 제거합니다(업스트림 파일은 Temporal UI를
- 브라우저에서 페이지가 하이드레이션(hydrated)된 후에 첫 번째 계정을 생성합니다(하이드레이션되지 않은 양식은 GET으로 제출되어 비밀번호가 URL에 노출됨). 그런 다음
DISABLE_REGISTRATION=true를 설정하고 재시작합니다. restart: always를 유지하고 "시작할 때 Docker Desktop 시작"을 활성화합니다. 머신이 스케줄러인 경우 절전 모드를 비활성화합니다.
2. 공개 호스트명(Cloudflare Tunnel)
- 원격 관리형 터널을 생성합니다(API:
config_src: cloudflare와 함께POST /accounts/{id}/cfd_tunnel, 인그레스 규칙과 함께PUT .../configurations, 프록시된CNAME을<tunnel-id>.cfargotunnel.com으로,GET .../token). - 동일한 컴포즈 네트워크에서
cloudflared를 서비스로 실행하고, 인그레스를localhost가 아닌http://postiz:5000으로 지정합니다. - 승인 필요: 터널은 로컬 서비스를 인터넷에 노출시키므로 생성 전에 승인을 받아야 합니다. 선택적으로 Cloudflare Access를 앞에 추가할 수 있습니다(계정에 Zero Trust가 활성화되어 있어야 함. Meta의 미디어 가져오기를 위해
/uploads는 접근 가능하게 유지).
3. Meta(Instagram + Threads)
- 게시용으로 별도의 Meta 앱을 생성합니다(이미 앱 내 기능(예: Instagram 스토리 공유)을 지원하는 앱에 사용 사례를 추가하지 마세요). 사용 사례: "Instagram에서 메시징 및 콘텐츠 관리" 및 "Threads API 액세스".
- Instagram:
- 사용 사례에서 요청할 때 비즈니스 포트폴리오를 생성합니다(무료, 이름, 소유자 이름, 비즈니스 이메일). 인증은 다른 사람의 데이터와 앱 검토(App Review)에만 필요합니다.
- 브랜드용 Facebook 페이지를 생성하고(Meta 광고에도 필요함) Instagram 전문 계정을 연결합니다: 페이지 설정 › 연결된 계정 › Instagram › 연결. OAuth 팝업은 브라우저가 보유한 Instagram 계정으로 로그인합니다. "다음으로 로그인..." 이름을 읽고, 개인 계정이면 먼저 계정을 전환하세요(개인 계정을 연결하면 전문 계정으로 전환됨).
- Instagram 사용 사례에서 스케줄러가 요청하는 정확한 범위를 추가합니다(Postiz:
instagram_basic,pages_show_list,pages_read_engagement,business_management,instagram_content_publish,instagram_manage_comments,instagram_manage_insights). Facebook for Business 리디렉션 URI를 스케줄러의 콜백으로 설정합니다(Postiz:/integrations/social/instagram). - 앱 ID + 시크릿(앱 설정 › 기본, 시크릿을 표시하려면 Facebook 비밀번호 입력) →
FACEBOOK_APP_ID/SECRET.
- Threads:
threads_basic,threads_content_publish,threads_manage_replies,threads_manage_insights를 추가하고, 리디렉트(/integrations/social/threads)와 설치 해제/삭제 콜백 URL을 설정합니다. 별도의 Threads 앱 ID/시크릿을 가져오고, 브랜드 프로필을 Threads 테스터로 추가한 후 휴대폰에서 초대를 수락합니다. - Threads 동의 URL이 동의 화면 대신 Threads 홈 페이지로 이동하는 경우, 브라우저 세션이
threads.com에 있는 반면 스케줄러는threads.net을 사용합니다. 동일한 URL을threads.com에서 열어보세요. - 브라우저가 현재 페이지 역할을 하고 있는 경우(페이지를 편집한 후), Facebook 동의는 먼저 "(으)로 전환해야 합니다"를 표시합니다. 페이지가 아닌 사람으로 계속 진행하세요.
- Facebook 동의 중에 Meta는 기본적으로 "모든 현재 및 미래 페이지/비즈니스/Instagram 계정"을 선택합니다. 다른 브랜드를 관리하는 계정의 경우 "현재만"을 선택하고 브랜드의 자산을 선택하세요.
4. X
- 개발자 콘솔 온보딩: 계정 이름, 정확한 사용 사례 설명(자체 계정만, 데이터 재판매 없음, 자동 좋아요/팔로우/DM 없음), 이용약관 동의.
- 가장 작은 크레딧 팩을 구매합니다. 자동 재충전을 끄고 청구 기간 한도를 설정합니다. 대시보드 총액은 크레딧 페이지와 차이가 있을 수 있습니다.
- 앱 › 사용자 인증 설정: 읽기 및 쓰기, "웹 앱, 자동화된 앱 또는 봇", 콜백 = 스케줄러 콜백(Postiz:
/integrations/social/x), 웹사이트, 이용약관 및 개인정보 보호 URL. 저장하면 OAuth 2.0 클라이언트 시크릿이 한 번 표시됩니다. - Postiz는 OAuth 1.0a를 사용합니다. 소비자 키(Consumer Key) 를 재생성하고 키 + "소비자 키 시크릿(Consumer Key Secret)"(정확히 해당 레이블)을 한 번 복사합니다 →
X_API_KEY/X_API_SECRET. - 권한 부여: "이 앱을 신뢰합니다"를 체크하고, 화면에 브랜드 핸들이 표시되는지 확인한 후 Authorize를 클릭합니다.
5. TikTok(선택 사항)
계정:
- 새 계정은 전화 인증이 필요하며, 하나의 번호는 하나의 계정에만 등록할 수 있습니다. 웹 가입은 "앱에서 계속"으로 끝날 수 있습니다. 옵션: 브랜드 계정용 두 번째 번호를 사용하거나 기존 개인 계정을 전환합니다(새 사용자 이름, 표시 이름, 프로필 사진, 약력, 기존 개인 동영상은 보관/비공개 처리).
- 일부 지역에서는 "비즈니스 계정으로 전환" 원클릭 옵션이 사라졌습니다. 메뉴에는 "인증된 비즈니스 계정 되기"가 있는데, 회사 서류를 요구합니다. 개인 계정으로도 충분합니다: TikTok Studio 스케줄링, 분석, Spark Ads, 콘텐츠 게시 API 모두 개인 계정에서 작동합니다. 비즈니스 음악 라이브러리가 주된 손실입니다.
- 사용자 이름은 30일에 한 번, 표시 이름은 7일에 한 번 변경할 수 있습니다. 웹 프로필(이름, 약력, 사진, 통계)은 앱보다 하루 이상 지연될 수 있으므로 앱을 신뢰하세요.
- 계정 지역은 가입 시 SIM/IP를 기준으로 설정되며 설정에서 변경할 수 없었습니다.
개발자 앱(스케줄러용):
- developers.tiktok.com 가입은 "엔터프라이즈 개발자"(이메일 + 코드 + 비밀번호)만 표시되지만, 앱을 생성할 때 개인(Individual) 소유권을 선택할 수 있으므로 시작하는 데 회사가 필요하지 않습니다.
- 앱을 생성한 다음 샌드박스를 생성합니다: 기본 정보(아이콘 1024², 카테고리, 설명 120자 이하, 이용약관/개인정보 보호 URL, 웹 플랫폼 URL), 제품 로그인 키트(Login Kit)(웹 리디렉션 URI = 스케줄러 콜백, Postiz
/integrations/social/tiktok) 및 콘텐츠 게시 API(Content Posting API)(Direct Post 켜기), 그리고 스케줄러가 요청하는 모든 범위. Postiz는user.info.basic,user.info.profile,user.info.stats,video.list,video.upload,video.publish를 요청합니다. 하나라도 누락되면 동의 페이지에 "문제가 발생했습니다... 다음을 수정하세요: 범위(scope)"가 표시됩니다. 모든 편집 후에 "변경 사항 적용(Apply changes)"을 클릭하세요. - 브랜드 계정을 샌드박스 대상 사용자(Target user) 로 추가합니다(로그인 팝업에서 휴대폰 앱의 QR 스캔을 허용함). 스케줄러에서 샌드박스 클라이언트 키/시크릿을 사용합니다.
- 파일로 푸시(Push-by-file)는 도메인 인증이 필요 없지만, URL로 가져오기(Pull-by-URL)는 필요합니다.
- 감사 전:
UPLOAD모드는 동영상을 계정의 TikTok 받은 편지함에 초안으로 보냅니다(24시간 이내에 휴대폰에서 게시, 최대 5개 보류).DIRECT_POST는 작동하지만 비공개로만 게시됩니다. 공개 직접 게시를 위해 데모 동영상과 함께 프로덕션 앱 검토를 제출하세요. - 동의 단계에서 이메일 코드로 "본인 확인"을 요청할 수 있습니다. 하루에 많은 계정 변경(이메일, 이름, 약력, 새 로그인)을 수행한 후 TikTok은 이러한 코드를 속도 제한합니다("최대 시도 횟수 도달"). 강제로 시도하지 말고 중단하고 다음 날 다시 시도하세요.
6. 확인
- 스케줄러 채널 목록에 각 브랜드 계정(이름/핸들)이 표시되고, 비활성화된 계정이 없어야 합니다.
- 캘린더가 시작되기 전에 플랫폼당 하나의 비공개/위험 부담이 적은 테스트 또는 초안을 게시하세요.
- 하루 후 리소스 사용량:
docker stats --no-stream.
캘린더
- 게시 캘린더를 고정된 날짜가 아닌 실제 출시 이벤트에 맞추세요: 출시 전(다운로드 클릭 유도 문구 없음, 가격 없음), 각 스토어 출시, 그리고 둘 다 라이브 상태. 스토어 리뷰 날짜는 변경됩니다. 변경 시 캘린더를 다시 조정하세요.
- 게시물의 모든 주장을 출시된 빌드와 비교하여 확인하고, 모든 클릭 유도 문구가 각 스토어에서 실제로 라이브 상태인지 확인하세요.
- 설문조사, 링크 또는 카운트다운이 포함된 스토리는 API를 통해 게시할 수 없습니다. 앱에서 직접 게시하세요.
사람의 승인이 필요한 결정 지점
브랜드 계정, 비즈니스 포트폴리오, Facebook 페이지 생성, 터널을 통한 로컬 서비스 노출, API 크레딧 구매 및 지출 한도, 절대 연결하면 안 되는 개인 계정, 개인 계정 전환, Docker 볼륨 또는 데이터 삭제.
일반적인 실수
- OAuth 팝업이 브라우저 세션을 재사용하여 개인 Instagram 계정을 연결하는 경우.
- 새 Meta 앱에 이전 Instagram-로그인 설정이 존재한다고 가정하는 경우.
- 모바일 앱 내부에 있는 Meta 앱에 게시 사용 사례를 추가하는 경우.
- Temporal SQL 가시성으로 충분할 때 Elasticsearch를 스택에 남겨두는 경우.
- 업스트림 컴포즈 파일이 다른 로컬 서비스에서 이미 사용 중인 포트를 차지하는 경우.
- X 키를 잘못된 레이블("소비자 키 시크릿(Consumer Key Secret)", 대화 상자 제목 아님)에서 저장한 경우.
- 앱이 1일에 두 스토어 모두에 라이브 상태인 것처럼 캘린더를 작성하는 경우.
- 모든 TikTok 계정 변경과 개발자 연결을 같은 날에 수행하여 인증 코드 속도 제한에 걸리는 경우.