React/Firebase

Firebase v9 + React 로 CRUD

또롱또 2022. 5. 28. 03:31
728x90

Firebase는 platform provided by google.

코드에 주석으로 뭐하는 코드인지 메모를 조금 해뒀다.

사진이 안보이면 클릭하면 커진다.

참고하면 좋은 자료들

1. https://travis.media/how-to-use-firebase-with-react/#20211130-getDoc

2. 파이어베이스 documents

3. https://www.youtube.com/watch?v=9zdvmgGsww0&list=PL4cUxeGkcC9jERUGvbudErNCeSZHWUVlb

 

 

1. 리액트 설치

yarn create react-app .

 

 

2. Firebase 추가

yarn add firebase

 

 

3. 아래로 이동해서 로그인까지한다.

https://console.firebase.google.com/u/0/

 

 

4. 프로젝트 추가 하면 플젝 이름정하고 하는데

뭐 건들지 말고 다 그냥 default 로 넘어가자.

 

5.톱니바퀴 -> 프로젝트 설정

 

6. 빨간동그라미 클릭해서 웹 추가 페이지로 간다 

등록할때 호스팅 버튼은 누르지 말자. 궁금하면 구글링하는것도 좋겠다.

 

7. vscode에 firebase-config.js 생성 한후에,

아까 웹 추가하고 나온 페이지에서 아래 빨간부분 복붙.

 

8. 데이터 베이스를 만든다.

웹 추가 페이지에서 콘솔로이동 한 후, 아래 사진에 있는 1, 2번 버튼만 클릭하면된다.

프로덕션모드에서 시작, 클라우드위치(한국살면 asia하면된다) 를 고른다.

 

9. DB규칙을 바꾼다 -> read write가 초기값은 false인데 true로 수정하고 게시한다.

 

10. DB생성 화면에 있는 번호 순서대로 클릭하고 입력한다.

 

 

11. firebase-config.js에 꺼내쓴다는 변수 생성.

firebaseConfig는 각자꺼 쓰고 나머진 복붙.

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import {getFirestore} from "@firebase/firestore"

// 파이어스토어에 접근할수 있게해주는 ID 등등 - 로그인해야지 준다
const firebaseConfig = {
    apiKey: "aas6nquiMi_BNRvbQ3pytdYVUNU",
    authDomain: "fir-study-2c509.firebaseapp.com",
    projectId: "fir-study-2c509",
    storageBucket: "fir-study-2c509.appspot.com",
    messagingSenderId: "31231445033",
    appId: "1:307451445033:web:de010b795d33e57bff4138",
    measurementId: "G-N2SH1342EJ7"
  };

  const app = initializeApp(firebaseConfig)

  export const db = getFirestore(app);

 

 

12. db 연동되었나 체크하기 - App.js

import { useState, useEffect } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 접근해서 데이터를 꺼내게 도와줄 친구들
import { collection, getDocs } from "firebase/firestore";

function App() {
 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

   // 시작될때 한번만 실행
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      console.log(data);
    }

    getUsers();
  },[])
  return (
    <div className="App">
      
    </div>
  );
}

export default App;

 

13. 콘솔창  확인 -> DB에서 데이터를 꺼내와야한다.

docs(....) 라고 되있으면 ....을 클릭하면 열린다.

 

14. CRUD의 R을 해줄 예정. 데이터를 한번 꺼내서 화면에 띄워보자 

App.js

더보기
import { useState, useEffect, useId } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 접근해서 데이터를 꺼내게 도와줄 친구들
import { collection, getDocs } from "firebase/firestore";

function App() {
 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

  // 유니크 id를 만들기 위한 useId(); - react 18 기능으로, 이 훅을 이렇게 사용하는게 맞고 틀린지는 모른다.
  const uniqueId = useId();
  console.log(uniqueId)

   // 시작될때 한번만 실행
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      // users에 data안의 자료 추가. 객체에 id 덮어씌우는거
      setUsers(data.docs.map((doc)=>({ ...doc.data(), id: doc.id})))
    }

    getUsers();
  },[])

  // 띄워줄 데이터 key값에 고유ID를 넣어준다.
  const showUsers = users.map((value)=> (<div key={uniqueId}> 
                                            <h1>Name: {value.name}</h1> 
                                            <h1>Age: {value.age}</h1> 
                                        </div>))
  return (
    <div className="App">
        {showUsers}
    </div>
  );
}

