WIL 4 (03/19 - 03/25)

진윈·2021년 3월 28일
0

Weekly I Learned

목록 보기
3/6
post-thumbnail
         		 @     리액트와의 첫 만남      @

0. 리액트

리액트는 페이스북에서 만든 자바스크립트 UI 라이브러이고, 컴포넌트라는 작은 레고들로 페이지를 구성하는 라이브러리이다. 정도의 수준으로 리액트를 들어보고 리액트 공부를 시작하게 되었다.
리액트는 자유도도 높고, 생태계도 넓고 계속해서 끊임없이 새로운 것들이 쏟아지는 라이브러리라고 해서 매우 기대가 되었다.

0.1. 준비과정

정말 기초적인 HTML, CSS, Javascript의 모양(?)정도만 알고있는 나라서, 기본적인 리액트 강의를 듣기전에 사전 공부가 필수적이었다. 민영튜터님의 강의를 보다가 기본적인 단어들조차 모르는 것들이 많아서 따라갈 수 없었다. 그래서 바로 생활코딩의 React 수업을 들었고, Javascript의 객체 지향에 대해서 모르면 리액트를 알기 어렵겠다는 생각이 들어서 Javascript 객체 지향을 따로 또 공부했다. 그리고 나서 민영튜터님의 강의를 듣기 시작했다.

1. 캘린더 만들기 프로젝트

결과적으로 시간이 부족해서 모든 기능을 만들지 못했고, 파이어베이스를 사용해서 배포하는 것도 하지 못했다.
앞에 도 말했듯 홀로 사전강의 공부를 하고 강의를 듣느라 시간을 좀 많이 쓰기도 했다. 기능이야 더 추가하면 되고 배포야 나중에 하면 되니까 그 전에 준비과정을 탄탄히 해놓는게 맞았다! 라는 생각을 하려고 한다.ㅋㅋ..._

완성한 기능들 ~~

캘린더
~~1. 이전 월, 다음 월 보기 버튼이 있고 해당 버튼 클릭 시 월 이동 가능하게 하기

-> fullcalendar 라이브러리를 써서 해결했다

2. 일정 하나를 클릭할 시 팝업 띄우기
- 팝업 내용: 일정 내용 및 일시 텍스트, 일정 삭제 및 일정 완료 버튼 2개

    → 각 버튼을 누르면 일정 삭제 혹은 일정 완료 되게 하기

-> 팝업은 띄웠지만 팝업 내용을 불러오지 못했다 ㅜ ㅜ

3. 일정 추가하기 버튼 (페이지 우측 아래에 플로팅 버튼으로 처리) 클릭 시 일정 추가하기 페이지로 이동하기
-> 플로팅 버튼도 material ui를 사용했다

4. 캘린더 내 일정은 시간 순으로 정렬하기
5. 우측 아래의 추가하기 버튼 위에 [완료된 일정 보기] 만들기
- 클릭 시, 완료된 일정만 캘린더에 표시 되고 버튼 텍스트가 [모든 일정 보기]로 바뀌도록 하기
- [모든 일정 보기] 버튼 클릭 시, 모든 일정 캘린더에 표시하기

일정 추가 페이지

  1. 일시, 일정 내용을 기입하지 않으면 팝업으로 경고하기
    • 실제로 파이어스토어에 들어가지 못하게 막기
  2. 일정 추가 시 캘린더 페이지로 이동하기

=> 결론적으로 보면 뷰랑 페이지간의 이동같은 간단한 기능들과 리덕스를 사용해서 입력 데이터를 캘린더에 붙여주는 정도의 기능을 완성했다.

2. 값진 삽질

왜 데이터를 불러오지 못했냐고 물으신다면 데이터를 불러오지 못했기 때문이라고,,, 말할 수 밖에 없는데

정작 중요한 데이터를 처리하는 일정 페이지 기능들을 만들 때가 되니 시간이 없었다.
정말 튜터님이 말씀하신대로 빠르게 라이브러리를 썼어야 했는데
초반에 라이브러리를 쓰지 않고 한땀한땀 자바스크립트로 캘린더 뷰를 짰었다.
그러다가 moment()라는 자바스크립트 라이브러리를 알게 되었고 공식 문서를 보면서 참고해 만들었다.

