Back-end/Firebase

[노마드코더] #6 Finishing Up

성중 2022. 4. 10. 16:31

Cleaning JS

Home과 Auth 페이지를 리팩토링해보자

 

[src/components/PostFactory.js]

import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { storageService, dbService } from "fbase";

const PostFactory = (props) => {
  const [post, setPost] = useState("");
  const [attachment, setAttachment] = useState(null);
  const onSubmit = async (event) => {
    event.preventDefault();
    let attachmentUrl = "";
    if (attachment !== null) {
      const attachmentRef = storageService
        .ref()
        .child(`${props.userObj.uid}/${uuidv4()}`);
      const response = await attachmentRef.putString(attachment, "data_url");
      attachmentUrl = await response.ref.getDownloadURL();
    }
    const postObj = {
      text: post,
      createdAt: Date.now(),
      creatorId: props.userObj.uid,
      attachmentUrl,
    };
    await dbService.collection("posts").add(postObj);
    setPost("");
    setAttachment(null);
  };
  const onChange = (event) => {
    const {
      target: { value },
    } = event;
    setPost(value);
  };
  const onFileChange = (event) => {
    const {
      target: { files },
    } = event;
    const theFile = files[0];
    const reader = new FileReader();
    // 파일이 읽어지면 실행
    reader.onloadend = (finishedEvent) => {
      const {
        currentTarget: { result },
      } = finishedEvent;
      setAttachment(result);
    };
    reader.readAsDataURL(theFile); // 파일을 읽기 시작
  };
  const onClearAttachment = () => setAttachment(null);
  return (
    <form onSubmit={onSubmit}>
      <input
        value={post}
        onChange={onChange}
        type="text"
        placeholder="What's on your mind?"
        maxLength={120}
      />
      <input type="file" accept="image/*" onChange={onFileChange} />
      <input type="submit" value="Post" />
      {attachment && (
        <div>
          <img src={attachment} alt="preview" width="50px" height="50px" />
          <button onClick={onClearAttachment}>Clear</button>
        </div>
      )}
    </form>
  );
};

export default PostFactory;

Home.js에서 Post 생성 기능을 PostFactory 컴포넌트로 분리

 

[src/components/AuthForm.js]

import React, { useState } from "react";
import { authService } from "fbase";

const AuthForm = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  // 회원가입과 로그인을 하나의 form으로 관리
  const [newAccount, setNewAccount] = useState(true);
  const [error, setError] = useState("");
  const onChange = (event) => {
    const {
      target: { name, value },
    } = event; // 비구조화 할당
    if (name === "email") {
      setEmail(value);
    } else if (name === "password") {
      setPassword(value);
    }
  };
  const onSubmit = async (event) => {
    event.preventDefault(); // submit 기본 동작(새로고침) 방지
    try {
      let data;
      if (newAccount) {
        data = await authService.createUserWithEmailAndPassword(
          email,
          password
        );
      } else {
        data = await authService.signInWithEmailAndPassword(email, password);
      }
      console.log(data);
    } catch (error) {
      setError(error.message); // 에러 메시지 출력
    }
  };
  const toggleAccount = () => setNewAccount((prev) => !prev);
  return (
    <>
      <form onSubmit={onSubmit}>
        <input
          name="email"
          type="email"
          placeholder="Email"
          required
          value={email}
          onChange={onChange}
        />
        <input
          name="password"
          type="password"
          placeholder="Password"
          required
          value={password}
          onChange={onChange}
        />
        <input
          type="submit"
          value={newAccount ? "Create Account" : "Sign In"}
        />
        {error}
      </form>
      <span onClick={toggleAccount}>
        {newAccount ? "Sign In" : "Create Account"}
      </span>
    </>
  );
};

export default AuthForm;

Auth.js에서 이메일 로그인/회원가입 폼을 AuthForm 컴포넌트로 분리

 

Deploying

CSS 작업을 마무리하고, 서비스를 GitHub Pages로 배포해보자!

 

1. package.json 최하단에 호스팅할 url를 지정해준다

    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "homepage": "https://joseph-106.github.io/React_Firebase"
}

"https://(사용자).github.io/(저장소)" 형태로 해줘야 한다!

 

2. GitHub Pages 배포를 위한 패키지를 설치해준다

npm i gh-pages

 

3. package.json에 배포 script를 추가해준다

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  },

 

4. 추가한 script를 실행하면 build 폴더가 생성되며 지정한 url에 배포된다

npm run deploy

 

Security on Firebase

배포된 도메인이 Authentication에 접근할 수 있도록 Firebase에 추가해줘야 한다!

 

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if
          request.time < timestamp.date(2022, 4, 19);
    }
  }
}

Cloud Firestore의 Rules를 보면 테스트 모드로 생성했기 때문에 사용 시간에 제약이 걸려있다

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

제약을 지우고 인증이 있어야만 생성과 조회가 가능하도록 수정해주자

 

Google Cloud Platform에서 API Key 보안을 관리할 수 있다🔽

 

Google Cloud Platform

하나의 계정으로 모든 Google 서비스를 Google Cloud Platform을 사용하려면 로그인하세요.

accounts.google.com

Firebase에서 사용한 구글 아이디로 접속하면 프로젝트 API Key가 저장되어 있다
제한사항을 HTTP 사이트로 변경하고 localhost / firebase / 배포 주소를 추가해준다 (/* 붙이기)

이제 승인된 도메인에서만 API Key를 호출할 수 있다!

 

결과물🔽

 

퐈이어베이스

 

joseph-106.github.io

 

본 내용은 노마드코더의 '트위터 클론코딩'을 바탕으로 작성되었습니다.

'Back-end > Firebase' 카테고리의 다른 글

[노마드코더] #5 Edit Profile  (0) 2022.04.08
[노마드코더] #4 File Upload  (0) 2022.04.06
[노마드코더] #3 CRUD  (0) 2022.03.28
[노마드코더] #2 Authentication  (0) 2022.03.18
[노마드코더] #1 Introduction  (0) 2022.03.11