๐ŸŒŸ Firebase Storage: ์„ค์ •, ์—…๋กœ๋“œ

summereuna๐Ÿฅยท2022๋…„ 4์›” 12์ผ

๐ŸŒŸ Twinkle (React, Firebase)

๋ชฉ๋ก ๋ณด๊ธฐ
19/42
post-thumbnail

์ด์ œ Firebase Storage์˜ bucket์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•ด๋ณด์ž.
์ด๋ฅผ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

  1. Firebase Storage ์…‹์—…

  2. ํŒŒ์ผ ์œ„์น˜์— ๋Œ€ํ•œ reference ๋งŒ๋“ค๊ธฐ
    ref()

  3. ํŒŒ์ผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ reference๋กœ ์—…๋กœ๋“œํ•˜๊ธฐ
    UploadString(ref, value, format);


ํŠธ์œ—ํ•˜๋Š” ๋ถ€๋ถ„ ์ฃผ์„ ์ฒ˜๋ฆฌ


๊ทธ ์ „์— routers/Home.js์˜ onSubmit ๋ฆฌ์Šค๋„ˆ์—์„œ ํŠธ์œ—(๋‹คํ๋จผํŠธ)์„ ์ปฌ๋ ‰์…˜์— ์ถ”๊ฐ€ํ•˜๋Š” ๋ถ€๋ถ„์„ ์ฃผ์„์ฒ˜๋ฆฌ(์ฃผ์„ ์ฒ˜๋ฆฌ ์›ํ•˜๋Š” ์ฝ”๋“œ ๋ธ”๋ฝ ์„ค์ • ํ›„, Option + Shift + A)ํ•˜์ž.

์‚ฌ์ง„์„ ๋จผ์ € ์—…๋กœ๋“œํ•˜๊ณ ๋‚˜์„œ ํŠธ์œ—์„ ์—…๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ผ๋‹จ ์ฃผ์„ ์ฒ˜๋ฆฌํ•ด ๋‘์ž.

const onSubmit = async (event) => {
  event.preventDefault();
  //ํŠธ์œ—ํ•˜๊ธฐ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กœ์šด document ์ƒ์„ฑํ•˜๊ธฐ
  /* try {
      await addDoc(collection(dbService, "tweets"), {
        //ํŠธ์œ— ์ž‘์„ฑ์ž
        creatorId: userObj.uid,
        text: tweet, //tweet(value๋กœ tweet state ๊ฐ’)
        createdAt: serverTimestamp(), //Date.now(),๋กœ ํ•ด๋„ ๋˜์ง€๋งŒ ์ด์™• ์žˆ๋Š”๊ฑฐ ํ•จ ์จ๋ณด์ž(ํƒ€์ž„์กด ๋™๋ถ์•„3 = ์„œ์šธ๋กœ ์„ค์ •๋˜์–ด ์žˆ์Œ)
      });
      //console.log("Document written with ID: ", docRef.id);
    } catch (error) {
      console.error("Error adding document: ", error);
    }
    //state ๋น„์›Œ์„œ form ๋น„์šฐ๊ธฐ
    setTweet(""); */
};

Firebase Storage ์…‹์—…


๐Ÿ“ fbase.js

//Firebase Web v.9
//์ฐธ๊ณ : https://firebase.google.com/docs/web/modular-upgrade#refactor_to_the_modular_style
//Follow this pattern to import other Firebase services
//import { } from 'firebase/<service>';

//ํŒŒ์ด์–ด๋ฒ ์ด์Šค์—์„œ ์Šคํ† ๋ฆฌ์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ
import { getStorage } from "firebase/storage";

//์Šคํ† ๋ฆฌ์ง€(์‚ฌ์ง„ ์—…๋กœ๋“œ) ๋‚ด๋ณด๋‚ด๊ธฐ
export const storageService = getStorage();

ํŒŒ์ผ ์œ„์น˜์— ๋Œ€ํ•œ reference ๋งŒ๋“ค๊ธฐ