import './App.css';
import {useState} from 'react';
import moment from 'moment';

const App =()=>{
	
//getMoment에는 state 값이 들어가고, setMoment는 getMoment 값을 수정하는 함수가 된다
// useState는 초기값을 설정하는 함수이고, 초기값을 moment()로 잡았다. 
//여기서 moment는 선언할때 현재의 날짜로 초기화 된다-> 오늘로 설정된다.
//그래서 today = getMoment 즉 today == moment() 오늘로 설정함

  const [getMoment, setMoment]=useState(moment());     
  const today = getMoment;    

  return(
    <div className="App">

        <div className="control">
          <button>이전달</button>
          <span>{today.format('YYYY 년 MM 월')}</span>   //YYYY는 년도 MM 은 달 입니다.
          <button>다음달</button>
        </div>
        <table>
          <tbody>
          </tbody>
        </table>
    </div>
  );
}
export default App;
  • 이전달/ 다음달 버튼을 누르면 해당하는 달로 옮겨지게 하기
return(
    <div className="App">

        <div className="control">
         <button
          onClick={() => {
            setMoment(getMoment.clone().subtract(1, "month"));
          }}
        >이전달</button>
          <span>{today.format('YYYY 년 MM 월')}</span>   //YYYY는 년도 MM 은 달 입니다.
          <button
          onClick={() => {
            setMoment(getMoment.clone().add(1, "month"));
          }}
        >다음달</button>
        </div>
        <table>
          <tbody>

          </tbody>
        </table>
    </div>
  );
