페어 활동 기록_Day18_한빈_현정 - boostcampwm-2022/web33-Mildo GitHub Wiki

✂️ 분배된 이슈

  • api 서버에서 Redis에서 가져온 24시간 이내의 정보 응답(#36)
  • 과거 시간대별 그래프 출력(#37)

🚩 구현 목표

  • Redis에서 지역별 24시간 전체 정보 가져오기 router 생성
  • 상세 모달 2단계 창에서 24시간 그래프 UI 만들고 24시간 정보 가져와서 렌더링

🍀 세부 목표

api 서버에서 Redis에서 가져온 24시간 이내의 정보 응답(#36)

  • Redis에서 최근 24시간 정보 가져오는 router 생성

과거 시간대별 그래프 출력(#37)

  • 클라이언트에서 해당 지역의 시간대별 인구밀도 가져오기
  • max, min을 어떻게 보여줄지 결정하기
  • 그래프 UI 구현하기
    • 시간을 ‘n시간 전’으로 가공하기
    • 데이터 24개 추리기
    • 그래프 너비 스타일링
    • 색, 크기 같은 전체적인 그래프 스타일링
  • 데이터 불러올 때 로딩 화면 구현

상세 모달창 닫기(#54)

  • 상세정보 1단계 모달 닫기
  • prevPlace 비워주기
  • 상세정보 2단계 모달 닫기
  • 다른 핀 클릭할 때 2단계 모달 닫기

🖥️ 구현 내용

상세 모달창 닫기

Day18 - 모달창 닫기.gif

  • 마커 이외의 부분을 누르거나 다른 마커를 눌렀을 때 모달창이 닫힘

시간대별 그래프

Day18 - 시간대별 그래프, 캐싱.gif

  • 그래프, 로딩 구현
  • 이미 캐싱된 경우 로딩 없이 빠르게 그래프를 보여줌

📖 학습 내용

React.Fragment

  • <React.Fragment></React.Fragment><></> 는 같다.

useEffect를 적절한 때에 써야 하는 이유

  • return 이후에 useEffect로 가기 때문에 렌더링에 관련된 것은 useEffect를 사용하지 않고 return 전에 코드를 작성하는 것이 좋다.
    • 렌더링에 관련된 로직인지 아닌지 파악하는 것이 가장 기본인 것으로 보임
  • 참고 자료

typescript에서 함수형 component props 기본 값 설정

  • {props = 값}

    const MapLoading: React.FC<MapLoadingProps> = ({
      message = '로딩중입니다...',
      width = '200px',
      height = '200px'
    }) => {
      return (
        <LoadingPageStyle>
          {message && <h1>{message}</h1>}
          <img src='https://ifh.cc/g/RQcSZX.gif' width={width} height={height} />
        </LoadingPageStyle>
      );
    };

jotai에서 [state, setState] 안 쓰는 방법

  1. useAtomValue
    • 값을 읽기만할 때 사용 가능
  2. useUpdateAtom
    • 값을 쓰기만할 때 사용 가능
import { useAtomValue, useUpdateAtom } from 'jotai/utils';

...
const count = useAtomValue(countAtom);
const setCount = useUpdateAtom(countAtom);

ApexCharts 사용법

🩺 의사결정

24시간 이내 데이터 캐싱

  1. 전역 상태로 두고 전역 상태에 없으면 api요청하고 전역 상태에 등록, 이미 있으면 전역 상태에서 가져오기
    1. 11시 50분에 요청 → 11시 30분 ~ 24시간 전의 11시 30분
    2. 12시 요청 → 캐싱된 데이터가 바뀌어야 함
      • 어차피 핀도 새로고침해야 새로운 데이터가 적용이 됨
  2. 매번 api 요청하는 것이 큰 부담이 되는가?
    1. 핀은 새로고침하면 데이터가 적용이 안 되는데, 상세정보만 업데이트 된다면?
    2. 핀도 실시간으로 데이터를 업데이트 시키자
  3. 실시간으로 데이터가 바뀌는 부분은 일단 미루고 전역상태로 만들자

⇒ 후에 그래프가 그려질 때 로딩되는 기능을 구현하고 나니, 캐싱된 데이터는 로딩 없이 빠르게 그래프를 그려주었다.

그래프 구현 방법

max, min 두 가지 중 어떤 걸 보여줄지?

  1. 평균 같은 통계 내서 보여주기
    1. 통계 방식이 문제
  2. max, min 둘 다 보여주기
    1. 그래프를 완전 겹쳐서 보여주기

Untitled

  • 그래프 안에 숫자를 넣으려면 그래프의 최대/최소 길이를 정해야 함
    • 48개 중 제일 큰 max를 구해서 나머지는 이에 맞춰 퍼센트를 구함

⇒ apexcharts 라이브러리를 이용해서 min, max 둘 다 보여주는 것으로 설정

그래프 구현 방법

  1. 라이브러리
    1. 그래프를 빨리 끝내고 반응형이나 최적화 문제를 신경 쓸 수 있음
    2. 애니메이션 등을 구현하지 않아도 사용할 수 있음
  2. 직접 구현
    1. 학습에 도움이 될 것 같으나, 수학 공부 이상의 학습이 될 수 있을지 의문

⇒ Apexcharts 라이브러리 사용하기로 결정

그래프 시간을 보여주는 법

  • 1시간 전, 2시간 전, 3시간 전 …을 보여주는 방법

  • 시간별 인구밀도 정보

    {
    	2022-11-29T13:05:00.000Z:{
    		populationLevel: "여유",
    		populationMax: 18000,
    		populationMin: 16000
    	}, 
    	...
    }
  1. 시간별 인구밀도 정보는 30분 간격으로 저장되므로, 홀수번째 시간들만 뽑아오기

    → 오류가 발생했거나 특정 상황에서 서울 실시간 도시 데이터 API에서 한 번이라도 데이터를 가져오지 못한다면, 밀릴 수 있음

  2. 제일 최근에 저장된 데이터의 시간을 기준으로 시간차를 계산한 후, 0.5시간처럼 소수점이 붙는 시간은 제외시키기

  3. 1시간 전, 2시간 전 등은 사용자가 계산해야 하므로 구체적인 시간을 적기

→ 그러나… 서울시 도시데이터가 일정한 시간 간격으로 제공되는 것이 아니라 24시간의 데이터를 어떻게 선정할지 논의할 필요가 있음

🚧 Trouble Shooting

apexcharts Cannot find module 에러

Untitled

  • 개발 모드로 설치하여 해결(yarn add -D react-apexcharts apexcharts)
    • 그러나 개발 모드로 설치하고 package.json에서 일반 의존성으로 옮길 경우 다른 사람의 yarn.lock이 달라질 수 있음

시간별 그래프 보여주기

  1. redis 저장 상태

    • redis에는 서울 실시간 도시 데이터 API에서 인구 밀도 데이터를 저장한 시간(populationTime)을 key로 갖고 있다.
    • 제일 최근에 저장한 데이터의 시간을 recent 라는 key로 갖고 있다.
    • recent 는 서울 실시간 도시 데이터 API에서 정보를 가져올 때 가장 처음 들어온 데이터의 populationTime 으로 설정된다.
  2. 문제점

    • 지역마다 populationTime 이 다르다.

      ex) 크론탭으로 한 번 가져올 때 서울역은 populationTime2022-11-22T06:40:00.000+00:00 이지만 강남역은 2022-11-22T06:45:00.000+00:00 일 수 있다.

    • 하나의 populationTime 을 key로 갖고 있기 때문에 recent 키를 이용하여 50개 지역의 인구밀도를 가져올 때는 문제가 되지 않는다.

    • 하지만 특정 지역의 시간대별 인구 밀도 정보를 가져올 때 시간 계산하는 것이 문제가 된다.

    // 시간차를 계산하는 코드
    const getHourDiff = (date: string) => {
      const msDiff =
        new Date(Object.keys(graphInfo)[0]).getTime() - new Date(date).getTime();
      const hourDiff = msDiff / (1000 * 60 * 60);
    
      return hourDiff.toFixed(1);
    };
    • 제일 최근 populationTime 을 기준으로 하여 시간차를 계산하면 이상적으로는 0.5, 1, 1.5 …가 나와야 하지만, 지역마다 populationTime 이 다르기 때문에 0, 0.4166666666666667, 1, 3.9166666666666665, 4.416666666666667 처럼 나올 수 있다.

jotai never 타입 에러

This expression is not callable. Type 'never' has no call signatures.ts(2349)

export const isSecondLevelAtom = atom<boolean>(false);

const [isSecondLevel, setIsSecondLevel] = useAtom~~<boolean>~~(isSecondLevelAtom);
  • atom을 선언할 때 이미 type을 정해주었으므로 useAtom을 사용할 때는 type을 정해주지 않아도 된다.

❓궁금한 점

🎸 기타

실시간 데이터 구현법

  1. react-js-cron 같은 라이브러리 사용
  2. 세션 등을 사용하여 클라이언트에서 일일이 시간을 확인한 후 30분이 지나면 자동으로 api요청
  3. socket 사용

→ 다른 팀 페어와 같이 논의해보기

⚠️ **GitHub.com Fallback** ⚠️