firebase.storage.Reference(๋ ˆํผ๋Ÿฐ์Šค)๋ž€?

  • ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜, ๋‹ค์šด๋กœ๋“œํ•˜๊ฑฐ๋‚˜, ํŒŒ์ผ์„ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜, ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด, ์ž‘์—…ํ•  ํŒŒ์ผ์— ๋Œ€ํ•œ reference๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
    • reference๋Š” ํด๋ผ์šฐ๋“œ์˜ ํŒŒ์ผ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
    • reference๋Š” ๊ฐ€๋ณ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•œ ๋งŒํผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—ฌ๋Ÿฌ ์ž‘์—…์— ์žฌ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

  • ๋ ˆํผ๋Ÿฐ์Šค ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
    • reference๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด getStorage()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํ† ๋ฆฌ์ง€ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ, ์„œ๋น„์Šค๋ฅผ ์ธ์ž๋กœ ์‚ฌ์šฉํ•˜์—ฌ ref()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    • ์ด reference๋Š” ๋‚ด ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€ ๋ฒ„ํ‚ท์˜ ๋ฃจํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค(points).

  • ์˜ˆ์‹œ
//v.9
import { getStorage, ref } from "firebase/storage";
//๋‚ด ์Šคํ† ๋ฆฌ์ง€ ๋ฒ„ํ‚ท์— references๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์Šคํ† ๋ฆฌ์ง€ ์„œ๋น„์Šค์— ๋Œ€ํ•œ reference ๊ฐ€์ ธ์˜ค๊ธฐ
const storage = getStorage();
//
// ๐Ÿ”ฅ ๋‚ด ์Šคํ† ๋ฆฌ์ง€ ์„œ๋น„์Šค์—์„œ ์Šคํ† ๋ฆฌ์ง€ reference ์ƒ์„ฑํ•˜๊ธฐ
const storageRef = ref(storage);
//
// ๐Ÿ”ฅ ํ•˜์œ„ ์ฐธ์กฐ(child references) ์ƒ์„ฑํ•˜๊ธฐ
const imagesRef = ref(storage, 'images');
// imagesRef๋Š” ์ด์ œ 'images'๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
//
// ๐Ÿ”ฅ ํ•˜์œ„ ์ฐธ์กฐ(child references)๋Š” '/'๋กœ ๊ตฌ๋ถ„๋œ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
const spaceRef = ref(storage, 'images/space.jpg');
// spaceRef๋Š” ์ด์ œ "images/space.jpg"๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
// images Ref๋Š” ์—ฌ์ „ํžˆ "images"๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค.

ref()

ref()
: ๊ตฌ๊ธ€ ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€ ์˜ค๋ธŒ์ ํŠธ = bucket์— ๋Œ€ํ•œ ์ฐธ์กฐ(reference)๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
๊ฐœ๋ฐœ์ž๋“ค์€ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์—…๋กœ๋“œ/๋‹ค์šด๋กœ๋“œ/์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์ง„ ํŒŒ์ผ์„ ์ฒจ๋ถ€ํ•˜์—ฌ ์—…๋กœ๋“œํ•˜๋ฉด, ๊ทธ ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ url์„ ๋ฐ›์•„์„œ ํŠธ์œ—์— ๋ฐ์ดํ„ฐ url์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ref()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

const fileRef = ref(storage,`์Šคํ† ๋ฆฌ์ง€์„œ๋น„์Šค์— ์—…๋กœ๋“œ๋  ํŒŒ์ผ์˜ path`);
  1. ์ฐธ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹คํ๋จผํŠธ ์ปฌ๋ ‰์…˜ ๋งŒ๋“ค ๋•Œ๋ž‘ ๋น„์Šทํ•˜๋‹ค. ๋‹คํ๋จผํŠธ ์ด๋ฆ„ ์ •ํ•  ์ˆ˜ ์žˆ์—ˆ๋“ฏ์ด ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋  ํด๋” ์ด๋ฆ„์„ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    (ํ•˜์œ„ ์ฐธ์กฐ(child references)๋Š” '/'๋กœ ๊ตฌ๋ถ„๋œ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.)

    • ํด๋”๋Š” ์œ ์ € ์•„์ด๋””${userObj.uid} ๋ณ„๋กœ ๋งŒ๋“ค๋„๋ก ์„ค์ •ํ•˜์ž.
  2. ๋˜ํ•œ ์ฒจ๋ถ€ํŒŒ์ผ์ด ์—…๋กœ๋“œ ๋  ๋•Œ ์ด๋ฆ„์„ ์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋•Œ ์‹๋ณ„์ž(id)๋ฅผ ๋žœ๋ค์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ํ™œ์šฉํ•˜์ž.

    • npm i uuid๋กœ uuid ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•œ๋‹ค.
    • import { v4 as uuidv4 } from "uuid";๋กœ uuid๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
    • uuid์˜ uuidv4() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ๋ช… ์‹๋ณ„์ž๋ฅผ ๋žœ๋ค์œผ๋กœ ์ƒ์„ฑํ•˜์ž.
      const fileRef = ref(storageService, `${userObj.uid}/${uuidv4()}`);

