프로필·상품·리뷰 사진처럼 흔한 이미지 업로드 기능 뒤에 왜 R2·S3가 필요한지, 보안과 비용, presigned URL, 리사이징까지 비개발자 눈높이로 정리했습니다.
컴윗
· 9분 읽기
클로드랑 지피티가 R2·S3를 연동하라는데, 그게 뭔가요?
프로필 사진 바꾸기, 상품 사진 등록하기, 리뷰에 영수증 첨부하기. 사용자가 사진을 올리는 기능은 웬만한 서비스에 한 번쯤 들어갑니다.
화면에 버튼 하나 만들면 끝날 것 같지만, AI에게 시켜보면 갑자기 낯선 이름이 나옵니다.
이미지 업로드를 구현하려면 파일을 저장할 스토리지가 필요합니다. 몇 가지 옵션이 있어요.
댓글 0
첫 댓글을 남겨보세요.
AWS S3 — 가장 널리 쓰이는 표준
Cloudflare R2 — 전송 요금이 무료
Supabase Storage — 이미 Supabase를 쓰고 계시다면
Vercel Blob — Vercel 프로젝트와 통합이 쉬움
어떤 걸 사용하시겠어요?
이미 서비스를 배포했는데 왜 다른 서비스를 또 연결하라는 걸까요? 시키는 대로 검색해 보면 버킷, 스토리지, CORS, 리전 같은 말이 한꺼번에 나옵니다. 프로필 사진 하나 바꾸게 하고 싶었을 뿐인데, 첫 단계부터 막힙니다.
이미지 업로드는 화면에 파일 선택 버튼을 붙이는 일보다 조금 큽니다. 사진을 오래 보관할 곳, 누가 올릴 수 있는지 확인하는 장치, 용량과 전송 비용, 큰 사진을 줄이는 절차까지 한 묶음입니다.
R2와 S3가 무엇인지, 왜 이런 준비가 필요한지부터 하나씩 풀어보겠습니다. 요금은 2026년 7월 22일 기준이라 결제 전에는 각 공식 페이지에서 한 번 더 확인하는 편이 좋습니다.
이미지를 보여주는 것과 사용자가 올리게 하는 것은 다릅니다
서비스를 만들 때 넣은 로고와 배너는 처음 배포할 때 함께 올릴 수 있습니다. 반면 사용자가 올리는 사진은 배포를 마친 뒤에도 계속 들어옵니다. 오늘 가입한 사람의 프로필 사진도 받아야 하고, 내일 판매자가 등록할 상품 사진도 보관해야 합니다.
웹사이트를 배포했다고 해서 사용자의 사진을 계속 받아 보관할 공간까지 따라오는 건 아닙니다. 그래서 사진과 영상을 맡아 줄 별도 창고를 연결합니다. 개발자는 이런 서비스를 오브젝트 스토리지라고 부릅니다. AWS S3와 Cloudflare R2가 대표적이고, Supabase Storage와 Vercel Blob도 같은 일을 합니다.
어디를 고르든 챙길 건 비슷합니다.
사진을 얼마나 오래, 얼마나 많이 보관할지
올린 사진을 사용자에게 보여줄 때 돈이 얼마나 나갈지
로그인한 사람만 올리게 할지
한 사람이 올릴 수 있는 파일의 크기와 개수를 어디까지 허용할지
휴대폰 원본 사진을 그대로 둘지, 알맞은 크기로 줄일지
S3나 R2를 고르는 일은 이 준비의 시작일 뿐입니다.
아무나 올릴 수 있게 두면 무료 드라이브가 됩니다
사진 업로드 주소를 누구에게나 열어 두면 무슨 일이 생길까요? 누군가 그 주소를 찾아내 자기 파일을 계속 올릴 수 있습니다. 내 서비스의 이미지 창고를 무료 구글 드라이브나 아이클라우드처럼 쓰는 셈입니다.
사람이 직접 할 필요도 없습니다. 자동화 프로그램은 큰 파일을 짧은 시간에 수천 개씩 올릴 수 있습니다. 저장 공간이 차고, 전송량이 늘고, 그 비용은 서비스 운영자가 냅니다. 이미지가 아닌 파일이나 위험한 파일을 섞어서 올릴 수도 있고요.
그래서 이미지 업로드에는 보통 이런 제한을 함께 넣습니다.
로그인한 사용자만 요청할 수 있게 확인
JPG·PNG·WebP처럼 허용한 파일만 받기
파일 하나의 최대 용량과 한 사람의 업로드 횟수 제한
자기가 올린 사진만 바꾸거나 지울 수 있게 권한 확인
업로드할 때마다 짧게 쓸 수 있는 임시 허가 발급
마지막 임시 허가를 만들 때 자주 쓰는 방식이 presigned URL입니다.
사진 한 장에만 쓰는 임시 업로드 주소
presigned URL은 어렵게 들리지만, 사진 한 장과 짧은 시간만 허용하는 임시 업로드 표에 가깝습니다.
사용자가 사진을 고르면 서비스는 먼저 로그인 여부와 파일 크기를 확인합니다. 문제가 없으면 “이 사진을 앞으로 몇 분 동안 정해진 자리에 올려도 된다”는 임시 주소를 줍니다. 사용자의 브라우저는 그 주소로 사진 창고에 바로 파일을 보냅니다. 시간이 지나면 주소를 쓸 수 없고, 다른 파일의 자리나 사진 창고 전체에는 접근할 수 없습니다.
사용자는 서비스에서 임시 업로드 주소만 받고, 사진은 스토리지로 바로 보냅니다.
이 구조는 중요한 열쇠를 사용자에게 보여주지 않습니다. 사용자는 허락받은 사진 하나만 올릴 수 있고, 사진 창고 전체를 건드릴 수 없습니다.
사진이 움직이는 길도 짧아집니다. 사진을 서비스 서버로 먼저 보내고 다시 스토리지로 넘기면 휴대폰 → 서비스 서버 → 이미지 창고를 거칩니다. 큰 파일이 서버를 두 번 오가면서 실행 시간과 전송량이 늘고, 배포 업체가 정한 파일 크기 제한에도 걸릴 수 있습니다.
presigned URL을 쓰면 휴대폰 → 이미지 창고로 바로 보냅니다. 서비스 서버는 잠깐 쓸 주소만 발급합니다. 불필요한 중간 전송을 빼니 서버가 처리할 일과 비용을 줄이고, 큰 사진에서 자주 만나는 업로드 실패도 피할 수 있습니다.
AI에게 직접 시킬 때는 “로그인한 사용자에게만 presigned URL을 발급하고, 파일 종류와 크기를 확인해 줘”라고 말하면 이 구조를 더 정확히 잡습니다.
네 가지 선택지, 요금표부터
사진 창고를 골랐다면 보관료와 전송료를 함께 봐야 합니다. 보관료는 사진을 저장해 둔 양에 붙고, 전송료는 사용자가 그 사진을 볼 때 움직인 데이터에 붙습니다.
사진 보관료(GB·월)
사용자에게 보여줄 때
무료 구간
처음 준비할 것
AWS S3
지역마다 다름
월 100GB까지 무료, 이후 지역별 과금
신규 계정은 크레딧 제도 적용
AWS 계정, IAM, 버킷
Cloudflare R2
$0.015
무료
저장 10GB, 상시
Cloudflare 계정, 버킷
Supabase Storage
Pro $25에 100GB 포함
250GB 포함, 초과 $0.09/GB
Free: 저장 1GB·전송 5GB
기존 프로젝트에 내장
Vercel Blob
$0.023
$0.05/GB부터
Hobby: 저장 1GB·전송 10GB
Vercel에 내장
숫자만 봐선 다 고만고만해 보이는데, 각각 성격이 꽤 다릅니다.
**S3**는 가장 널리 쓰입니다. AI가 참고할 자료와 예제도 많고 서울 지역을 고를 수 있습니다. 대신 AWS 계정, 결제 카드, 권한 설정, 액세스 키 발급을 차례로 거쳐야 합니다. 바이브코딩을 하다가 AWS 화면을 처음 열면 이 과정부터 낯설 수 있습니다.
**R2**는 사용자가 사진을 볼 때 드는 전송료를 받지 않습니다. S3와 연결 방법도 비슷합니다. 다만 저장 지역을 서울로 직접 고르는 방식은 아닙니다. 한국 사용자가 많다면 실제 사진이 얼마나 빨리 뜨는지 확인할 필요가 있습니다.
**Supabase Storage**는 이미 Supabase를 쓰고 있다면 연결할 계정을 하나 줄일 수 있습니다. 무료 플랜은 저장 1GB와 전송 5GB라 사진을 많이 다루면 유료 플랜도 함께 살펴봐야 합니다.
**Vercel Blob**은 서비스를 Vercel에 배포했다면 연결하기 편합니다. 다만 저장과 전송 외에도 작업과 요청에 따라 과금 항목이 나뉩니다. 사용량이 늘기 전에 어떤 항목에서 돈이 나가는지 확인해 볼 만합니다.
사진을 저장하는 돈보다 보여주는 돈이 커질 수 있습니다
사진은 한 번 저장하지만 사용자가 볼 때마다 다시 보냅니다. 그래서 서비스가 커지면 저장료보다 전송료가 더 커질 수 있습니다.
5MB짜리 사진 2,000장을 보관하면 10GB입니다. 이 정도의 보관료는 업체에 따라 월 몇십 센트 수준입니다. 그런데 목록 화면에서 2MB짜리 원본 사진을 열 장씩 보여주고 하루에 500명이 방문하면, 하루 10GB, 한 달 300GB를 보냅니다. S3라면 월 무료 전송량 100GB를 빼도 200GB에 요금이 붙습니다. 지역에 따라 단가가 달라지지만, $0.09/GB인 지역을 예로 들면 약 $18입니다. 방문자가 열 배로 늘면 전송량도 열 배로 늘고요.
이 계산에서 사진 한 장을 2MB에서 200KB로 줄이면 전송량도 10분의 1로 줄어듭니다. 어느 업체를 고르든 사진 크기를 함께 챙겨야 하는 이유입니다.
이미지 업로드 팁: 휴대폰 원본을 그대로 올리지 않는 이유
요즘 휴대폰 사진은 한 장에 3~10MB를 넘기도 합니다. 프로필 화면에서 작게 보여줄 사진까지 원본 크기로 보낼 필요는 없습니다. 저장 공간을 더 쓰고, 사용자는 사진이 뜰 때까지 더 오래 기다립니다.
그래서 업로드할 때 사진의 가로·세로 크기를 줄이고 WebP 같은 가벼운 형식으로 바꿉니다. 프로필 사진은 작은 크기, 상품 상세 사진은 조금 큰 크기처럼 화면 용도에 맞춰 여러 크기를 준비하기도 합니다. 이 작업을 이미지 리사이징 또는 이미지 최적화라고 부릅니다.
잘 만든 커머스 서비스를 보면 상품 사진이 여러 장인데도 빠르게 뜹니다. 개발자들이 원본 사진을 화면마다 그대로 보내지 않고, 목록·상세·장바구니에 필요한 크기와 형식으로 미리 줄여 놓았기 때문입니다.
리사이징은 저장 용량과 전송 비용을 줄입니다. 사진이 가벼우니 화면도 더 빠릿해집니다. 사진이 많은 상품 목록이나 커뮤니티 피드에서는 차이가 더 크게 느껴집니다.
직접 연결하면 여기까지 챙깁니다
스토리지를 하나 골랐다고 이미지 업로드 기능을 다 만든 건 아닙니다. 실제 서비스에 붙이려면 아래 설정이 남습니다.
스토리지 계정과 결제 수단 준비
사진을 담을 버킷 생성
업로드 권한과 액세스 키 발급
비밀키가 화면이나 공개 GitHub 저장소에 나오지 않게 관리
내 서비스 주소에서만 업로드를 허용하는 CORS 설정
로그인·파일 종류·용량·횟수 확인
presigned URL 발급과 업로드 실패 처리
이미지 리사이징과 형식 변환
사진 교체, 삭제, 회원 탈퇴 때 파일 정리
설정 하나를 빠뜨리면 로컬에서는 잘 되는데 배포 후에 사진만 안 올라가거나, 작은 사진은 되는데 휴대폰 원본만 실패할 수 있습니다. 키가 공개되거나 업로드 권한을 넓게 열어 두면 비용과 보안 문제도 함께 생깁니다.
그래서 컴윗에서 미리 준비했습니다
컴윗은 이 준비를 프로젝트에 미리 넣었습니다.
컴윗에서 만든 프로젝트를 클로드 코드나 코덱스로 열고 “프로필 사진을 바꿀 수 있게 해줘” 또는 “상품 사진을 등록하게 해줘”라고 말하면 됩니다. 컴윗 스킬은 AI가 미리 연결한 이미지 서버를 쓰도록 안내합니다. R2와 S3 중에서 고르라고 묻지 않고, 별도 계정이나 버킷·키·CORS 설정도 요구하지 않습니다.
직접 만들면 사람이 여러 설정을 챙기지만, 컴윗 프로젝트에서는 만들고 싶은 기능만 말하면 됩니다.
컴윗 스킬은 AI가 presigned URL 방식으로 업로드를 만들고, 로그인과 파일 제한을 확인하도록 안내합니다. 휴대폰 원본을 그대로 올리지 않도록 리사이징 절차도 함께 알려줍니다. 저장 용량과 전송량을 줄이고, 사용자는 화면에서 사진을 더 빨리 볼 수 있습니다.
서버는 한국에 있고, 이미지 사용료는 컴윗 플랜에 포함합니다. 스토리지 업체의 청구서를 따로 관리할 필요도 없습니다. 막히는 지점이 생기면 현직 개발자가 프로젝트를 같이 확인합니다.
이미지 업로드는 버튼 하나처럼 보이지만, 그 뒤에는 저장 공간·권한·비용·리사이징이 함께 있습니다. 컴윗에서는 사진을 어디에 둘지보다, 어떤 화면에서 누가 어떤 사진을 올릴지만 정하면 됩니다.