(TIL) 10. RN & FB & dayjs : 대환장파티

김동우·2021년 9월 15일
0

React-Native

목록 보기
10/17
post-thumbnail

1. 잡설

네. 반갑습니다.

본격적인 프로젝트의 시작입니다.

정말 즐거운데, 이게 참 즐겁다가 불행하다가 정말 모르겠습니다. 이제는 저도 모르겠네요.

뭐든 새로운 기술을 사용해보는건 참 흥미롭습니다.

뭐 때문에 막힐지 모르니까 매일이 크레바스 위를 걷는 기분인 것 같네요.

그래도 오늘 할당을 다 채웠다는 사실이 정말 기쁩니다.

오늘 일감

  • Text 제한하기(min 20, max 300)
  • 실시간으로 당일, 전일 데이터 관리하는 로직 작성하기
    - 00:00 기준 오늘 할일 => 어제 한 일 이동(DB load : on)
    - 저장하기 (DB save : set) 버튼 구현
    - 터치 시 수정기능 (TextArea)

완료사항

  • Text 제한하기(min 20, max 300) ✔️
  • 실시간으로 당일, 전일 데이터 관리하는 로직 작성하기 save & onLoad로 해결? ✔️
    - 00:00 기준 오늘 할일 => 어제 한 일 이동(DB load : on) ✔️
    - 저장하기 (DB save : set) 버튼 구현 ✔️
  • 터치 시 수정기능 (TextArea) ✔️
  • DB 설계 일부 변경하기 (task dir) ✔️
  • dayjs 로직 정리하기 ✔️

돌아보니 이것저것 그래도 좀 했네요.

나름 즐거운 하루인건 맞았나봅니다.

2. firebase DB setting error(android)

오늘은 신박한 DB 연동 문제가 있었습니다.

이상하게 어제까지만 해도 잘 되던게 오늘 갑자기 자고 일어나니 모르쇠로 일관하더라구요.

android는 참 알다가도 모르겠습니다.

꾸역꾸역 세팅을 처음부터 다시 설정하며, firebase project 설정을 다시 추적하던 중에 이유를 알 수 있었습니다.

  • google-services.json을 확인해보니,
   "project_info": {
    "project_number": "~",
      ---
    "firebase_url": "https://~", // firebase_url 이 녀석이 없었습니다..
      ---
    "project_id": "~",
    "storage_bucket": "~"
  },

저게 왜 없어졌는지 저는 정말 알다가도 모르겠더군요.

아마 초기세팅에서부터 빠져있었거나, 아니면 중간에 DB연동 이슈를 해결하려고 이리저리 적용하다 사라진게 아닐까 싶습니다.

firebase DB를 사용하는데 어려움이 있으신 분들은 이걸 보고 해결하시면 어떨까 싶기도 하네요.

  1. 저것 말고도 해결과정에서 android studio에 직접 google-services.json을 드래그해서 refactor 할 경우 프로젝트가 박살나는 것도 하나의 이슈였습니다.

    당황하지 않고, 바로 clone 다시 만들기. local에서 작업파일 살려오기.

이것저것 원시적인 방법으로 돌아가지 않을 수 있었습니다.

때로는 일차원적인 방법이 가장 최고일지도 모르겠네요.

3. dayjs

이녀석 참 물건이었습니다.

제 벨로그를 보셨던 분들은 그동안 제가 Date()와 얼마나 많은 싸움을 했었는지 아실 수도 있겠습니다.

1차 프로젝트에서의 countdown timer, 2차에서의 calendar... 3차는 DB와 Date?

그냥 대충 dayjs().~ 해버리면 뚝딱입니다.

물론 필요한 로직 정도는 짜야겠지만, 변환과정을 생략할 수 있다는건 축복인 것 같습니다.

그래서 이번 로직은 가독성이 상당히 좋습니다.

로직도 아니고, 그냥 뭐랄까요... 어... 좀 더 편하게 가져다 쓰기?