๐Ÿ“ routes/Home.js

// ์‹๋ณ„์ž ์ž๋™ ์ƒ์„ฑํ•ด์ฃผ๋Š” uuid
import { v4 as uuidv4 } from "uuid";
// storageService ๊ฐ€์ ธ์˜ค๊ธฐ
import { dbService, storageService } from "fbase";
// ref() ๊ฐ€์ ธ์˜ค๊ธฐ
import { ref } from "@firebase/storage";

//

const onSubmit = async (event) => {
  event.preventDefault();
  //file ๋ ˆํผ๋Ÿฐ์Šค ์œ„์น˜ = ํŒŒ์ด์–ด๋ฒ ์ด์Šค ์Šคํ† ๋ฆฌ์ง€ > user๋ณ„ ํด๋” > ์—…๋กœ๋“œํ•  ๋•Œ ๋žœ๋ค์œผ๋กœ ์ƒ์„ฑ๋œ id์‹๋ณ„์ž
  const fileRef = ref(storageService, `${userObj.uid}/${uuidv4()}`);
  
  //
  • ์ด๋ ‡๊ฒŒ file ๋ ˆํผ๋Ÿฐ์Šค ์œ„์น˜๋ฅผ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค.
    ํŒŒ์ด์–ด๋ฒ ์ด์Šค ์Šคํ† ๋ฆฌ์ง€ > user๋ณ„ ํด๋” > ์—…๋กœ๋“œํ•  ๋•Œ ๋žœ๋ค์œผ๋กœ ์ƒ์„ฑ๋œ id์‹๋ณ„์ž

  • ์ด์ œ fileRef๋Š” user๋ณ„ ํด๋”์˜ ๋žœ๋ค id(${userObj.uid}/${uuidv4()})๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

ํŒŒ์ผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ reference๋กœ ์—…๋กœ๋“œํ•˜๊ธฐ


UploadString()

uploadString() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›์‹œ, base64, base64url ๋˜๋Š” data_url ์ธ์ฝ”๋”ฉ๋œ ๋ฌธ์ž์—ด์„ ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€์— ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.

  • uploadString(ref, value, format)
    : ๋ฐ์ดํ„ฐ๋ฅผ reference์˜ ์œ„์น˜์— ์—…๋กœ๋“œํ•˜๋Š” ๋ฉ”์„œ๋“œ
    1. ์ฒซ ๋ฒˆ์งธ ์ธ์ž ref: {@link StorageReference} ์—์„œ ๋ฌธ์ž์—ด(string)์„ ์—…๋กœ๋“œํ•ด์•ผ ํ•œ๋‹ค.
    2. ๋‘ ๋ฒˆ์งธ ์ธ์ž value: ์—…๋กœ๋“œํ•  String
    3. ์„ธ ๋ฒˆ์งธ ์ธ์ž format: ์—…๋กœ๋“œํ•  String ํ˜•์‹

  • ์˜ˆ์‹œ
//v.9
import { getStorage, ref, uploadString } from "firebase/storage";
//
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
//
// Data URL string
const message4 = 'data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message4, 'data_url').then((snapshot) => {
  console.log('Uploaded a data_url string!');
});

์ฐธ๊ณ ํ• ์ˆ˜ ์žˆ๋Š” ์œ„์น˜๋ฅผ ์ƒ์„ฑํ–ˆ์œผ๋‹ˆ, ์ด์ œ uploadString() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์œ„์น˜์— ์ฐ์œผ๋กœ ์—…๋กœ๋“œ ํ•  ์ฐจ๋ก€์ด๋‹ค.

