[유데미x스나이퍼팩토리] 10주 완성 프로젝트 캠프 32일차

🍊 Firebase

1. Firebase

Firebase는 모바일 및 웹 애플리케이션을 만들기 위해 Google에서 개발한 플랫폼

  • 인증(Authentication): 사용자 로그인 및 ID 관리
  • 클라우드 함수(Cloud Functions): 서버 없이 이벤트 위주로 동작하는 백엔드
  • 클라우드 파이어스토어(Cloud Firestore): 클라우드에 호스팅 된 실시간의 비관계형(NoSQL) 데이터베이스
  • 클라우드 스토리지(Cloud Storage): 거대하게 확장할 수 있는 파일 스토리지
  • 파이어베이스 호스팅(Firebase Hosting): 전 세계를 대상으로 한 웹 호스팅
  • 머신러닝 키트(ML Kit): 일반적인 머신러닝(ML) 작업을 위한 SDK
  • 실시간 데이터베이스(Realtime Database): 클라우드에 호스팅 된 실시간의 비관계형(NoSQL) 데이터베이스

모든 애플리케이션을 만들 때 필요한 부분들을 자동으로 만들어 주는 플랫폼

Firebase와 애플리케이션 연동

  1. Firebase 사이트로 이동
  2. 콘솔로 이동
  3. add project
  4. Get started by adding Firebase to your app (선택)
  5. Add Firebase SDK npm i firebase 설치
  6. firebase.js 파일 생성 후 파일에 SDK 넣어주기
  7. import “firebase/auth” 추가
  8. app 내보내주기
  9. index.js에서 import app from ‘./firebase’ 추가

기능

Authentication → Sign-in method 에서 기능 선택 및 사용 설정

상세 내용 참고

Firebase로 배포하기

  1. npm i -g firebase-tools
    • -g는 global의 약자로 로컬에 글로벌로 설치하여 다른 프로젝트에서도 사용가능하게 함.
  2. firebase login
    • 오류가 나는 경우가 많은데 그럴 경우엔
    • Windows PowerShell 앱을 검색 관리자로 실행
    • 현재 권한상태를 확인 get-ExecutionPolicy
    • 권한 상태를 “RemoteSigned”으로 변경 Set-ExecutionPolicy RemoteSigned / Yes
    • 권한이 정상적으로 변경되었는지 확인 get-ExecutionPolicy
    • vscode에서 명령어를 다시 수행
  3. 브라우저에서 Firebase CLI Login Successful 확인
  4. npm run build
  5. firebase init
  6. 어떠한 기능을 사용할지 space bar로 선택 후 엔터
  7. 기존 or 새로운 프로젝트 선택
  8. build
  9. y
  10. github에 올릴지 말지 선택
  11. 터미널에 firebase deploy 후 호스팅 URL 확인

2. 카페 좌석 확인 구독 시스템

App.jsx

<Route path="/seat/:id" element={<Seat />} />

pages Seat.jsx

import { Fragment } from "react";
import { useParams } from "react-router-dom";
import { getCafeDetail } from "../libs/cafes-function";
import SeatHeader from "../components/ui/SeatHeader";
import SeatDetail from '../components/seat/SeatDetail';

const Seat = () => {
  const { id } = useParams();
  const cafe = getCafeDetail(Number(id));

  return (
    <Fragment>
      <SeatHeader cafe={cafe} />
      <SeatDetail />
    </Fragment>
  );
};

export default Seat;

components seat SeatDetail.jsx

import React, { useState, useEffect } from "react";
import "../style/SeatDetail.css";

// 페이지 새로고침 시에 3개의 랜덤한 좌석이 선택되고, 
// 클릭하여 좌석을 선택하거나 해제할 수 있음.

