Toy Project : Teta's Card Maker

ichbinmin2·2021년 3월 6일
0

Toy Project

목록 보기
2/2
post-thumbnail

👩🏻‍💻 Toy Project : Teta's Card Maker

▪️ 프로젝트 소개

지인의 정보를 card로 담아 입력하고, 입력한 데이터를 저장/관리하는 웹사이트입니다.

▪️ 기술 스택

  • ReactJS / React-Hooks / PostCss
  • Firebase / Cloudinary
  • JavaScript(ES6) / HTML

▪️ 진행 도구

  • Notion (프로젝트 기능 구현 계획과 일정 관리)
+ Git + [GitHub](https://github.com/ichbinmin2/teta_CardMaker) + Postman (API data 관리)

▪️ 구현한 기능

  • React-hooks, CSS(PostCSS) 사용
  • Router를 사용한 페이지 이동 구현
  • Firebase Authentication을 사용한 소셜 로그인 인증 구현
  • Firebase realtime database를 사용한 카드 데이터 저장 관리
  • Cloudinary 를 이용한 이미지 업로더 기능 구현
  • Dependency Injection을 통한 API 보안 관리
  • cursor 애니메이션 구현
  • 도형 애니메이션 및 반응형 웹페이지 구현

▪️ 구현 기능 영상

소셜 로그인 (Firebase Authentication)

Firebase Authentication 서비스를 이용한 구글, 깃허브 소셜 로그인을 구현했다. Firebase 를 Add 할 때 역시, 지난 토이 프로젝트에서 진행했던 것과 동일하게 Dependency Injection를 적극 활용하여 API 보안 관리를 진행하고자 .env 파일 안에서 API Key를 작성하고 전체적으로 firebase API를 받아오는 js 안에서 불러오도록 만들었다.

⚡️ 진행과정 참조 ⚡️
Firebase를 이용한 소셜 로그인 구현(1)
Firebase를 이용한 소셜 로그인 구현(2)

firebase.js

import firebase from "firebase/app";
import "firebase/auth";
import "firebase/database";

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DPMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
};

const firebaseApp = firebase.initializeApp(firebaseConfig);

export const firebaseAuth = firebaseApp.auth();
export const firebaseDatabase = firebaseApp.database();
export const googleProvider = new firebase.auth.GoogleAuthProvider();
export const githubProvider = new firebase.auth.GithubAuthProvider();

그리고, 인증 서비스 기능만을 담당하는 auth_service.js를 만든 뒤 firebase에서 import해온 firebaseAuth, githubProvider, googleProvider 등으로 해당 auth service 내에서 class를 작성하고 각각의 용도에 맞는 (인증)서비스가 필요한 컴포넌트에서 받아오는 방식으로 구현했다.

import { firebaseAuth, githubProvider, googleProvider } from "./firebase";

class AuthService {
  // 로그인 
  login(providerName) {
    const authProvider = this.getProvider(providerName);
    return firebaseAuth.signInWithPopup(authProvider);
  }

// 로그아웃
  logout() {
    firebaseAuth.signOut();
  }

  userLogin(onUserChanged) {
    firebaseAuth.onAuthStateChanged((user) => {
      onUserChanged(user);
    });
  }
  
// 소셜 로그인 받아오기
  getProvider(providerName) {
    switch (providerName) {
      case "Google":
        return googleProvider;
      case "Github":
        return githubProvider;
      default:
        throw new Error(`not supported provider : ${providerName}`);
    }
  }
}

export default AuthService;

  1. 소셜 로그인
    firebase.js(firebase API)에서 import 해온 firebaseAuth에 getProvider와 signInWithPopup(firebase)메소드 함수를 사용하여 인증 서비스가 필요한 컴포넌트에서 해당 함수를 받아오는 방식으로 구현했다. Github와 Google 의 인증 서비스 구분은 switch 문을 활용하여 각각의 인자가 case와 동일하면 그에 맞는 해당 소셜 인증 API 명령어로 받아올 수 있도록 설정해주었다.

  2. 로그아웃
    로그아웃 역시, firebase.js(firebase API)에서 import 해온 firebaseAuth에 signOut(firebase)메소드 함수를 사용하여 로그아웃 서비스가 필요한 컴포넌트에서 해당 함수를 받아오는 방식으로 구현했다.

  3. 로그인 유지
    로그인을 한 상태에서 새로 페이지를 열었을 때에도 자동으로 로그인이 되도록 구현했다. 이때에도 인증 서비스 기능만을 담당하는 auth_service.js의 class 에서 user가 로그인이 되어있는 상태인지만을 확인하는 로직에 onAuthStateChanged(firebase)메소드 함수를 활용하여 조건식을 통해 로그인 정보가 필요한 컴포넌트에 id 값을 넣어주는 방식으로 구현했습니다.

