[Trouble Shooting]리액트 3주차 과제

FeRo 페로·2022년 7월 24일
0

나태지옥에 있다 벌을 받다

이번 주는 나태지옥에 빠져 있었다. 지난 주 목요일 프로젝트를 제출하고 나서 금, 토, 일 3일을 정말 말 그대로 아무것도 안 하고 쉬었다. 인강 몇 개 본 것 빼고는 아무것도 안 했다. 그렇다 보니 월요일에 부랴부랴 인강 보고 화요일 오후 늦게 프로젝트를 시작했다. 하지만 이번 프로젝트는 앞선 두 번의 프로젝트와는 규모가 달랐다.

구현해야 하는 기능도 상당히 많았고 그 만큼 시간도 오래 걸렸다. 그런데 늦게 시작했으니 어떻게 됐을까? 당연히 제시된 기능을 다 구현하지 못한 채로 제출을 했다. 한 수요일 쯤? 나태지옥에 빠진 스스로를 질타하면서 밤을 샜지만 그래도 결국은 수정과 삭제를 구현할 시간이 없어서 그냥 제출을 해야 했다. 이 자리를 빌어서 다시 한 번 나태지옥에 빠진 스스로를 반성 해본다.

Redux ToolKit

이번 주는 리덕스 툴킷을 써보았다. 사실 아직은 '깡' 리덕스로도 잘 쓰고 있어서 '왜 이걸 또 배워야 할까?'하는 생각이 있었는데 역시 다 이유가 있었다. 스파르타에서 제공하는 인강을 봤었는데 덕스 타입을 하나의 슬라이스에 만드는 것에서 첫 매력을 느꼈다. 하나의 폴더에서 state, type, action function, reducer를 작성하는 것을 덕스 구조라고 하는데, createSlice를 쓰면 하나의 slice 안에 이 네 가지 요소가 다 들어가게 된다. 더욱 콤팩트하게 되는 것이다. 훨씬 간편하고 보일러 플레이트가 줄어든다.

두 번째로 매력을 느낀 건 createAsyncThunk도 있고 immer도 내장되어 있다는 점이었다. 그래서 훨씬 사용할 때의 편의성도 좋아졌다.

물론 사용하는 방식이 익숙지 않아서 고생을 좀 했었는데 몇 번 만들면서 익숙해 지니까 훨씬 더 괜찮은 거 같았다. 더 써보면 그 필요성을 더 느낄 거 같다.

Trouble Shooting

이번 주는 인스타그램과 같이 사진과 글을 같이 올리는 사이트를 만드는 것이었다. 좀 특이한 점이 있다면 글의 형식을 정할 수 있다는 특징이 있었다.

글을 올렸을 때, 화면에서 새로고침 전에는 추가가 안됨

제목과 같은 문제가 있었다. 문제는 state에 대한 초기화가 되지 않는다는 것이었다. 크게 두 가지 방법이 머리에 떠올랐다.

글 업로드 >> firebase 액션 함수를 통해 DB에 업로드 >> Reducer의 액션 함수를 통해 state에도 해당 업로드 반영

글 업로드 >> firebase 액션 함수를 통해 DB에 업로드 >> firebase의 DB를 load 하는 액션 함수 다시 한 번 호출해서 state 초기화

결론적으로 선택은 글을 올리고 나서 DB에서 게시물을 Load 하는 firebase 액션 함수를 한 번 더 호출했다. 리듀서에서 최신화를 할 수 있으나 이 방법은 지난 주 프로젝트에서 사용을 했기 때문에 이번에는 이렇게 해보았다. 하지만 지난 주에 한 방식이 더 좋다고 생각하는 이유는 이번 주에 쓴 방법은 올릴 때 한 번, 로딩할 때 한 번, 총 두 번을 서버에 접근하는 것이기 때문에 서버의 비용을 증가한다고 생각하기 때문이다.

extraReducers 사용방법