//๋ ˆํผ๋Ÿฐ์Šค(fileRef)๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์œ„์น˜์— ์ฐ์œผ๋กœ ๋ฐ์ดํ„ฐ ์—…๋กœ๋“œํ•˜๊ธฐ
const response = await uploadString(fileRef, attachment, "data_url");
  1. ์ฒซ ๋ฒˆ์งธ ์ธ์žref์—๋Š” ์—…๋กœ๋“œ๋  ํŒŒ์ผ์˜ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” fileRef๋ฅผ ๋„ฃ๋Š”๋‹ค.

  2. ๋‘ ๋ฒˆ์งธ ์ธ์ž value์—๋Š” attachment์— ๋“ค์–ด์žˆ๋Š” url์„ ๋„ฃ๋Š”๋‹ค.

  3. ์„ธ ๋ฒˆ์งธ ์ธ์ž ํฌ๋งทํ˜•์‹์—๋Š” "data_url"๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ“ routes/Home.js

import { v4 as uuidv4 } from "uuid";
import { dbService, storageService } from "fbase";
// uploadString ๊ฐ€์ ธ์˜ค๊ธฐ
import { ref, uploadString } from "@firebase/storage";

//

const onSubmit = async (event) => {
  event.preventDefault();

  //storage์— ํŒŒ์ผ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋กœ๋“œ๋  ์œ„์น˜ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ ˆํผ๋Ÿฐ์Šค ์ƒ์„ฑํ•˜๊ธฐ
  const fileRef = ref(storageService, `${userObj.uid}/${uuidv4()}`);
  
  //๋ ˆํผ๋Ÿฐ์Šค(fileRef)๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์œ„์น˜์— ์ฐ์œผ๋กœ ๋ฐ์ดํ„ฐ ์—…๋กœ๋“œํ•˜๊ธฐ
  //fileRef๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์œ„์น˜์— attachment์— ๋“ค์–ด์žˆ๋Š” ์ฒจ๋ถ€ํŒŒ์ผ url์„ ๋„ฃ์–ด๋ผ, ํฌ๋งทdata_url
  const response = await uploadString(fileRef, attachment, "data_url");
  //๋งˆ์ง€๋ง‰์œผ๋กœ ํŒŒ์ผ์ด ์ž˜ ์—…๋กœ๋“œ ๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฝ˜์†”์— ์ฐ์–ด๋ณด์ž!
  console.log(response);
  
  //

๋ฌธ์ œ ๋ฐœ์ƒ!


  1. ์—…๋กœ๋“œ ํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ permission์ด ์•ˆ๋‚ฌ๋‹ค๊ณ  ์—๋Ÿฌ๊ฐ€ ๋œฌ๋‹ค.

  2. Firebase > Storage > Rules ๊ทœ์น™์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ด ์ฃผ์ž.

  3. ๊ทธ๋Ÿฌ๋ฉด ์ž˜ ๋œ๋‹ค!

  • ์ฝ˜์†”์— ์—…๋กœ๋“œํ•œ ํŒŒ์ผ์„ ์ฐ์–ด๋ณด๋‹ˆ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œฌ๋‹ค.

    ๋ณด๋‹ค์‹œํ”ผ ๋ ˆํผ๋Ÿฐ์Šค์˜ ์œ„์น˜์— ํŠธ์œ™ํด ๋ฒ„์ผ“์ด ๋œจ๊ณ  path๊ฐ€ user์˜ uid/๋žœ๋คid๋กœ ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํŒŒ์ด์–ด๋ฒ ์ด์Šค ์Šคํ† ๋ฆฌ์ง€์—์„œ๋„ ํ™•์ธ ๊ฐ€๋Šฅ!

    • (๋ฌผ๋ก  ํŒŒ์ผ ์‚ญ์ œํ•˜๊ณ  ๋‹ค์‹œ ๋งŒ๋“ค๊ณ  ํ…Œ์ŠคํŠธ ํ•˜๋А๋ผ ํŒŒ์ผ๋ช…์€ ๋‹ค๋ฆ„ ^ใ…‡^;)
profile
Always have hope๐Ÿ€ & constant passion๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€