```해석
{today.format('YYYY 년 MM 월')}
// 이 함수를 쓰면 오늘로 날짜를 포멧해준다


<button onClick={() => {
            setMoment(getMoment.clone().subtract(1, "month"));
// 버튼을 눌렀을 때 이동할 수 있도록 onClick 사용
// 위에서 봤듯 setMoment는 getMoment로 받은 값을 수정해줄 수 있음
// clone()은 기존의 moment()가 아닌 새로운 객체를 반환했다는 의미임
// subtract(1, "month") 하면 해당 month에서 1을 빼줌 - subtract 은 빼기의 의미임
// 반대로 add(1, 'month')하면 해당 month에서 1을 더해줌 - add는 더하기의 의미임
          }}
        >
- 다음으로 달력 날짜 찍히게 만들기

1. 첫 주와 마지막 주에 대한 설정 

    `startOf('month').week() 사용` 

```jsx
const Calendar = () => {
  const [getMoment, setMoment] = useState(moment());

  const today = getMoment;
  const firstWeek = today.clone().startOf("month").week();
  const lastWeek =
    today.clone().endOf("month").week() === 1
      ? 53
      : today.clone().endOf("month").week();


// startOf('month').week()는 그 달의 시작하는 week()
// endOf('month').week()는 그 달의 끝나는 week()임

 const firstWeek = today.clone().startOf("month").week();
 const lastWeek =
    today.clone().endOf("month").week() === 1
      ? 53
      : today.clone().endOf("month").week();

// lastweek에서 쓰인 조건문을 보면 1년은 52주 존재하고 몇일이 더 있어서
// 달력은 53주로 표현해야 한다. 
//하지만 moment()는 내년의 첫주인 1로 표시하기 때문에 마지막 주가 1이 되면 53이라고 표시하라고 조건문 달아줌
  1. 날짜 배열 보여주기
const arr = [1, 2, 3, 4, 5];
  
  return (
    <div className="App">
        <table>
          <tbody>
            {arr}  // 웹에 12345 가 표시됩니다.
          </tbody>
        </table>
    </div>
  );

--> 이런 리액트의 특징(배열을 표시하면 배열 내의 요소를 전부 보여줌)을 이용함 
  • 최종
import "./App.css";
import React, { Component } from "react";
import Calendar from "./Calendar";
import { useState } from "react";
import moment from "moment";
import calendarArr from "./Calendar";

const App = () => {
  const [getMoment, setMoment] = useState(moment());

  const today = getMoment;
  const firstWeek = today.clone().startOf("month").week();
  const lastWeek =
    today.clone().endOf("month").week() === 1
      ? 53
      : today.clone().endOf("month").week();

  const calendarArr = () => {
    let result = [];
    let week = firstWeek;
    for (week; week <= lastWeek; week++) {
      result = result.concat(
        <tr key={week}>
          {Array(7)
            .fill(0)
            .map((data, index) => {
              let days = today
                .clone()
                .startOf("year")
                .week(week)
                .startOf("week")
                .add(index, "day"); //d로해도되지만 직관성

              if (moment().format("YYYYMMDD") === days.format("YYYYMMDD")) {
                return (
                  <td key={index} style={{ backgroundColor: "red" }}>
                    <span>{days.format("D")}</span>
                  </td>
                );
              } else if (days.format("MM") !== today.format("MM")) {
                return (
                  <td key={index} style={{ backgroundColor: "gray" }}>
                    <span>{days.format("D")}</span>
                  </td>
                );
              } else {
                return (
                  <td key={index}>
                    <span>{days.format("D")}</span>
                  </td>
                );
              }
            })}
        </tr>
      );
    }
    return result;
  };

  return (
    <div className="App">
      <div className="control">
        <button
          onClick={() => {
            setMoment(getMoment.clone().subtract(1, "month"));
          }}
        >
          이전달
        </button>
        <span>{today.format("YYYY 년 MM 월")}</span>
        <button
          onClick={() => {
            setMoment(getMoment.clone().add(1, "month"));
          }}
        >
          다음달
        </button>
      </div>
      <table>
        <tbody>{calendarArr()}</tbody>
      </table>
    </div>
  );
};
export default App;

이런식으로 다 만들어놓고! 중간에 튜터님과의 면담 시간에 다른 사람들의 이야기를 듣고 fullcalendar로 노선을 갈아타게 되었다.
물론 fullcalendar로는 캘린더 뷰를 그리기 굉장히 쉬웠다.
그리고 순조롭게(?) 리덕스 훅으로 잘 가져오고 콘솔로도 잘 찍어줬지만 리듀서와 액션 생성자를 만들때 그만 CREATE를 CRAETE로 적는 실수를 하게 되고 거짓말 안하고 쟤 때문에 하루를 날렸다 ㅜ ㅜ 오타일거라는 생각은 못하고 action, initialState, Action Creator, Reducer, Store를 모두 다 쪼객고 분해하고 컴포넌트와 데이터 연결이 잘못되었는지 다시 찍어보고 ,,,
차라리 파이어베이스를 연결해보면서 오타를 찾을 수 있었을텐데 하는 아쉬움이 남는다.

그렇지만 그때 제대로 리덕스와 다른 기초개념들을 공부해둔 덕에 2주차를 오히려 수월하게 (?) 보내고 있다.

3. 깨달은 점

  • 코드를 아끼지 말자 이때까지 해놓은거 날라갈까봐 야금야금 손 보느라 오히려 더 큰 시간을 허비했다

  • 나를 믿자.
    자신이 없어서 다른 사람들이 하는 방식대로 하는 건 하지 말자 (다른 사람들을 무조건 따라하지 말자는 의미가 아니라 '나에게 자신이 없어서'가 이유가 되게하진 말자

  • 더 적극적으로 질문하자.
    물론 해보지도 않고 질문하는건 너무 나에게 치사한 방법이지만, 해도해도 안되는걸 계속 붙잡고 있는 것도 미련한 짓이다. 어려움을 겪고 있는 내용, 시도해본 방법등을 잘 정리해서 공손하게 물어보자.

  • 어쩔 땐 move on이 도움이 된다
    안되면 되게하라! 가 나의 신념은 아니지만 해결되지 않은 찝찝함을 가지고 뒤로 넘어가고 싶지 않았다. 하지만 그게 결국 정도는 아니더라. 정말 크리티컬한 오류가 아니라면 일단 체크해두고 살짝 넘어가보면 내가 이해하지 못했던 개념을 이해해서 해결될 수도 있고, 오타^^를 확인해서 해결할 수도 있고, 그래도 결국에 해결되지 못하면 그때가서 제대로 파보는 편이 좋을 것 같다.

4. 이번 한 주는

강의에 집착하지 않고

개념을 더욱 단단히 잡고

완성한다 !

profile
천방지축 어리둥절 빙글빙글

0개의 댓글