toolkit에서 내장 thunk를 쓰려고 했는데 방법을 몰랐다. 지난 주에도 해보고 싶었는데 시간이 없어서 미뤘다. 또 미루기는 싫어서 공식 docs도 보고 조원에게도 물어보면서 찾아본 결과 툴킷 내장 thunk(createAsyncThunk)를 쓸 때 Slice의 extraReducers에서 해당 리듀서를 추가 해주어야 한다는 것을 알게 되었다.

로그인 firebase함수 설계

새로고침 시에 리듀서가 초기화 되기 때문에 그때는 firestore의 userDB에 접근하는 과정이 필요했다. 하지만 문제가 있었는데 이미 그 과정을 담당하는 액션 함수가 있었다.

로그인 과정에서 firebase authentication과 비동기 통신 이후에, firestore userDB에서 유저 정보를 가져와서 유저 리듀서의 state를 초기화 하는 작업을 한 번에 하는 액션 함수가 있었다.

하지만 생각해보면 두 가지 기능을 하나의 함수에 넣은 격이라 잘 만들어진 함수라고 보기도 어려웠다. 그리고 리듀서가 초기화 된 상황에서 DB에만 접근해야 하는 상황에서는 이 두 가지 기능 중 firestore userDB에서 유저 정보를 가져오는 과정만 하는 함수가 필요했다.

결국은 firestore에 접근하는 과정을 따로 하나의 파이어베이스 액션 함수로 만들었다. 이를 통해서 새로고침 시 리듀서 초기화 해결했다.

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { signInWithEmailAndPassword } from "firebase/auth";
import { getDocs, query, collection, where } from "firebase/firestore";
import { db } from "../../shared/firebase";
import { auth } from "../../shared/firebase";

export const FBloginAction = createAsyncThunk(
  "user/login",
  async ({ userId, pw }) => {
    console.log("로그인 파이어베이스 액션함수 시작");
    let loginReq;
    try {
      loginReq = await signInWithEmailAndPassword(auth, userId, pw);
    } catch (err) {
      return console.log("로그인 authentication 액션함수: ", err);
    }

    let user_docs;
    let getUserInfo;
    try {
      user_docs = await getDocs(
        query(
          collection(db, "userDB"),
          where("userId", "==", loginReq.user.email)
        )
      );
      user_docs.forEach((el) => (getUserInfo = { ...el.data() }));
      return getUserInfo;
    } catch (err) {
      return console.log("로그인 firestore 액션함수:", err);
    }
  }
);
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { signInWithEmailAndPassword } from "firebase/auth";
import { getDocs, query, collection, where } from "firebase/firestore";
import { db } from "../../shared/firebase";
import { auth } from "../../shared/firebase";

export const FBloginAction = createAsyncThunk(
  "user/login",
  async ({ userId, pw }) => {
    console.log("로그인 파이어베이스 액션함수 시작");
    try {
      await signInWithEmailAndPassword(auth, userId, pw);
      return auth.currentUser;
    } catch (err) {
      return console.log("로그인 authentication 액션함수: ", err);
    }
  }
);

export const FBloadedAction = createAsyncThunk("user/load", async (param) => {
  const loginReq = { ...param };

  let user_docs;
  let getUserInfo;
  try {
    user_docs = await getDocs(
      query(collection(db, "userDB"), where("userId", "==", loginReq.email))
    );
    user_docs.forEach((el) => (getUserInfo = { ...el.data() }));
    return getUserInfo;
  } catch (err) {
    return console.log("로그인 firestore 액션함수:", err);
  }
});

마무리

나태 지옥에 빠져서 과제를 100% 완성하진 못했지만, 그래도 Redux toolkit을 사용해 보았다는 가장 큰 수확이 있었다. 그래도 조금만 더 시간이 있었으면 과제를 다 할 수 있었을 탠데 하는 생각은 든다. 남은 캠프 기간 동안에는 나태 지옥은 그만...

profile
주먹펴고 일어서서 코딩해

0개의 댓글