오늘은 Firebase 서비스를 이용하여 게시판을 구현해보도록 하겠습니다.
우선 Firebase 서비스를 이용하기 위한 초기 세팅은 아래 링크를 참고바랍니다.
아래 명령어를 터미널에 입력하여 install합니다.
npm install firebase
firebase.js파일을 생성하여 Firebase의 프로젝트 설정
메뉴에서 발급받은 코드를 그대로 복사합니다.
발급 받은 key가 유출되면 안되니 모두 env파일에 저장했습니다.
env 파일은 위와 같이 최상위 경로에 있어야 하며 반드시 작명은 REACT_APP_
으로 시작하여야 하고 공백을 허용하지 않습니다. (변수명과 값 사이의 =
양쪽에 띄어쓰기 금지)
위 이미지는 잘못된 예시입니다. (이거 때문에 한참 오류가...)
위와 같이 getFirestore
를 import하고 이를 이용해 db
객체를 생성하여 export
하는 구문을 추가해줍니다.
우선 import할 목록의 설명이 필요하겠죠?
new Date()
을 이용해 시간을 저장해도 상관없습니다.query
, orderBy
를 이용하여 쿼리 정렬할 때에 Firestore에서 보다 정밀하고 안전한 작업을 도와줍니다.위 기능들을 이용하면 Firestore를 이용해 게시판의 조회, 추가, 삭제 기능을 구현할 수 있습니다.
데이터 추가를 위한 코드는 위 코드가 전부입니다.
쓰는법 찾아서 작성할때는 엄청 힘들었는데 몇 줄 되지도 않네요. ㅎㅎ
handleSubmit
은 게시글 작성을 위한 form
의 onSubmit
에 등록된 함수입니다. 작성 완료
버튼을 누를때 DB에 데이터를 추가하겠다는 뜻이겠죠?
collection()
함수는 매개변수로 Firestore 객체와 collection의 이름을 받아 저장할 위치를 반환합니다.
addDoc()
함수에는 매개변수로 저장 위치(collection)과 저장할 데이터가 들어갑니다.
저장 위치에 collection(db, "board")
함수를 이용해 값을 반환하여 넣어주고
저장할 값은 key-value 형식으로 값을 넣어줍니다. value에는 form으로 작성된 값이 들어갔습니다.
setFormData(initForm)
와 fetchData()
는 제가 임의로 만든 함수이니 신경쓰지 않으셔도 됩니다.
(같은 페이지 내에서 글작성과 글목록이 다 보여지는 형태라서 form과 글목록을 초기화하는 함수입니다.)
데이터를 가져오는 코드입니다.
글 목록을 렌더링할때 board
state를 이용합니다.
데이터를 가져와서 해당 state에 할당하였습니다.
getDoc()
함수에는 매개변수로 저장 위치(collection)가 들어갑니다.
위 코드는 시간순으로 정렬하기 위해 query
를 이용하였는데 정렬이 필요없다면
await getDocs(collection(db, "board"));
이것만 작성하시면 됩니다.
가져온 데이터를 querySnapshot
에 할당하였습니다.
데이터의 추가 작업이 필요하므로 forEach
문을 이용하였습니다.
var data = doc.data()
: doc
에는 key-value
의 값만 들어있는 것이 아니라 많은 정보가 포함되어있습니다. key-value
의 데이터는 .data()
를 이용하여 추출 가능합니다.
저장된 시간은 밀리초로 저장되므로 문자로 변환하였습니다.
저장된 document의 파일명은 doc.id
에 담겨있습니다.
※ data.id
가 아닙니다. 데이터의 key중 id가 있는경우가 많아 헷갈릴 수 있으니 유의합시다.
나중에 데이터를 삭제하기 위해서 파일명이 필요하니 따로 저장했습니다.
이렇게 데이터를 가져오는 작업을 fetchData()
라는 함수로 묶어 처음 렌더링할 때 useEffect()을 이용해 실행하고 목록 초기화가 필요할 때 사용합니다.
삭제는 아주 간단합니다.
deleteDoc(doc(db, collection명, document명));
형태로 작성해주면 됩니다.
위에서 doc.id
을 이용해 저장한 파일명을 이용합니다.
위 코드는 게시글 하나 단위로 component를 생성하기에 props로 doc.id
를 넘겨주었습니다.
위와 같이 getStorage
를 import하고 이를 이용해 storage
객체를 생성하여 export
하는 구문을 추가해줍니다.
ref(storage, 파일명)
형식으로 사용하며 아래 함수 모두 이를 이용합니다.사용자가 사진을 업로드하면 uploadBytes
을 이용해 Storage에 추가할 수 있습니다.
나중에 파일명으로 getDownloadURL
을 사용하여 이미지를 나타내는 방법도 있으나
게시글에 대한 내용이 Firestore에 저장되어 있는 상황에서 게시글을 출력할 때 Firestore에서 내용을 가져오고 getDownloadURL
을 이용해서 이미지를 출력하는것 보다
Firestore에 미리 이미지의 URL을 저장해두는 방식이 편리하겠죠?
imgURL은 Firestore에 저장할 때(addDoc)도 사용하기 위해 상단에 빼두었고 사용자가 이미지를 업로드하지 않았을 때에 기본 이미지를 출력하기 위해 `${process.env.PUBLIC_URL}/images/board/default.png
를 사용하였습니다.
form에 등록된 파일은 imgFile
에 담기며 등록된 이미지가 있는 경우
파일명(imgName)을 현재 시간으로 저장했습니다. (파일명이 겹치지 않기 위함입니다.)
uploadBytes(ref, 파일)
을 사용하여 이미지를 업로드할 수 있고
.then
을 이용해 업로드된 파일에 대한 정보를 얻을 수 있습니다.
.then
에서 getDownloadURL()
을 이용하여 업로드한 파일의 경로를 얻어서 imgURL
에 저장합니다.
※ getDownloadURL()
도 역시 getDownloadURL(ref(~~))
형식으로도 사용 가능합니다. 여기선 업로드된 정보를 바로 얻어올 수 있어서 위 코드처럼 사용하였습니다.
이미지 파일이 업로드 된 후에 Firestore에 저장해야 하기 때문에 .then
으로 위에서 만든 addDocument()
을 사용하였습니다.
addDocument()
에 업로드한 사진의 URL과 파일명이 추가된 모습입니다.
업로드한 사진이 있는 경우 uploadImg()
을 실행하며 없는 경우 addDocument()
을 실행합니다.
(uploadImg()에 .then으로 addDocument()을 연결하였으므로 uploadImg() 실행 시 내부에서 addDocument()도 실행됩니다.)
삭제는 역시 간단합니다.
위에서 업로드한 파일이 없는 경우 imgName
을 null로 저장하였기 때문에
imgName
을 이용해 조건문을 만들어서 파일을 삭제하는 구문을 추가합니다.