Slack API 파일 업로드: files.upload 대신 세 번 호출
files.upload 지원 중단 뒤에는 files.getUploadURLExternal, upload_url에 바이트 POST, channel_id와 files.completeUploadExternal 순입니다.

Slack API로 파일을 업로드하려면 세 번 호출하세요. 파일의 filename과 바이트 단위 length로 files.getUploadURLExternal을 호출하고, 반환된 upload_url로 원본 바이트를 POST한 뒤, 반환된 파일 ID와 파일을 공유할 채널의 channel_id로 files.completeUploadExternal을 호출하면 그 채널에 파일이 공유됩니다. 호출 한 번으로 끝나던 예전 files.upload는 지원 중단(deprecated)되었습니다. Slack 레퍼런스 페이지에는 이 메서드가 November 12, 2025에 동작을 멈추고 종료(sunset)된다고 나와 있습니다.
Slack 관련 내용은 files.upload, files.getUploadURLExternal, files.completeUploadExternal, Working with files 페이지에서, Sume 관련 내용은 Run 웹훅 (영문)과 실행과 결과 (영문)에서 가져왔습니다. 모두 2026-09-28에 확인했습니다. Sume에는 Slack 앱이나 커넥터가 없습니다. 완성된 영상에 대한 Sume 웹훅은 여러분의 서버가 받고, Slack 호출도 그 서버가 합니다. 링크만으로 충분하다면, Slack 영상 생성 봇은 업로드 대신 URL을 게시하는 방식입니다.
files.upload는 지원 중단되었나요?
네. Slack 변경 로그에 따르면 May 16, 2024부터 새로 만든 앱은 files.upload를 호출할 수 없고, 이를 대체하는 두 메서드는 "more reliable, especially when uploading large files."(특히 큰 파일을 업로드할 때 더 안정적)라고 합니다. files.upload 레퍼런스 페이지에는 이 변경 로그를 가리키는 method_deprecated 오류가 나와 있습니다.
Slack SDK는 새 절차를 호출 하나로 감싸 줍니다. Node용 @slack/web-api 패키지에서는 uploadV2, python-slack-sdk에서는 files_upload_v2, Java SDK에서는 FilesUploadV2Request입니다. SDK 없이 하면 이 절차는 HTTP 요청 세 번입니다.
API로 채널에 파일을 어떻게 업로드하나요?
Web API 호출 두 번은 Authorization 헤더에 토큰을 담아 보내세요. 가운데 요청은 Slack이 알려 준 URL로 보냅니다.
files.completeUploadExternal은 정확히 한 번 호출하세요. 이 메서드를 끝내 호출하지 않으면 Slack은 그 업로드를 버리며, 호출하기 전에 Slack이 파일 처리를 마칠 때까지 기다릴 필요는 없습니다.- 두 Web API 메서드 모두 폼 인코딩된 본문을 받습니다. Slack의 예제는
files를 폼 안에 JSON 문자열로 넣어 보내고, 바이트는application/octet-stream으로 보냅니다.
| 단계 | 보내는 것 | 돌려받는 것 |
|---|---|---|
1. files.getUploadURLExternal | filename, 그리고 파일의 바이트 크기인 length | upload_url과 file_id |
2. upload_url로 POST | 원본 바이트 또는 multipart 폼으로 보낸 파일 | 성공하면 HTTP 200, 그 밖의 상태는 모두 실패 |
3. files.completeUploadExternal | 파일 ID 배열인 files(제목은 선택), 그리고 channel_id와 선택 항목인 initial_comment | 공유된 파일 객체. channel_id가 없으면 파일은 비공개로 남음 |
// Node 18+. SLACK_BOT_TOKEN needs the files:write scope.
async function slack(method, params) {
const res = await fetch(`https://slack.com/api/${method}`, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}` },
body: new URLSearchParams(params), // form-encoded
});
const json = await res.json();
if (!json.ok) throw new Error(`${method}: ${json.error}`);
return json;
}
async function uploadToChannel(fileUrl, filename, channelId) {
const src = await fetch(fileUrl); // a public media.sume.com URL
if (!src.ok) throw new Error(`download answered ${src.status}`);
const bytes = Buffer.from(await src.arrayBuffer());
const { upload_url, file_id } = await slack("files.getUploadURLExternal", {
filename, length: String(bytes.length), // exact size in bytes
});
const sent = await fetch(upload_url, { method: "POST", body: bytes,
headers: { "Content-Type": "application/octet-stream" } });
if (sent.status !== 200) throw new Error(`upload_url answered ${sent.status}`);
await slack("files.completeUploadExternal", {
files: JSON.stringify([{ id: file_id, title: filename }]),
channel_id: channelId, initial_comment: "Your video is ready",
});
}어떤 스코프와 한도가 적용되나요?
- 새 메서드 두 개 모두 봇 토큰이나 사용자 토큰에
files:write스코프가 필요하며, Slack은 두 메서드를 Tier 4(분당 100회 이상 호출)로 분류합니다. - 봇이 채널 멤버여야 합니다. 그렇지 않으면
files.completeUploadExternal이not_in_channel로 응답합니다. - Slack 도움말 센터에 따르면 최대 1GB 크기의 파일을 추가할 수 있습니다. 이 페이지는 Slack 안에서 직접 파일을 추가하는 경우를 다루며, 두 메서드 레퍼런스에는 일반적인 파일 크기 상한이 나와 있지 않습니다. 워크스페이스가 큰 파일 업로드를 제한할 수도 있으며, 이때
files.getUploadURLExternal은file_upload_size_restricted를 반환합니다. length가 0이면missing_argument로 거부되므로, 실제로 가진 바이트 수를 재서 넣으세요.
백엔드에서 생성한 영상은 어떻게 게시하나요?
완성된 영상의 웹훅을 받는 서버에서 업로드하고, 브라우저에서는 절대 업로드하지 마세요. 그래야 Slack 토큰과 Sume API 키가 모두 서버에만 남습니다. Sume Format 실행이라면 흐름은 다음과 같습니다.
- 실행이 완료되거나 실패하면 Sume는 여러분의
communication.webhook_url로 서명된 POST를 한 번 보냅니다. 원본 본문에 대한 HMAC-SHA256 서명을 검증하고, 이벤트를 기록하고, 10초 시도 시간 안에2xx로 응답하세요. 검증 방법은 Sume 영상 실행용 서명된 웹훅에서 다룹니다. 느린 엔드포인트는 재시도를 받으므로 업로드는 응답한 다음에 하세요. - 봉투의
request_id로 중복을 제거하세요. 이 값은 재시도마다 같으므로, 재시도된 전달이 영상을 두 번 게시하지 않습니다. - 보여 줄 결과물 하나인
payload.primary_output_url이나,url,content_type,size_bytes가 담긴payload.artifacts[]항목을 가져오세요. 이media.sume.comURL은 내구성 있고 URL을 가진 누구에게나 공개되므로, 다운로드에 API 키가 필요 없습니다. - Slack URL을 Sume의
webhook_url로 등록하지 마세요. Sume의 POST에는 Slack 메시지가 아니라 Sume 자체의 실행 영수증이 담깁니다.
출처
- Run 웹훅 (영문)
- 실행과 결과 (영문)
- 인증
- Slack: files.upload 메서드 (2026-09-28 확인)
- Slack: files.getUploadURLExternal 메서드 (2026-09-28 확인)
- Slack: files.completeUploadExternal 메서드 (2026-09-28 확인)
- Slack: 파일 다루기(Working with files) (2026-09-28 확인)
- Slack 변경 로그: files.upload 메서드 지원 종료 (2026-09-28 확인)
- Slack 도움말 센터: Slack에 파일 추가하기 (2026-09-28 확인)
관련 글
연동 카테고리의 다른 글
- Strands Agents MCP: 에이전트를 Sume MCP 서버에 연결
MCPClient로 Strands 에이전트를 원격 MCP 서버에 연결하세요. Sume 호스팅 MCP URL과 API 키 헤더를 넣고, tool_filters로 유료 도구를 뺍니다.
- Teams Incoming Webhook 종료: Workflows로 전환
Microsoft는 Teams의 Office 365 커넥터를 May 18~22, 2026에 비활성화하기로 했습니다. 대신 Workflows 웹훅 URL을 만들고 Adaptive Card를 POST하세요.
- ChatGPT에 MCP 서버를 추가하는 방법: 개발자 모드
ChatGPT 개발자 모드를 켜고, 서버 URL로 앱을 만들고, OAuth로 로그인하세요. Sume 호스팅 MCP 서버를 예로 들어 단계를 설명합니다.
- Python으로 영상에 자막을 넣는 방법
Python Requests로 영상에 자막을 넣으세요. 영상 URL을 Sume의 /v1/video-captions로 POST하고, Job을 폴링한 뒤 자막을 입힌 video_url을 읽으면 됩니다.
작성자 Sume