Mini프로젝트_감지센서 관리_달력 만들기 (React-calendar, moment.js)

이고운·2022년 10월 24일
0

기업협업

목록 보기
2/4

기업협업 두번째 과제는 감지센서 관리 프로그램 만드는 것이었다.
나는 이번에 달력 라이브러리를 사용해보고 싶어서 달력 부분을 만든다고 하고 진행했다.

1.프로젝트 개요

1) 프로젝트 기간

2022.10.07 ~ 2022.10.09

2) 역할 및 기능 구현

  • 안승섭: 테이블 UI 및 정렬 기능 구현
  • 천찬영: 테이블 필터링 기능 구현
  • 이고운: 달력 기능 구현
  • 양미옥: 기온 그래프 구현
  • 임지영: 습도 그래프 구현
  • 정예원: 기압 그래프 구현

3) 협업 툴

4) 코드 컨벤션

  • 버전: Node.js 16.16.0
  • Styled-Components, SCSS 혼합해서 사용
  • 클래스명은 언더바 형식으로 통일
  • fetch를 이용한 API 통신
  • 파일 확장자는 모두 js로 통일
  • 에셋은 src/Assets 하위에 배치
  • Git-flow

2. 내가 구현한 기능 상세 설명 및 문제 발생 건

처음에는 단순하게 달력만 라이브러리로 만들 생각하고 있었다.
그런데 생각해보니까 달력 날짜에 따라 그래프가 연동이 되여 결과가 출력이 되어야했다. 때문에 그래프 쪽도 같이 봤어야했다.

1) 달력 라이브러리 사용

달력 라이브러리는 react-calendar를 사용했다. 라이브러리 공식 문서가 잘 되어있어서 해당 사이트를 참고했다.

  • react-calendar 공식문서
    기본적으로 들어가는 코드 양식이 따로 있어서 그걸 참고로 하고 추가로 공식문서에 있는 내용에 있는 props들을 참고해서 넣었다.
    아 추가로 달력 라이브러리 css를 수정하려면 하기에 있는 파일을 import해서 수정하면 된다고 했다. 하지만 나는 css를 크게 수정할 생각이 없어서 달력 양식만 좀 바꿨다.

    import 'react-calendar/dist/Calendar.css';

<Calendar.js>
import styles from './Calendar.module.scss';
import Calendar from 'react-calendar';
import { useState, useRef } from 'react';
import 'react-calendar/dist/Calendar.css';

function CalendarPage({ clickIcon, setModal }) {
  const [value, onChange] = useState(new Date());
  const calendar = useRef(null);

  return (
    <div
      className={styles.calendar_container}
      ref={calendar}
      onClick={e => {
        if (calendar.current === e.target) {
          setModal(false);
        }
      }}
    >
      <button
        onClick={() => {
          setModal(false);
        }}
      >
        X
      </button>
      <Calendar
        calendarType="US"
        value={value}
        onChange={e => {
          clickIcon(e);
          onChange();
        }}
      />
    </div>
  );
}

export default CalendarPage;

달력페이지 자체의 코드는 간단하다. 일단 그래프화면에서 달력 아이콘을 클릭했을 때 달력이 모달창으로 열려야해서 아이콘이랑 모달창 props를 달력페이지로 넘겨줬다.

그리고 달력 바깥쪽 클릭시 모달창을 닫히게 해주고 싶어서 useRef 사용했다.
전체 바깥쪽에 ref 속성을 지정해주고 클릭함수를 지정해줬다.
사실 X버튼은 없어도 되는데 그래도 직관적인 버튼 하나 있는게 나은 것 같아서 넣었다.
그리고 실제 달력이 들어가는 부분은 단순하게 양식만 US 타입으로 지정해줬다.
우리가 기본적으로 사용하는 일~토 레이아웃의 달력은 US 타입의 달력이라고 한다. 그래서 calendarType="US"로 지정해주면 아래와 같이 들어가진다.

그리고 달력에 날짜에 onChange함수를 넣어줬는데 이 때 사용한 clickIcon은 그래프 페이지에서 넘어온 props이다. 아이콘 클릭 후 날짜를 클릭하면 그 날짜를 저장하기 위해 사용했다.

2) 달력과 그래프 연동

달력은 내가 만들고 그래프는 다른 사람들이 만들어서 처음에 어떤 걸 가져와야할 지 고민했다. 일단 그래프 페이지는 내가 작성한 코드가 아니다 보니 다른 분이 작성한 코드를 일부 수정한 것도 있었고 이게 어떤 데이터인지 몰라 헤맸던 적도 있지만 그 때마다 슬랙에 정보 공유를 하면서 진행했기 때문에 소통에 문제 없이 원활하게 끝낼 수 있었다.

기존에 그래프 완성하신 다른 팀원분이 useEffect와 fetch로 json데이터를 받아오게 코드를 작성해 놓으셨다. 기존에 전체데이터를 가져왔다면 나는 이 데이터를 내 달력 날짜에 맞게 가져왔어야 했다.

<Graph.js>
import { useEffect, useState } from 'react';
import { getThingspeak } from './Api';
import moment from 'moment';

