ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [1인 헤어샵 예약 시스템 구현기] firebase로 실시간 예약 시스템 구현하기
    프론트엔드 개발자가 될거야./react 2022. 10. 28. 15:30

    https://jeongeuni.tistory.com/72

     

    [1인 헤어샵 예약 시스템 구현기] 초기세팅과 firebase (기술스택: react, ts, redux-toolkit, styled-component +

    부트캠프를 수료한 후 개인적으로 typeScript, redux-toolkit을 공부해서 프로젝트 리팩토링도 하고 개인 프로젝트도 했다. 기초적인 toDoList, 가위바위보 게임을 구현했었기에 더 깊게 파볼 수 있는 프

    jeongeuni.tistory.com


    백엔드가 없으면 한정된 mock데이터로만 작업해야 하는 아쉬움이 있었다.

    이번에 firebase을 공부해서 실시간으로 user의 데이터가 반영되는 헤어샵 예약 시스템을 만들었다.

    이거 구현할 수 있을까? 하는데 했다. 뿌듯하다. 역시 하면 된다 : )

     

    https://one-people-hairshop.netlify.app/ 이 링크를 클릭하면 나의 헤어샵을 예약할 수 있다.

    헤어샵 이름은 "뽀까까까"

    무슨 뜻일까? 볶아깎아를 빠르게 말하면 뽀까까까이다. 

    개인적으로.. 아주 맘에 드는 헤어샵 이름이다 🙂

     

    중간중간 일이 있어서 작업을 많이 못한 날도 있지만 작업기간은 10월 21일~10월 28일, 

    기술스택은 firebase, TypeScript, React.js, Redux-toolkit, Styled-Component 로 진행했다.

    달력은 2차 프로젝트 때 써본 datePicker를 커스텀하여 사용했다.

     

    디자인부터 헤어샵이름, 구현까지 내 손, 내 아이디어가 거치지 않은 곳이 없다.

    그래서 더 재밌게 애정있게 작업했다 ☺️

    친구들도 예약해줬는데 실시간으로 그 정보를 볼 수 있고 웹사이트에 직접 반영도 되니까 너무 신기했다..... 

    firebase 짱...


    📌  1. 피그마에서 디자인 고안하기

    

    직접 디자인과 어울리는 색상까지 생각하면서 구현해야하니까 아이패드로는 할 수 없다고 생각했고

    이전 직장에서 피그마로 잠시 작업했었는데 그래서 아주아주 조금 할 줄 알기에

    피그마에서 디자인을 고안해가며 작업했다. 정말 그저 간단한 디자인, 색상 참고용...!! 

    이렇게 메인페이지, 예약 페이지, 예약확인 페이지로 구성되어 있다 : )


    📌 2. firebase에서 데이터 가져오기 - ⭐️실시간 예약상황 반영하기⭐️

    이 부분에 가장 많은 시간을 할당했다.

    여러 시간대가 예약이 차있을 수도 있으니 배열에 담아줘야하는데

    이 부분을 생각하지 못하고 하나의 값만 disabled 처리 되도록 했었다. 

    늘 느끼는 거지만 처음부터 완벽한 기획을 가진 개발은 없다.

    실수하며 빠르게 올바른 정답으로 고쳐가는 것이 최선이지 않을까...

     

    실시간 예약상황 구현기를 뜯어보자면,

    const reserve = firestore.collection("reserve") 로 firebase의 내 프로젝트에 접근하고

    reserve.get().then() 으로 reserve에 있는 데이터를 가지고 올 수 있다.

    firebase에서 가져온 데이터를 모두 infoObjArr에 할당한 뒤,
    그 중 선택한 날짜와 일치하는 데이터 filter하여 selectedTime만 뽑았다.

    selectedTime이 11시, 13시, 15시 등 여러개 일 수도 있으니 bucketData배열에 넣었고

    setReservedTime으로 reservedTime state가 되도록 했다.

      const [reservedTime, setReservedTime] = useState<(string | undefined)[]>([]);
    
      const getReservedTime = () => {
        const reserve = firestore.collection("reserve");
    
        reserve.get().then((docs) => {
          let bucketData = [] as (string | undefined)[][];
          let infoObjArr = [] as TotalInfoType[];
          docs.forEach((doc) => {
            infoObjArr = [...infoObjArr, { ...doc.data() }];
          });
    
          const thisDayInfo = infoObjArr.filter(
            (info) => info.month === month && info.day === day
          );
    
          if (thisDayInfo) {
            const totalSelectedTime = thisDayInfo.map(
              (el, i) => thisDayInfo[i].selectedTime
            );
    
            bucketData = [...bucketData, totalSelectedTime];
            setReservedTime(bucketData[0]);
          }
        });
      };

    그리고

    reservedTime배열에 buttonTime이 있거나 or 현재 시간보다 buttonTime이 작은 경우

    버튼을 disabled 처리해줬다.

      const disabledTime = (buttonTime: string) => {
        const date = new Date();
        return (
          reservedTime.includes(buttonTime) ||
          (date.getMonth() + 1 === month &&
            date.getDate() === day &&
            date.getHours() > parseInt(buttonTime, 10))
        );
      };

     

     

     


    📌 3. firebase에 데이터 저장하기

    날짜, 시간 선택 후 예약자 정보를 입력하고 '예약하기' 버튼을 누르면 모달창이 뜬다.

    이 모달창에서는 예약자 성함, 예약한 시각, 예약한 시술 종류를 다시한번 보여준다.

    '취소'를 누르면 예약을 다시 진행할 수 있고

    '확인'을 누르면 firebase에 예약정보가 저장된다.

    '확인'을 누르면 addUserInfo함수가 실행되며 .add로 firebase에 데이터를 보내주는 것이다.

      const { month, day, selectedTime } = useSelector(
        (state: RootState) => state.date
      );
      const { name, number, selectedSort, request } = useSelector(
        (state: RootState) => state.info
      );
    
      const addUserInfo = () => {
        const reserve = firestore.collection("reserve");
        reserve.add({
          name,
          number,
          selectedSort,
          request,
          month,
          day,
          selectedTime,
        });
      };

    📌 4. 내 예약 확인하기

    예약했던 핸드폰번호로 조회하면 내 예약을 확인할 수 있다.

    만약 조회되는 번호가 없으면 '예약이 없습니다'를 보여준다.

      const [searchNumber, setSearchNumber] = useState<string>();
      const [userInfo, setUserInfo] = useState<UserInfoType | null>();
      const [noData, setNoData] = useState<string>();
    
      const searchMyReserve = async (e: React.FormEvent<HTMLFormElement>) => {
        setNoData("");
        setUserInfo(null);
        e.preventDefault();
        const reserve = firestore.collection("reserve");
        const res = await reserve.get().then((userData) => userData);
    
        res.forEach((data) => {
          if (data.data().number === searchNumber) {
            const userInfoData = data.data() as UserInfoType;
            setUserInfo(userInfoData);
          } else {
            setNoData("예약이 없습니다.");
          }
        });
      };

    이렇게 Firebase를 학습하여 backend 없이도 예약 시스템을 구현했다.

    간단한 예약 시스템 flow를 갖춘 시스템을 만든 것이 뿌듯하고 재밌었다 : )

     

    현재, 이 프로젝트 포함하여 3개의 팀프로젝트와 3개의 개인프로젝트가 생겼는데

    앞으로 취업 전까지 어떻게 주니어 개발자로서 역량을 키워가야할지 고민이다. 

    프로젝트들을 리팩토링 해야할까 아니면 next.js를 공부해야할까?

    socket.io로 채팅 기능도 구현해보고싶다.

     

    그리고 6개의 프로젝트를 하며 든 생각이 있다.

    나는 머리가 좋을까? 아닌 것 같다🙂 나쁘지는 않지만 좋지도 않다... 

    그저 오류가 나도 코드 구상이 떠오르지 않아도

    일단 코드를 치거나, 구글링 열심히 하거나, stackoverflow에 질문하면서까지 악바리 근성으로 해결 하고야 마는 것 같다.

    이 악바리 근성은 엉덩이가 무거워야하는 개발자랑 너무 잘 맞는 것 같다. (고등학교 때는 조금 속상했던...)

    앞으로도 이 근성으로 열심히 이겨나갈 나를 믿고 꾸준히 해나가야지🧐🙂😊

    댓글

Designed by Tistory.