학습 목표와 사전 지식
목표: Storage 이미지의 객체 경로·다운로드 링크·권한 실패를 구분합니다.
사전 지식: Storage ref, 개발자 도구, Firebase Console의 파일 목록
이미지가 깨지면 DB의 문자열을 임의로 고치기 전에 bucket과 객체 경로를 확인하세요. SDK로 얻은 다운로드 URL과 인증된 객체 요청은 보안 의미가 다릅니다.
| 증상 | 확인할 사실 | 수정 위치 |
|---|---|---|
| 404 / object-not-found | 객체가 실제로 존재하는가 | DB의 storagePath·업로드 완료 처리 |
| 403 / unauthorized | SDK 인증·Rules 또는 다운로드 token이 유효한가 | 인증/Rules 또는 링크 재발급 |
| 새 탭 성공·fetch 실패 | 동일 URL의 CORS 응답인가 | bucket CORS |
| 업로드는 됐으나 DB 저장 실패 | 고아 객체가 남았는가 | 업로드 후 보상 정리 작업 |
src/images.js · 전체 모듈; 초기화된 storage와 저장된 경로를 전달
import { getDownloadURL, ref } from 'firebase/storage';
export async function resolveImage(storage, storagePath) {
if (!storagePath) throw new Error('객체 경로가 필요합니다.');
return getDownloadURL(ref(storage, storagePath));
}
404 최소 재현과 수정
개발 bucket에서 products/demo/cover.png를 업로드한 뒤 경로 products/demo/missing.png로 조회하면 없는 객체 오류가 납니다. src/images.js에 전달하는 DB storagePath를 실제 업로드 결과의 snapshot.ref.fullPath로 저장하도록 수정합니다. 같은 객체 경로로 다시 조회해 URL 취득과 이미지 표시를 확인합니다. 슬래시가 포함된 경로를 직접 URL에 이어 붙이는 대신 ref와 getDownloadURL을 사용하세요.

다운로드 token은 공유 링크의 일부입니다
getDownloadURL로 얻은 token URL은 링크를 가진 사람이 접근 가능한 공유 링크로 다뤄야 합니다. 장기 비공개 파일에 URL을 배포하고 Rules만 변경하면 즉시 회수된다고 가정하지 마세요. token을 회전·제거한 경우 기존 링크를 다시 열어 거부되는지 확인하고 DB의 링크를 갱신합니다. 로그·분석 이벤트에 전체 token URL을 남기지 않습니다. 비공개 읽기는 인증 SDK getBlob/getBytes와 Rules, 또는 별도 서버 전달 구조를 검토하세요.
403 수정 전 확인
같은 다운로드 URL을 여는 검사와 getDownloadURL을 새로 호출하는 검사는 구분합니다. 전자는 링크의 유효성, 후자는 SDK 요청의 권한에 영향을 받습니다. Firebase Console에서 버킷 이름을 복사하되 .appspot.com을 무조건 붙이지 마세요. 새 버킷은 .firebasestorage.app 형식일 수 있습니다. 플랜·할당량 문제는 공식 오류 코드와 해당 프로젝트 상태로 확인합니다.

파일 삭제와 DB 정합성
새 이미지 업로드 성공 → 새 경로 DB 반영 → 이전 객체 정리 순으로 나눕니다. Firestore와 Storage를 묶는 원자적 트랜잭션은 없습니다. 중간 실패를 기록하고 재시도할 수 있어야 하며, 삭제 함수에 사용자가 준 임의 URL을 그대로 넘기지 않도록 허용 경로와 권한을 검사하세요.
직접 확인할 결과
실제/없는 경로 각각 SDK 조회
링크 재발급 전후 기존 URL 확인
로그아웃 SDK 접근과 token URL 접근 별도 확인
사용 전 플랜 확인
2026-09-13 공식 문서 기준 Cloud Storage for Firebase는 기본 버킷 접근을 포함해 Blaze 종량제 플랜이 필요합니다. 무료 사용량과 결제 플랜은 다른 개념입니다. 개발 프로젝트의 결제 연결·예산 알림·실제 사용량을 확인하세요.
검증 범위와 기준일
공식 문서 확인일: 2026-09-13. 웹 SDK 예제는 모듈형 API 기준입니다. 이 글의 코드·구조 정적 검토와 실제 클라우드 인증·저장·배포 검증을 구분합니다. 본인 개발 Firebase 프로젝트의 실제 인증·권한·배포 요청은 이 편집 환경에서 실행하지 않았습니다.
이어서 학습하기
- Firebase permission-denied 오류 해결: Firestore Rules 체크리스트
- Firebase CORS 오류 해결: Storage 이미지 업로드가 막힐 때 확인할 설정
공식 문서
이 글이 도움이 되었나요?
Firebase 학습 순서
필수 13개 · 전체 19개
읽음 기록 관리
전체 과정 목차 (19개)
- 필수 길잡이 · Firebase 실무 로드맵: Auth, Firestore, Storage, Functions
- 필수 학습 · Firebase 초기화 구조: Next.js firebase.ts 설계 기준
- 필수 학습 · Firebase Authentication 사용 기준: 로그인 유지와 비밀번호 재설정
- 필수 학습 · Firebase 보안 규칙 설계: Firestore와 Storage 권한 관리하기
- 필수 학습 · Firestore CRUD 사용법: 컬렉션 구조와 읽기 쓰기 흐름
- 필수 학습 · Firebase Auth Context 설계: 로그인 권한과 라우팅 관리하기
- 필수 학습 · Firebase Storage 이미지 업로드 사용법: 상품 이미지 관리 흐름 만들기
- 필수 학습 · Firebase Custom Claims 사용법: 관리자 권한 구분하기
- 필수 학습 · Firebase Functions v2 사용법: 트리거 배포 Secret 처리
- 필수 학습 · Firestore seed data 설계: 리뷰 더미 데이터 구조 잡기
- 선택 참고 · Firebase 배포 제외 파일 설정: firebase.json의 ignore 사용법
- 선택 참고 · Firebase Firestore 인덱스 삭제 질문 해결: 배포 중 안전하게 판단하기
- 선택 참고 · Firebase Auth unauthorized-domain 오류 해결: 로그인 도메인 설정 확인
- 선택 참고 · Firebase permission-denied 오류 해결: Firestore Rules 체크리스트
- 선택 참고 · Firebase Storage 이미지 오류 해결: 403·404·token·Rules 확인법 현재 글
- 선택 참고 · Firebase CORS 오류 해결: Storage 이미지 업로드가 막힐 때 확인할 설정
- 필수 선수 · Firebase 실무 오류 해결 모음: Storage, Firestore, Auth 체크리스트
- 필수 학습 · Firestore undefined 오류 해결: 선택 필드가 저장을 막을 때
- 필수 학습 · Firestore arrayUnion 중첩 배열 오류: 배열을 그대로 넘기면 실패하는 이유
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.