function Graph() {
  const [data, setData] = useState({}); //그래프 데이터
  const [current, setCurrent] = useState(new Date());
  const [modal, setModal] = useState(false);
  
  const selectedDate = moment(current).format('YYYY-MM-DD');
  const selectedDateNext = moment(selecedDate)
    .add(1, 'days')
    .format('YYYY-MM-DD');

  const clickIcon = date => {
    setCurrent(date);
    if (date) {
      setModal(!modal);
    }
  };
  
  useEffect(() => {
    getThingspeak(selecedDate, selecedDateNext).then(json => setData(json));
  }, [selecedDate]);
  
  return (
    <div className={styles.graph_container}>
      {modal && (
        <Calendar
          setModal={setModal}
          clickIcon={clickIcon}
        />
      )}
      
         <div className={styles.graph_title}>
        <h2>{selecedDate}</h2>
        <p>
          <BsCalendarMonth onClick={clickIcon} />
        </p>
      </div>
  • 선택한 날짜 하루의 데이터를 출력해야하기 때문에 selectedDate, selectedDateNext값을 moment.js를 이용해 선언해줬다.
    moment.js를 날짜 라이브러리인데 현재 날짜 양식을 지정해주고 날짜를 조작하기 위해 사용했다.

    Moment.js 공식문서

  • 달력아이콘을 클릭했을 때 함수를 지정해줬는데, 날짜를 클릭하면 현재 날짜에 그 클릭한 날짜를 상태값으로 저장해주는 것이다.

  • 그러면 current에 담긴 상태값을 가지고 moment 포맷으로 저장해준다.

  • 여기서 만들어진 selectedDate값으로 useEffect를 사용하여 데이터를 가져온다. 이 데이터 가져오는 방법은 아래에 더 자세하게 작성할 것이다.

3) ❌ 문제 발생 ❌

달력을 만들고 날짜 지정까지 했는데 문제는 그 데이터를 어떻게 가져올까라는 것이었다. 기존에 fetch로 가져온 데이터는 그냥 원데이터전체라 이걸 날짜를 쪼개서 가져오는 것에 고민이 많았다. 그리고 그 날짜를 쪼갤 때 fetch 함수를 어떻게 수정할 지에 대해 생각을 했다. 일단 초기세팅해주신 같은 팀원분이 fetch함수를 import하여 쓸 수 있게 코드를 작성해주셨는데, 이 부분이 새로웠다. 기존에는 그냥 해당 페이지에 useEffect로 적어줬었는데, 그 다른 팀원분은 별도의 API 파일을 만들고 거기에 fetch 함수를 적은 다음에 그 함수를 import 해서 가져왔다.

<Api.js>
  import { BASE_URL, CHANNEL_ID, API_KEY } from '../../config.js';

export async function getThingspeak(startDate, endDate) {
  const res = await fetch(
    `${BASE_URL}/${CHANNEL_ID}/feeds.json?api_key=${API_KEY}&start=${startDate}&end=${endDate}`,
    {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    }
  ).catch(() => alert('통신에 실패하였습니다.'));

  return res.json();
} 

base_url같은 것으로 한 번 더 import해서 가져오는 건 보안상 유출을 막기 위해 이렇게 한다고 한다. 이 방법은 기존에 다른 프로젝트 할 때도 사용했던 방식이다.
그 하단에 fetch 함수도 우리가 기존에 사용하던 함수라 일반 적이다.
그런데 이 함수를 다른 쪽으로 import하는 방식이 새로웠다.

<Gragh.js>
    useEffect(() => {
    getThingspeak(selectedDate, selectedDateNext).then(json => setData(json));
  }, [selectedDate]);

보면 useEffect 함수 안에 Api.js에서 작성했던 함수를 가져온 것을 볼 수 있다.
사실 처음에 select날짜까지도 선언하고 나서 저걸 어떻게 fetch 데이터에 수정을 해야할 지, 여러번 수정을 했으나, 이렇게 import해서 사용하는 방식이 처음이다 보니 이렇게 초기세팅해준 팀원분의 도움을 받을 수 밖에 없었다..
이것 저것 수정해보고 검색도 했는데 결국 못찾아서 문의 드렸더니 간단한 방식이라고 하면서 수정해주셨다. 수정해 주신 코드를 보니 알 것 같다.
참조로 들어간 startDate, endDate를 그래프 페이지 임포트 해서 함수 작성해줄 때 그 값을 내가 선언해준 selectedDate, selectedDateNext로 대체해서 넣어준 것이다. 그리고 그 데이터를 json형식으로 가져와 data(setData)에 넣어줘서 사용했다.

4) 결과화면

3. 느낀 점

이번 미니 프로젝트는 실제로 작업할 시간이 그렇게 많지는 않았다. 그리고 주말이 포함되어있다보니 팀원들이 UI쪽은 가볍게 가고 기능 위주로 진행하자고 해서 그렇게 진행한 프로젝트이다. 이번 프로젝트를 하면서 느낀 점은 라이브러리는 공식 문서가 중요하다는 점이다. 물론 블로그 같은 글도 도움이 많이 되지만
정석적으로는 공식문서를 먼저 보고 필요한 데이터가 있는지 찾아보는게 좋다는 것을 느꼈다. 이번에 달력 라이브러리를 사용하면서 구글에 react-calendar를 검색해서 나오는 블로그들을 보다가 달력 양식을 일~토로 수정하는 방법을 모르겠어서 해메다가 공식문서를 보게되었는데 아주 친절하게 userguide props항목에 calendarType이 적혀 있었다.!! 다음에는 공식문서 먼저 보고 없는 자료를 구글에 검색해보는 것이 좋을 것 같다는 생각이 들었다.

라이브러리는 공식문서 먼저 확인하고 참고하기❗️❗️❗️

profile
자 이제 시작이야~ 내 꿈을~ 내 꿈을 위한 여행~~🌈

0개의 댓글