export default App;

 

15. DB 구조를 잘 기억하자 

만약 새로운 사람이 등록되면 어디에 추가되야하는가? 정답: 가운데 문서

 

 

16. CRUD중의 C를 해볼 예정 input과 button을 만들어보자,

- 일단 input과 button에 값이 잘 들어오는지 확인

App.js

더보기
import { useState, useEffect, useId } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 접근해서 데이터를 꺼내게 도와줄 친구들
import { collection, getDocs } from "firebase/firestore";

function App() {
  // input으로 받을 새로운 사람의 이름과 나이
  const [newName, setNewName] = useState("");
  const [newAge, setNewAge] = useState(0);

  console.log(newName, newAge);

 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

  // 유니크 id를 만들기 위한 useId(); - react 18 기능으로, 이 훅을 이렇게 사용하는게 맞고 틀린지는 모른다.
  const uniqueId = useId();
  //console.log(uniqueId)

   // 시작될때 한번만 실행
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      // users에 data안의 자료 추가. 객체에 id 덮어씌우는거
      setUsers(data.docs.map((doc)=>({ ...doc.data(), id: doc.id})))
    }

    getUsers();
  },[])

  const createUsers = () =>{

  }

  // 띄워줄 데이터 key값에 고유ID를 넣어준다.
  const showUsers = users.map((value)=> (<div key={uniqueId}> 
                                            <h1>Name: {value.name}</h1> 
                                            <h1>Age: {value.age}</h1> 
                                        </div>))
  return (
    <div className="App">
      {/* onchange를 이용해서, 변하는 값을 state로 저장한다. */}
      <input type="text" placeholder='name...' onChange={(event)=> {setNewName(event.target.value)}}/>
      <input type="number" placeholder='age...' onChange={(event)=> {setNewAge(event.target.value)}}/>
      <button onClick={createUsers}>Create User</button>
        {showUsers}
    </div>
  );
}

export default App;

 

17. addDoc을 이용해서 DB로 값 보내기

더보기
import { useState, useEffect, useId } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 데이터에 접근을 도와줄 친구들
import { collection, getDocs, addDoc } from "firebase/firestore";

function App() {
  // input으로 받을 새로운 사람의 이름과 나이
  const [newName, setNewName] = useState("");
  const [newAge, setNewAge] = useState(0);

  console.log(newName, newAge);

 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

  // 유니크 id를 만들기 위한 useId(); - react 18 기능으로, 이 훅을 이렇게 사용하는게 맞고 틀린지는 모른다.
  const uniqueId = useId();
  //console.log(uniqueId)

   // 시작될때 한번만 실행
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      // users에 data안의 자료 추가. 객체에 id 덮어씌우는거
      setUsers(data.docs.map((doc)=>({ ...doc.data(), id: doc.id})))
    }

    getUsers();
  },[])

  const createUsers = async () =>{
    // addDoc을 이용해서 내가 원하는 collection에 내가 원하는 key로 값을 추가한다.
    await addDoc(usersCollectionRef, {name: newName, age:newAge});
  }

  // 띄워줄 데이터 key값에 고유ID를 넣어준다.
  const showUsers = users.map((value)=> (<div key={uniqueId}> 
                                            <h1>Name: {value.name}</h1> 
                                            <h1>Age: {value.age}</h1> 
                                        </div>))
  return (
    <div className="App">
      {/* onchange를 이용해서, 변하는 값을 state로 저장한다. */}
      <input type="text" placeholder='name...' onChange={(event)=> {setNewName(event.target.value)}}/>
      <input type="number" placeholder='age...' onChange={(event)=> {setNewAge(event.target.value)}}/>
      <button onClick={createUsers}>Create User</button>
        {showUsers}
    </div>
  );
}