카드 메이커 페이지

  • 실시간 정보 입력 및 수정, data 삭제 기능 구현

⚡️ 진행과정 참조 ⚡️
입력 값을 실시간으로 수정/삭제하기

해당 폼을 입력하는 태그마다 useRef() 를 설정해준 뒤, event.current.target이 업데이트 될 때마다 해당 card의 name 값을 value 값으로 업데이트 할 수 있도록 함수를 작성해주었다.

또한, 상위 컴포넌트의 콜백 함수 내에서 delete 명령어를 사용하고, 해당 폼을 입력하는 컴포넌트에 props 로 함수를 보내 delete 버튼을 누르면 입력 폼 카드가 삭제되는 기능까지 구현하였다.

  • Cloudinary를 적극 활용하여, 이미지 업로딩을 구현했다.

⚡️ 진행과정 참조 ⚡️
TIL. Cloudinary를 사용한 이미지 업로딩(1)
TIL. Cloudinary를 사용한 이미지 업로딩(2)

const url = process.env.REACT_APP_CLOUDINARY_API_KEY;
const name = process.env.REACT_APP_CLOUDINARY_PROJECT_NAME;

class ImageUploader {
  async imageUpload(file) {
    const data = new FormData();
    data.append("file", file);
    data.append("upload_preset", `${name}`);

    const result = await fetch(`${url}`, {
      method: "POST",
      body: data,
    });
    return await result.json();
  }
}

export default ImageUploader;

앞서, 작성한 firebase 인증 class 처럼 이미지 업로더 기능만을 담당하는 image_uploader.js 안에서 class 를 만든뒤, 이미지 업로더 서비스가 필요한 컴포넌트에서 해당 함수를 받아오는 방식으로 구현했다.

이미지를 업로드할 때, 이벤트 함수와 조건식을 활용하여 css로 로딩스피너도 만들었다.

실시간 데이터 서비스 (Firebase Realtime database)

  • 실시간 정보 저장, 삭제 기능

⚡️ 진행과정 참조 ⚡️
TIL. Firebase를 이용한 실시간 데이터 베이스 구현

import { firebaseDatabase } from "./firebase";

class CardRepository {
  syncCards(userId, onUpdate) {
    const ref = firebaseDatabase.ref(`${userId}/cards`);
    ref.on("value", (snapshot) => {
      const value = snapshot.val();
      value && onUpdate(value);
    });
    return () => ref.off();
  }

  saveCard(userId, card) {
    firebaseDatabase.ref(`${userId}/cards/${card.id}`).set(card);
  }

  removeCard(userId, card) {
    firebaseDatabase.ref(`${userId}/cards/${card.id}`).remove();
  }
}

export default CardRepository;

실시간 데이터 서비스 기능만을 담당하는 card_repository.js 안에서 class 를 만든뒤, 로그인 함수를 작성하고 set와 remove(firebase)메소드를 사용하여 실시간 데이터 서비스가 필요한 컴포넌트에서 해당 함수를 받아오는 방식으로 데이터 저장/삭제 기능을 구현했다.

Router 페이지 이동 기능 구현

  • Router와 useHistory()를 사용하여 페이지 이동을 구현했다.
        <Route exact path="/">
          <Main />
        </Route>
        <Route path="/board">
          <MainBoard
            authService={authService}
            FileInput={FileInput}
            cardRepository={cardRepository}
          />
        </Route>

반응형 웹페이지 구현 및 애니메이션 구현

  • @media screen 을 이용하여 반응형 사이트를 구현했습니다.


✨✨ 사이트 둘러보기! 👉🏻👉🏻 [Teta's Card Maker] (https://603ce6b8d579f1f8067c72df--teta-cardmaker.netlify.app/)

profile
N개월차 프론트엔드 개발자, Teta Min

관심 있을 만한 포스트

0개의 댓글