const SeatDetail = () => {
  const [selectedSeats, setSelectedSeats] = useState([]); // 선택된 좌석을 저장하는 상태
  const [seatRows, setSeatRows] = useState([]); // 좌석 정보를 저장하는 상태

  useEffect(() => {
    initializeSeats();
  }, []);

  useEffect(() => {
    if (seatRows.length > 0) {
      setRandomSeats();
    }
  }, [seatRows]);

  // 좌석 초기화 함수
  const initializeSeats = () => {
    const rows = [
      ["1", "2", "5", "6"],
      ["3", "4", "7", "8"],
      ["9", "10", "11", "12"],
      ["13", "14", "17", "18"],
      ["15", "16", "19", "20"],
    ];

    setSeatRows(rows);
  };

  // 랜덤 좌석 선택 함수
  const setRandomSeats = () => {
    const randomSelectedSeats = [];

    // 3개의 랜덤 좌석 선택
    while (randomSelectedSeats.length < 3) {
      const randomRowIndex = Math.floor(Math.random() * seatRows.length);
      const randomSeatIndex = Math.floor(Math.random() * seatRows[randomRowIndex].length);

      const seat = { row: randomRowIndex, seat: randomSeatIndex };

      // 중복된 좌석이 아닌 경우에만 추가
      if (!randomSelectedSeats.some(
        selectedSeat => selectedSeat.row === seat.row && selectedSeat.seat === seat.seat
      )) {
        randomSelectedSeats.push(seat);
      }
    }

    setSelectedSeats(randomSelectedSeats);
  };

  // 좌석 클릭 핸들러 함수
  const handleSeatClick = (rowIndex, seatIndex) => {
    setSelectedSeats(prevSelectedSeats => {
      const seat = { row: rowIndex, seat: seatIndex };

      // 선택된 좌석인 경우 해제, 아닌 경우 추가
      if (prevSelectedSeats.some(
        selectedSeat => selectedSeat.row === seat.row && selectedSeat.seat === seat.seat
      )) {
        return prevSelectedSeats.filter(
          selectedSeat => selectedSeat.row !== seat.row || selectedSeat.seat !== seat.seat
        );
      } else {
        return [...prevSelectedSeats, seat];
      }
    });
  };

  return (
    <div className="seat-grid">
      {seatRows.map((row, rowIndex) => (
        <div key={rowIndex} className="seat-row">
          {row.map((seat, seatIndex) => {
            const isSelected = selectedSeats.some(
              selectedSeat => selectedSeat.row === rowIndex && selectedSeat.seat === seatIndex
            );

            return (
              <div
                key={seatIndex}
                className={`seat ${isSelected ? "selected" : ""}`}
                onClick={() => handleSeatClick(rowIndex, seatIndex)}
              >
                {/* 숫자 대신 공백으로 표시 */}
              </div>
            );
          })}
        </div>
      ))}
    </div>
  );
};

export default SeatDetail;

3. 결과

좌석

4. 회고

이제 좀 몸이 나아가고 있는거 같다. 이번 주는 정말 할 것도 너무 많고 힘든 주였다. (몸 아픈게 제일 큼 🥲)
Redux는 헷갈리는게 역시 많은거 같아서 좀 더 공부를 해야할 거 같다.
어제는 firebase에 대해서 배웠다. 물론 나는 전날에 예습을 잠깐했기 때문에 막 어려운 느낌은 아니였다. 사실 예습안해도 할만한 정도랄까? 대부분 설명은 공식홈페이지에 나와있으니 따라해보면 쉽다.
그래서 이번 과제는 캠프 사람들과 다 같이 정한 카페 좌석 확인 구독 시스템으로 했다. 캠프 수업이 끝나고 하려다가 금요일에도 오프라인 수업을 못 갈까봐 그냥 푹 쉬고 다음 날 하기로 했다.
오늘 겨우 몸을 일으켜서 시작했는데 팀장님이 먼저 하고 계셨는지 우리 팀 레포를 만들어서 먼저 하신부분을 올려주셨다. 그래서 나는 좌석 페이지를 맡아 구현하게 됬는데,
좌석설정을 어떻게 해야할까 많이 고민이 되었다. 그래서 그냥 맘대로 만들어 버렸달까… 일단 Click 시에 좌석을 선택하거나 해제할 수 있게 만들어봤고,
useEffect로 새로고침 시 랜덤 좌석 선택으로도 만들어봤다 ㅋㅋ.. 어떻게보면 남은좌석? 보여주는건데 데이터가 없으니 그냥 돌려버렸다!
사실 정신없이 시간에 쫒겨 만든거라 제대로 만들었다고 보기도 뭐하긴 하다.. 으허 어려워라 이번에도 정신없는 회고.. 그럼 안녕..👋🏻



본 후기는 유데미-스나이퍼팩토리 10주 완성 프로젝트캠프 학습 일지 후기로 작성 되었습니다.

#프로젝트캠프 #프로젝트캠프후기 #유데미 #스나이퍼팩토리 #웅진씽크빅 #인사이드아웃 #IT개발캠프 #개발자부트캠프 #리액트 #react #부트캠프 #리액트캠프

Leave a comment