export default App;

페이지 새로고침하면 나온다.

 

18. CRUD의 U를 해볼 예정.

각 이름과 나이 정보아래에 버튼을 하나 주고, 버튼을 누르면 나이가 증가되게 해볼예정

처음에 생성할때 작성한 age가 문자열로 들어가있다.그래서 추가를 누를경우 아래 사진처럼 문자열뒤에 숫자가 붙는다.

그래서 createUsers() 만들때 Number()로 형변환을 해 주었다.

자세한건 소스코드를 보면 알수 있다.

더보기

 

import { useState, useEffect, useId } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 데이터에 접근을 도와줄 친구들
import { collection, getDocs, addDoc, updateDoc, doc } from "firebase/firestore";

function App() {
  // input으로 받을 새로운 사람의 이름과 나이
  const [newName, setNewName] = useState("");
  const [newAge, setNewAge] = useState(0);

  console.log(newName, newAge);

 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

  // 유니크 id를 만들기 위한 useId(); - react 18 기능으로, 이 훅을 이렇게 사용하는게 맞고 틀린지는 모른다.
  const uniqueId = useId();
  //console.log(uniqueId)

   // 시작될때 한번만 실행 // 읽어오기 - R
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      // users에 data안의 자료 추가. 객체에 id 덮어씌우는거
      setUsers(data.docs.map((doc)=>({ ...doc.data(), id: doc.id})))
    }

    getUsers();
  },[])

  // 생성 - C
  const createUsers = async () =>{
    // addDoc을 이용해서 내가 원하는 collection에 내가 원하는 key로 값을 추가한다.
    await addDoc(usersCollectionRef, {name: newName, age:Number(newAge)});
  }

  // 업데이트 - U
  const updateUser = async( id, age) =>{
    // 내가 업데이트 하고자 하는 db의 컬렉션의 id를 뒤지면서 내가 수정하고자 하는 id랑 같은 id값을 가진 데이터를 찾는다
    const userDoc = doc(db, "users", id)
    // 내가 업데이트 하고자 하는 key를 어떻게 업데이트할지 준비,, 중요한점이 db에는 문자열로 저장되어있다. 그래서 createUsers()함수안에서 age를 생성할때 숫자열로 형변환 해줘야한다
    const newField = {age: age + 1};
    // updateDoc()을 이용해서 업데이트
    await updateDoc(userDoc, newField);
  }

  // 띄워줄 데이터 key값에 고유ID를 넣어준다.
  const showUsers = users.map((value)=> (<div key={uniqueId}> 
                                            <h1>Name: {value.name}</h1> 
                                            <h1>Age: {value.age}</h1> 
                                            {/* 증가버튼은 이 안에 있어야지, 각기 다른 데이터마다 붙는다, users data를 map으로 돌기때문에, 그 안의 id랑 age를 넣어주면 된다.*/}
                                            {/* id를 넣어주는 이유는, 우리가 수정하고자 하는 데이터를 찾아야하기 때문에. */}
                                            <button onClick={()=>{updateUser(value.id, value.age)}}>Increase Age</button>
                                        </div>))
  return (
    <div className="App">
      {/* onchange를 이용해서, 변하는 값을 state로 저장한다. */}
      <input type="text" placeholder='name...' onChange={(event)=> {setNewName(event.target.value)}}/>
      <input type="number" placeholder='age...' onChange={(event)=> {setNewAge(event.target.value)}}/>
      <button onClick={createUsers}>Create User</button>
        {showUsers}
    </div>
  );
}

export default App;

 

19. CRUD의 마지막 D를 해볼 예정. 

업데이트랑 동일한 방법으로 id값 찾아서 지운다.

더보기
import { useState, useEffect, useId } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 데이터에 접근을 도와줄 친구들
import { collection, getDocs, addDoc, updateDoc, doc, deleteDoc } from "firebase/firestore";
import { async } from '@firebase/util';

