본문 바로가기

회고/스파르타 코딩클럽

[리액트 심화반] 3주차 개발일지

1. 배운 내용

파이어스토어로 데이터 관리하기

파이어베이스의 스토리지 서비스를 이용하여 이미지 업로드하기

파일 업로드 전 이미지 미리보기 구현

잦은 이벤트 처리 기법

 

 

2. 새로 알게 된 내용

1) 파이어스토어 연동하기

- firebase.js에서 파이어스토어 추가

import "firebase/firestore";
...
const firestore = firebase.firestore();
...
export{auth, apiKey, firestore};

- 파이어스토어에서 데이터 가져오기

import { firestore } from "../../shared/firebase";
...
const getPostFB = () => {
  return function (dispatch, getState, { history }) {
    const postDB = firestore.collection("post");

    postDB.get().then((docs) => {
      let post_list = [];

      docs.forEach((doc) => {
        // 잘 가져왔나 확인하기! :)
        // 앗! DB에서 가져온 것하고 우리가 Post 컴포넌트에서 쓰는 데이터 모양새가 다르네요!
        // console.log(doc.id, doc.data());

        // 데이터 모양을 맞춰주자!
        let _post = doc.data();
        let post = {
            id: doc.id,
            user_info: {
                user_name: _post.user_name,
                user_profile: _post.user_profile,
                user_id: _post.user_id,
            },
            contents: _post.contents,
            image_url: _post.image_url,
            comment_cnt: _post.comment_cnt,
            imsert_dt: _post.insert_dt
        }

        post_list.push(post);
      });

      // 리스트 확인하기!
      console.log(post_list);

      dispatch(setPost(post_list));
    });
  };
};
...

- 컴포넌트에서 호출하기

import React from "react";

import Post from "../components/Post";
import {useSelector, useDispatch} from "react-redux";
import {actionCreators as postActions} from "../redux/modules/post";


const PostList = (props) => {
    const dispatch = useDispatch();
    const post_list = useSelector((state) => state.post.list);

    console.log(post_list);

    React.useEffect(() => {
        dispatch(postActions.getPostFB());

    }, []);

    return (
        <React.Fragment>
            {post_list.map((p, idx) => {

                return <Post key={p.id} {...p}/>
            })}
        </React.Fragment>
    )
}

export default PostList;

 

2) 이미지 프리뷰 구현

- FileReader 써보기

const selectFile = (e) => {
    // e.target은 input이죠!
    // input이 가진 files 객체를 살펴봅시다.
    console.log(e.target.files);
    // 선택한 파일이 어떻게 저장되어 있나 봅시다.
    console.log(e.target.files[0]);

    // ref로도 확인해봅시다. :)
    console.log(fileInput.current.files[0]);

    const reader = new FileReader();
    const file = e.target.files[0];

    // 파일 내용을 읽어옵니다.
    reader.readAsDataURL(file);

    // 읽기가 끝나면 발생하는 이벤트 핸들러예요! :)
    reader.onloadend = () => {
      // reader.result는 파일의 컨텐츠(내용물)입니다!
      console.log(reader.result);
    };
  };

- 리덕스에 preview를 넣어주기 👉🏻 액션 만들고, initialState에도 넣어주고, 리듀서 작성하고, 액션을 내보낸다.

- <PostWrite />에서 미리보기 이미지 넣어주기

...

const PostWrite = (props) => {
  const dispatch = useDispatch();
  const is_login = useSelector((state) => state.user.is_login);
  const preview = useSelector((state) => state.image.preview);
  
	...
    return (
      <React.Fragment>
				...
          <Image
            shape="rectangle"
            src={preview ? preview : "http://via.placeholder.com/400x300"}
          />
        ...
      </React.Fragment>
    );
}

export default PostWrite;

- <Upload />에서 액션을 dispatch 해주면 끝!

const selectFile = (e) => {
    // e.target은 input이죠!
    // input이 가진 files 객체를 살펴봅시다.
    console.log(e.target.files);
    // 선택한 파일이 어떻게 저장되어 있나 봅시다.
    console.log(e.target.files[0]);

    // ref로도 확인해봅시다. :)
    console.log(fileInput.current.files[0]);

    const reader = new FileReader();
    const file = e.target.files[0];

    // 파일 내용을 읽어옵니다.
    reader.readAsDataURL(file);

    // 읽기가 끝나면 발생하는 이벤트 핸들러예요! :)
    reader.onloadend = () => {
      // reader.result는 파일의 컨텐츠(내용물)입니다!
      console.log(reader.result);
      dispatch(imageActions.setPreview(reader.result));
    };
  };

- <input/>(인풋 태그)를 사용해서 유저가 선택한 파일을 File 객체로 받아온다. FileReader는 이 파일의 내용을 읽어 온다. 이 내용을 가지고 미리보기도 만들 수 있고 다른 이름으로 저장도 할 수 있게 해준다.

 

3) Debounce와 Throttle

- changeText 함수가 발생할 때마다 api 요청을 하면 너무 많은 요청이 되므로 처리하는 기술이 필요하다.

- debounce란? 이벤트가 일어나면, 일정시간을 기다렸다가 이벤트를 수행함. 일정 시간 내에 같은 이벤트가 또 들어오면 이전 요청은 취소함.

import React from "react";
import _ from "lodash"; // lodash 부르기

const Search = () => {
  const debounce = _.debounce((k) => console.log("디바운스! :::", k), 1000);
  const keyPress = React.useCallback(debounce, []);

  const onChange = (e) => {
    keyPress(e.target.value);
  };

  return (
    <div>
      <label>Search:</label>
      <input onChange={onChange} />
    </div>
  );
};

export default Search;

- throttle이란? 일정 시간 동안 일어난 이벤트를 모아서 주기적으로 1번씩 실행해준다.

import React from "react";
import _ from "lodash"; // lodash 부르기

const Search = () => {
  const throttle = _.throttle((k) => console.log("쓰로틀! :::", k), 1000);
  const keyPress = React.useCallback(throttle, []);

  const onChange = (e) => {
    keyPress(e.target.value);
  };

  return (
    <div>
      <label>Search:</label>
      <input onChange={onChange} />
    </div>
  );
};

export default Search;

 

 

3. 느낀 점

지금 일하고 있는 곳도 이벤트가 많이 발생해서 최대한 줄이려고 노력하고 있는데 잦은 이벤트 처리 기법을 배워서 써먹어보려고 한다. 특히 리액트 기술 기반이라 잘 쓸 수 있을 것 같다. 파이어스토어로 게시물 데이터들을 관리하는 방법은 클라우드 서비스에서 처음 써보는 것 같다. 매번 aws에서 mysql 올려두는 식으로 진행했었는데 색달라서 좋았다. 특히 파이어베이스가 좀 더 aws보다는 친절하다는 생각이 들었다.

 

 

반응형