그 쯤 되는 것 같습니다.

필요하신 분들은 꼭 써보시길 바랍니다.

2019년 기준 moment.js는 개발을 중단하기로 했습니다.
또한 moment.js는 오래된 라이브러리임에 따라 안정성을 유지한 채 확장하기 어렵고, 사용 목적에 비해 큰 메모리를 차치하기에 요즘은 dayjs로 갈아타고 있다고 합니다.

dayjs의 경우 지속적으로 개발하고 있고, locale도 100여개 정도를 지원한다고는 합니다.

이정도 프로젝트에서는 뭘 사용해도 상관없겠지만요.

import dayjs from 'dayjs';
import 'dayjs/locale/ko';

dayjs.locale('ko');

export const dayjsNow = () => {
  return dayjs().format('YYYY-MM-DD HH:mm:ss');
};

export const nowYear = () => {
  return dayjs().year();
};

export const nowMonth = () => {
  return dayjs().month() + 1;
};

export const nowDate = () => {
  return dayjs().date();
};

export const nowTime = () => {
  return `${dayjs().hour()}:${dayjs().minute()}:${dayjs().second()}`;
};

export const nowDateArray = () => {
  return [nowYear(), nowMonth(), nowDate()];
};

export const todayYearMonthDate = () => {
  return dayjs().format('YYYY-MM-DD');
};

export const yesterdayYearMonthDate = () => {
  const yesterday = `${nowYear()}-${nowMonth()}-${nowDate() - 1}`;
  return dayjs(yesterday).format('YYYY-MM-DD');
};

export const timeLag = (fromDayString: string, subDayString: string) => {
  const time = dayjs(subDayString).valueOf() - dayjs(fromDayString).valueOf();
  const hour = Math.floor(time / (60 * 60 * 1000));
  const minute = Math.floor((time / (60 * 1000)) % 60);
  const seconds = Math.floor((time / 1000) % 60);

  const workedTime = `${hour}:${
    minute < 10 ? '0' + minute : minute
  }:${seconds}`;
  return workedTime;
};

이전 프로젝트에서는 year, month, day data를 따로 요청할 일이 없었는데, 이번 DB 특성상 따로 사용할 일이 있어 우선은 빼두었습니다.

셋 다 사용하게 될 경우에는 array method를 사용하는게 나을 것 같네요.

개인적으로 slice와 split을 좋아하지 않기도 하고, 최적화에 있어 유의미하지 않겠다는 판단이 들어 따로 두었습니다.

그래도 프로젝트 후반부에는 어떨지 모르겠습니다.

4.

그 이외에도 뭐...

import React, {useEffect, useState} from 'react';
import {WorkLogUseCase} from '../../../domain/useCase/WorkLogUseCase';

import {WorkLog} from './WorkLog';

const workLogLogic = new WorkLogUseCase();
const {buttonDisableTest, getYesterdayWorkLog, getTodayWorkLog, saveWorkLog} =
  workLogLogic;

const loadWorkLog = (
  setYesterdayWorkLogText: React.Dispatch<React.SetStateAction<string>>,
  setTodayWorkLogText: React.Dispatch<React.SetStateAction<string>>,
) => {
  getYesterdayWorkLog().then(workLogObj => {
    if (workLogObj !== null) {
      setYesterdayWorkLogText(workLogObj.workLog);
    }
  });
  getTodayWorkLog().then(workLogObj => {
    if (workLogObj !== null) {
      setTodayWorkLogText(workLogObj.workLog);
    }
  });
};