function App() {
  // input으로 받을 새로운 사람의 이름과 나이
  const [newName, setNewName] = useState("");
  const [newAge, setNewAge] = useState(0);

  console.log(newName, newAge);

 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

  // 유니크 id를 만들기 위한 useId(); - react 18 기능으로, 이 훅을 이렇게 사용하는게 맞고 틀린지는 모른다.
  const uniqueId = useId();
  //console.log(uniqueId)

   // 시작될때 한번만 실행 // 읽어오기 - R
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      // users에 data안의 자료 추가. 객체에 id 덮어씌우는거
      setUsers(data.docs.map((doc)=>({ ...doc.data(), id: doc.id})))
    }

    getUsers();
  },[])

  // 생성 - C
  const createUsers = async () =>{
    // addDoc을 이용해서 내가 원하는 collection에 내가 원하는 key로 값을 추가한다.
    await addDoc(usersCollectionRef, {name: newName, age:Number(newAge)});
  }

  // 업데이트 - U
  const updateUser = async( id, age) =>{
    // 내가 업데이트 하고자 하는 db의 컬렉션의 id를 뒤지면서 데이터를 찾는다
    const userDoc = doc(db, "users", id)
    // 내가 업데이트 하고자 하는 key를 어떻게 업데이트할지 준비,, 중요한점이 db에는 문자열로 저장되어있다. 그래서 createUsers()함수안에서 age를 생성할때 숫자열로 형변환 해줘야한다
    const newField = {age: age + 1};
    // updateDoc()을 이용해서 업데이트
    await updateDoc(userDoc, newField);
  }

  // 삭제 - D
  const deleteUser = async(id) =>{
    // 내가 삭제하고자 하는 db의 컬렉션의 id를 뒤지면서 데이터를 찾는다
    const userDoc = doc(db, "users", id);
    // deleteDoc을 이용해서 삭제
    await deleteDoc(userDoc);
  }

  // 띄워줄 데이터 key값에 고유ID를 넣어준다.
  const showUsers = users.map((value)=> (<div key={uniqueId}> 
                                            <h1>Name: {value.name}</h1> 
                                            <h1>Age: {value.age}</h1> 
                                            {/* 증가버튼은 이 안에 있어야지, 각기 다른 데이터마다 붙는다, users data를 map으로 돌기때문에, 그 안의 id랑 age를 넣어주면 된다.*/}
                                            {/* id를 넣어주는 이유는, 우리가 수정하고자 하는 데이터를 찾아야하기 때문에. */}
                                            <button onClick={()=>{updateUser(value.id, value.age)}}>Increase Age</button>
                                            <button onClick={()=>{deleteUser(value.id)}}>Delete User</button>
                                        </div>))
  return (
    <div className="App">
      {/* onchange를 이용해서, 변하는 값을 state로 저장한다. */}
      <input type="text" placeholder='name...' onChange={(event)=> {setNewName(event.target.value)}}/>
      <input type="number" placeholder='age...' onChange={(event)=> {setNewAge(event.target.value)}}/>
      <button onClick={createUsers}>Create User</button>
        {showUsers}
    </div>
  );
}

export default App;

 

20. CRUD때마다 화면을 다시 그리기

화면을 rerendering 하는 방법은 세가지만 기억하자, state, props, updateForce().

그중에 가장 만만한 state 로 해보겠다.

마지막 이 코드만 복붙하면 지금까지 한 내용이 다 들어있다.

주석확인만 잘 하면 될듯하다.

더보기
import { useState, useEffect, useId } from 'react';
import './App.css';
// 파이어베이서 파일에서 import 해온 db
import {db} from './firebase-config'
// db에 데이터에 접근을 도와줄 친구들
import { collection, getDocs, addDoc, updateDoc, doc, deleteDoc } from "firebase/firestore";
import { async } from '@firebase/util';

