일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 프론트엔드 성능 최적화 가이드
- 블로그 서비스 최적화
- unique identifiers
- 학습내용정리
- const
- 새 코드 받아오기
- js pattern
- 딥다이브
- package management
- pr review
- DOM
- 프로그래머스
- 제너레이터와 async/await
- 브라우저의 렌더링 과정
- 올림픽 통계 서비스 최적화
- 커리어
- 스코프
- 자바스크립트 패턴
- 이미지 갤러리 최적화
- middleware pattern
- mixin pattern
- 자바스크립트
- peerdependencies
- version management
- 모던 자바스크립트 Deep Dive
- 진행기록
- Babel과 Webpack
- 이벤트
- 자바스크립트 딥다이브
- js pattern
- Today
- Total
Dev Blog
1일차 셋업/기본 로직 구현 본문
목적: 파이어베이스를 사용해보고 싶었다. 백엔드에 들이는 시간을 아낄 수 있기에 프론트엔드 파트에 집중할 수 있을 것 같다.
컨셉: 유저들이 사진을 공유하고 사진에 대해 대화를 나눌 수 있는 반응형 채팅 웹. 파이어베이스의 소셜로그인과 실시간 데이터베이스 기능을 사용할 계획이다.
Initial Set-up
Set up react environment with necessary dependencies and new Firebase.
Connect App with database and Storage of Firebase.
리액트 개발환경을 세팅했다. 일단, 토이 프로젝트이기 때문에 많은 모듈은 필요하지 않다고 판단하여 styled component 정도만 적용했다.
파이어베이스에 데이터베이스와 스토리지(이미지저장) 을 생성하여 앱과 연결시켰다.
먼저, 파이어베이스 모듈을 설치하고 import 한 후, 생성 및 *초기화 한다.
*초기화: 객체를 선언하고 값을 할당하는 것.
import firebase from "firebase/app";
import "firebase/storage"; //store images
import "firebase/firestore"; //database
import "firebase/auth";
import dotenv from "dotenv";
dotenv.config();
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: process.env.REACT_APP_APIKEY,
authDomain: process.env.REACT_APP_AUTHDOMAIN,
projectId: process.env.REACT_APP_PROJECTID,
storageBucket: process.env.REACT_APP_STORAGEBUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGESENDER,
appId: process.env.REACT_APP_APPID,
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
// firebase.analytics();
const projectStorage = firebase.storage(); //This reference points to the root of Cloud Storage bucket.
const projectFirestore = firebase.firestore();
const timeStamp = firebase.firestore.FieldValue.serverTimestamp;
const projectAuth = firebase.auth();
export { projectStorage, projectFirestore, timeStamp, projectAuth };
Complete Basic Logics
- Upload form
- Firebase storage hook
- Make progress bar
- Firestore hook & showing image
- Create modal for selected image
1) 이미지 storage
이미지 파일을 storage 에 업로드하고, url 을 리턴받아 작성일자와 함께 파이어 데이터베이스에 올린다.
useEffect hooks 를 이용, file(이미지파일)에 변화가 생길때마다 즉, 새 이미지가 업로드될 때마다 데이터베이스에 추가시킨다.
ref() 는 해당 데이터베이스를 참조(바라보는 것)하는 메소드이다.
//useStorage.js
import { useState, useEffect } from "react";
import {
projectStorage,
projectFirestore,
timeStamp,
} from "../firebase/config";
const useStorage = (file) => {
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
const [url, setUrl] = useState(null);
useEffect(() => {
//references : if images is uploaded in default storage, file.name should be used as a name
const storageRef = projectStorage.ref(file.name);
//collection is a container of documents
//document is a unit of storage. It includes key-value objects
const collectionRef = projectFirestore.collection("images");
storageRef.put(file).on(
"state_changed",
(snap) => {
let percentage = (snap.bytesTransferred / snap.totalBytes) * 100;
setProgress(percentage);
},
(err) => {
setError(err);
},
async () => {
const url = await storageRef.getDownloadURL();
const createdAt = timeStamp();
collectionRef.add({ url, createdAt });
setUrl(url);
}
);
}, [file]);
//useEffect callback will be fired if file dependency is changed
return { progress, url, error };
};
export default useStorage;
ProgressBar.js 에서 framer-motion 라이브러리를 이용하여 애니메이션을 만든다.
//ProgressBar.js
import React, { useEffect } from "react";
import useStorage from "../hooks/useStorage";
import styled from "styled-components";
import { motion } from "framer-motion";
const ProgressBar = ({ file, setFile }) => {
const { url, progress } = useStorage(file);
//useStorage(file) returns { progress, url, error };
// console.log(progress, url);
useEffect(() => {
if (url) {
setFile(null);
}
}, [url, setFile]);
return (
<Progress
percentage={progress}
initial={{ width: 0 }}
animate={{ width: progress + "%" }}
>
a
</Progress>
);
};
const Progress = styled(motion.div)`
width: ${(props) => props.percentage + "%"};
background: black;
color: transparent;
`;
export default ProgressBar;
2) firestore
Firebase database(firestore) 해당 collection의 모든 사진들을 가져올 수 있다.
Collection 에 변화가 생길때마다(즉, 다큐먼트들) images 의 최신 데이터를 불러온다.
//useFirestore.js
import { useState, useEffect } from "react";
import { projectFirestore } from "../firebase/config";
const useFiretore = (collection) => {
const [docs, setDocs] = useState([]);
useEffect(() => {
const unsub = projectFirestore
.collection(collection) //collection will be 'images'
.orderBy("createdAt", "desc")
.onSnapshot((snap) => {
//snapshot including all of documents in collection of
//database when there is change in collection.
let documents = [];
snap.forEach((doc) => {
documents.push({ ...doc.data(), id: doc.id });
//doc.data(): all data of a document
});
setDocs(documents);
});
return () => unsub();
}, [collection]);
return { docs };
};
export default useFiretore;
ImageGrid.js 에서 데이터를 받아와 렌더시킨다.
import React from "react";
import useFiretore from "../hooks/useFirestore";
import styled from "styled-components";
import { motion } from "framer-motion";
const ImageGrid = ({ setSelectedImg }) => {
const { docs } = useFiretore("images");
// console.log(docs);
return (
<ImageBox>
{docs &&
docs.map((doc) => (
<ImageWrap
layout
className="img-wrap"
key={doc.id}
onClick={() => setSelectedImg(doc)}
>
<Image
src={doc.url}
alt="uploaded pic"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1 }}
/>
</ImageWrap>
))}
</ImageBox>
);
};
이미지
'Projects > JStargram' 카테고리의 다른 글
4일차 CSS/기능 리팩토링 및 배포 완료 (0) | 2021.04.09 |
---|---|
3일차 파이어베이스 로그인/로그아웃 및 채팅 구현 (0) | 2021.04.09 |
2일차 사진 갤러리 로직 및 CSS 완료 (0) | 2021.04.08 |