export const WorkLogPresenter = () => {
  const [yesterdayWorkLogText, setYesterdayWorkLogText] = useState<string>('');
  const [todayWorkLogText, setTodayWorkLogText] = useState<string>('');
  const [saveOrInsert, setSaveOrInsert] = useState<string>('저장하기');
  const [saveButtonDisabled, setSaveButtonDisabled] = useState<true | false>(
    true,
  );
  const [insertCheck, setInsertCheck] = useState<true | false>(false);

  useEffect(() => {
    if (!insertCheck) {
      loadWorkLog(setYesterdayWorkLogText, setTodayWorkLogText);
    }
    if (yesterdayWorkLogText !== undefined && todayWorkLogText !== undefined) {
      buttonDisableTest(yesterdayWorkLogText.length, todayWorkLogText.length)
        ? setSaveButtonDisabled(true)
        : setSaveButtonDisabled(false);
    }
  }, [yesterdayWorkLogText, todayWorkLogText, insertCheck]);

  return (
    <WorkLog
      yesterdayWorkLogText={yesterdayWorkLogText}
      todayWorkLogText={todayWorkLogText}
      setYesterdayWorkLogText={setYesterdayWorkLogText}
      setTodayWorkLogText={setTodayWorkLogText}
      saveOrInsert={saveOrInsert}
      saveButtonDisabled={saveButtonDisabled}
      setInsertCheck={setInsertCheck}
      saveWorkLog={() => {
        saveWorkLog(yesterdayWorkLogText, todayWorkLogText);
      }}
    />
  );
};

이런 녀석이나

import {WorkLogRepository} from '../../data/repository/WorkLogRepository';

export class WorkLogUseCase extends WorkLogRepository {
  buttonDisableTest(yesterdayTextLength: number, todayTextLength: number) {
    if (
      yesterdayTextLength < 20 ||
      todayTextLength < 20 ||
      yesterdayTextLength >= 300 ||
      todayTextLength >= 300
    ) {
      return true;
    } else {
      return false;
    }
  }

  saveWorkLog(yesterdayWorkLogText: string, todayWorkLogText: string) {
    if (
      yesterdayWorkLogText.length < 20 ||
      todayWorkLogText.length < 20 ||
      yesterdayWorkLogText.length >= 300 ||
      todayWorkLogText.length >= 300
    ) {
      return;
    } else {
      return super.setWorkLogInDB(yesterdayWorkLogText, todayWorkLogText);
    }
  }
}

이런 녀석,

import {UsingFirebaseDB} from './UsingFirebaseDB';
import {todayYearMonthDate, yesterdayYearMonthDate} from '../../utils/dayjs';

import {IWorkLog} from '../../presentation/interface/IWorkLog';
export class WorkLogRepository extends UsingFirebaseDB {
  async getYesterdayWorkLog(): Promise<IWorkLog | null> {
    try {
      const workLog = await super.getDataFromDB(
        `/uid/task/${yesterdayYearMonthDate()}`,
        'value',
        snapshot => {
          return {...snapshot.val()};
        },
      );
      return workLog;
    } catch {
      return null;
    }
  }
  async getTodayWorkLog(): Promise<IWorkLog | null> {
    try {
      const workLog = await super.getDataFromDB(
        `/uid/task/${todayYearMonthDate()}`,
        'value',
        snapshot => {
          return {...snapshot.val()};
        },
      );
      return workLog;
    } catch {
      return null;
    }
  }

  async setWorkLogInDB(yesterdayLogText: string, todayWorkLogText: string) {
    try {
      await super.setDataToDB(
        `/uid/task/${yesterdayYearMonthDate()}/workLog`,
        yesterdayLogText,
      );
      await super.setDataToDB(
        `/uid/task/${todayYearMonthDate()}/workLog`,
        todayWorkLogText,
      );
    } catch {
      console.log('DB update Error! : WorkLog');
    }
  }
}

이런 녀석이 있긴 합니다.

load 함수를 useCase로 뺄까 말까 고민중인데, 아무래도 인자가 setState 함수에 해당하기 때문에 고민이 되는 것 같습니다.

그 이외에 디테일한 수정은 팀의 방향성에 맞춰 리팩토링 & unit test 시간에 진행하기로 결정했습니다.

그럼 오늘도 모두 고생하셨습니다.

저는 내일 다른 글로 뵙겠습니다. 감사합니다.

0개의 댓글