function App() {
  // input으로 받을 새로운 사람의 이름과 나이
  const [newName, setNewName] = useState("");
  const [newAge, setNewAge] = useState(0);
  
  // changed를 true로 바꿔주면 되지않을까?
  const [changed, setChanged] = useState(false);

  console.log(newName, newAge);

 // 이따가 users 추가하고 삭제하는거 진행을 도와줄 state
  const [users, setUsers] = useState([]);
  // db의 users 컬렉션을 가져옴
  const usersCollectionRef = collection(db, "users");

  // 유니크 id를 만들기 위한 useId(); - react 18 기능으로, 이 훅을 이렇게 사용하는게 맞고 틀린지는 모른다.
  const uniqueId = useId();
  //console.log(uniqueId)

   // 시작될때 한번만 실행 // 읽어오기 - R
  useEffect(()=>{
  	// 비동기로 데이터 받을준비
    const getUsers = async () => {
     // getDocs로 컬렉션안에 데이터 가져오기
      const data = await getDocs(usersCollectionRef);
      // users에 data안의 자료 추가. 객체에 id 덮어씌우는거
      setUsers(data.docs.map((doc)=>({ ...doc.data(), id: doc.id})))
    }

    getUsers();
    // 뭐든 동작할때마다 changed가 true값으로 변경되니까 화면을 그리고 다시 false로 돌려줘야지 다시 써먹는다.
    setChanged(false)
  },[changed]) // 처음에 한번 그리고, changed가 불릴때마다 화면을 다시 그릴거다

  // 생성 - C
  const createUsers = async () =>{
    // addDoc을 이용해서 내가 원하는 collection에 내가 원하는 key로 값을 추가한다.
    await addDoc(usersCollectionRef, {name: newName, age:Number(newAge)});
    // 화면 업데이트를 위한 state 변경
    setChanged(true)
  }

  // 업데이트 - U
  const updateUser = async( id, age) =>{
    // 내가 업데이트 하고자 하는 db의 컬렉션의 id를 뒤지면서 데이터를 찾는다
    const userDoc = doc(db, "users", id)
    // 내가 업데이트 하고자 하는 key를 어떻게 업데이트할지 준비,, 중요한점이 db에는 문자열로 저장되어있다. 그래서 createUsers()함수안에서 age를 생성할때 숫자열로 형변환 해줘야한다
    const newField = {age: age + 1};
    // updateDoc()을 이용해서 업데이트
    await updateDoc(userDoc, newField);
    // 화면 업데이트를 위한 state 변경
    setChanged(true)
  }

  // 삭제 - D
  const deleteUser = async(id) =>{
    // 내가 삭제하고자 하는 db의 컬렉션의 id를 뒤지면서 데이터를 찾는다
    const userDoc = doc(db, "users", id);
    // deleteDoc을 이용해서 삭제
    await deleteDoc(userDoc);
    // 화면 업데이트를 위한 state 변경
    setChanged(true)
  }

  // 띄워줄 데이터 key값에 고유ID를 넣어준다.
  const showUsers = users.map((value)=> (<div key={uniqueId}> 
                                            <h1>Name: {value.name}</h1> 
                                            <h1>Age: {value.age}</h1> 
                                            {/* 증가버튼은 이 안에 있어야지, 각기 다른 데이터마다 붙는다, users data를 map으로 돌기때문에, 그 안의 id랑 age를 넣어주면 된다.*/}
                                            {/* id를 넣어주는 이유는, 우리가 수정하고자 하는 데이터를 찾아야하기 때문에. */}
                                            <button onClick={()=>{updateUser(value.id, value.age)}}>Increase Age</button>
                                            <button onClick={()=>{deleteUser(value.id)}}>Delete User</button>
                                        </div>))
  return (
    <div className="App">
      {/* onchange를 이용해서, 변하는 값을 state로 저장한다. */}
      <input type="text" placeholder='name...' onChange={(event)=> {setNewName(event.target.value)}}/>
      <input type="number" placeholder='age...' onChange={(event)=> {setNewAge(event.target.value)}}/>
      <button onClick={createUsers}>Create User</button>
        {showUsers}
    </div>
  );
}

export default App;

728x90