1. 초기 셋팅
* 콘솔
- 파이어베이스 콘솔에서 storage를 시작하자.
- 아래와 같이 파일을 저장하는 버킷이 생성되면 끝이다.
* 코드
- 셋팅을 위해 만들어 둔 fbase.js 파일에 storage를 추가한다.
// fbase.js
// ...
import "firebase/storage"
const firebaseConfig = {
// ...
};
firebase.initializeApp(firebaseConfig);
// ...
export const storageService = firebase.storage();
- firebase.storage() 를 storageService라는 변수로 export 해주었다.
2. 첨부
* 파일 첨부
- 위처럼 파일선택을 하고, 파일명을 띄우고, 미리보기 사진을 띄워보자.
// Home.js
import React, { useState, useEffect } from 'react';
import { dbService, storageService } from 'fbase';
// ...
const Home = ({ userObj }) => {
// ...
const [attachment, setAttachment] = useState()
const [file, setFile] = useState('')
const onFileChange = (event) => {
const {target:{files, value}} = event;
const theFile = files[0];
const reader = new FileReader();
setFile(value)
reader.onloadend = (finishedEvent) => {
const { currentTarget: {result}} = finishedEvent
setAttachment(result)
}
reader.readAsDataURL(theFile);
}
const onClearAttachment = () => {
setAttachment(null)
setFile('')
};
return (
<div>
<form onSubmit={onSubmit}>
<input value={nweet} onChange={onChange} type="text" placeholder="게시글을 써주세요." maxLength={120} />
<input type="file" accept="image/*" onChange={onFileChange} value={file}/>
<input type="submit" value="제출하기" />
{attachment && (
<div>
<img src={attachment} width="50px" height="50px" alt="attachment"/>
<button onClick={onClearAttachment}>Clear</button>
</div>
)}
</form>
<div>
...
</div>
</div>
);
};
export default Home;
- input type="file" 을 이용하여 파일을 첨부받을 수 있다.
- file 이라는 state는 파일명을 담을 상태이고, attachment는 파일 자체를 의미하는 state이다.
- onChange 속성으로 함수를 주었다. 이 때, event.target 내에 files 는 파일 자체를 갖고 있다. value는 파일명을 갖게 된다.
- 그러므로 value는 file state에 넘겨주었다.
- 파일 자체를 어떻게 관리하느냐가 문제이다. 이 때 사용할 것이 자바스크립트의 fileReader API이다. FileReader 인스턴스를 사용하여 파일을 읽는 객체를 만들었다.
- onloadend 를 통해 파일 읽는것이 끝나는 리스너를 만들어 주었다. 이 때 생기는 이벤트 객체의 currentTarget 내의 result에 파일이 복잡한 텍스트로 변경된 값이 저장되어 있다.
- 파일을 읽으려면 readAsDataURL 메서드를 사용한다. 완전히 읽어져서 담기면 onloadend 메서드가 실행된다.
- 이렇게 만들어진 결과를 attachment state에 담는다. 이를 브라우저 주소창에 입력해보면 브라우저는 텍스트를 해석해 사진을 보여준다.
- 다시 return을 보면 attachment가 있을 때 src에 넣어 보여주도록 하였다. 삭제 버튼도 만들어두었다.
* 첨부 제거
- 위의 첨부파일을 제거하려면 제거버튼을 누르면 되도록 설계해두었다.
- 버튼 onClick에 넣어둔 onClearAttachment를 살펴보자.
// ...
const onClearAttachment = () => {
setAttachment(null)
setFile('')
};
// ...
- Clear버튼을 누르면 attachment와 file 을 비우도록 하였다.
3. 업로드
- 이제 파이어베이스의 storage에 파일을 업로드 해보자.
// Home.js
import React, { useState, useEffect } from 'react';
import { v4 as uuidv4 } from "uuid"
import { dbService, storageService } from 'fbase';
import Post from 'components/Post'
// ...
const onSubmit = async (event) => {
event.preventDefault();
let attachmentUrl = "";
if (attachment !== "") {
const attachmentRef = storageService.ref().child(`${userObj.uid}/${uuidv4()}`);
const response = await attachmentRef.putString(attachment, "data_url")
attachmentUrl = await response.ref.getDownloadURL()
}
const postObj = {
text: post,
createdAt: Date.now(),
creatorId: userObj.uid,
attachmentUrl,
}
await dbService.collection("posts").add(postObj);
setNweet('');
setAttachment('');
setFile('')
};
- 지난 장에서 만든 onSubmit함수에 파일을 업로드 하는 로직이 추가되었다.
- 파일명을 랜덤으로 만들기 위해서 uuidv4 를 사용하였다.
- 사진의 url 정보를 담을 attachmentUrl을 먼저 선언한다. attchment 가 있는지 확인하고 없으면 빈 url을 객체에 넣어서 db에 전달할 것이다.
- 만약 attachment 가 있다면, storage의 버킷에 넣어준다.
- 먼저 storageService.ref()의 child 메서드를 이용해서 이미지의 경로를 만들어 준다. 유저의 id를 폴더로 하는 path를 만들어 주었다.
- put 메서드를 사용할 수 있다. putString으로 문자열을 전달할 수 있는데, 두 번째 인자로는 format을 입력해야한다. 이렇게하면 버킷에 저장된 것을 확인할 수 있다.
- 이제 필요한 것은 저장된 이미지의 url이다. 이 url을 img태그에 넣어야 이미지가 보일 것이기 때문이다.
- putString이 일어나고 나면 응답을 주는데, 이 응답에서 ref속성에 getDownloadURL 메서드를 사용하면 그 링크를 받아올 수 있다.
- 이제 그 링크를 객체에 넣고, 객체는 파이어베이스 컬렉션에 넣는다. 그리고 Post 컴포넌트에 랜더링하면 끝이다.
4. 삭제
- 삭제는 Post.js 컴포넌트에서 확인해보자. 지난 장에서 만들었던 삭제 함수에 조금 더 추가만 하면 된다.
// Post.js
import { dbService, storageService } from 'fbase';
import React, { useState } from 'react';
const Post = ({ postObj, isOwner }) => {
// ...
const onDeleteClick = async () => {
const ok = window.confirm("삭제하시겠습니까?");
console.log(ok)
if (ok) {
await dbService.doc(`posts/${postObj.id}`).delete();
await storageService.refFromURL(postObj.attachmentUrl).delete();
}
}
// ...
- 먼저 storageService를 import하였다.
- 삭제를 하려면 당연히 버킷내의 파일의 경로를 알아야한다. 하지만 이 경로를 따로 객체에 저장해주지 않았기때문에 번거로울 수 있다.
- 그러나 다행히 경로를 찾아주는 메서드를 파이어베이스에서 지원한다. refFromURL메서드를 사용하여 파일의 url을 넣어주면 storage내의 경로를 알려준다. 이를 delete메서드로 지워주기만하면 된다.
참고
'Server > Firebase' 카테고리의 다른 글
<파이어베이스> 프로필 수정 (0) | 2021.07.18 |
---|---|
<파이어베이스> 필터와 정렬 (0) | 2021.07.18 |
<파이어베이스> 게시글 CRUD (0) | 2021.07.15 |
<파이어베이스> 로그인과 로그아웃 (0) | 2021.07.14 |
<파이어베이스> 파이어베이스와 리액트 준비 (0) | 2021.07.11 |