반응형

요약

React, Firebase 활용한 뉴스피드 프로젝트

뉴스 피드란? 내 게시물을 포함한 모든 게시물을 볼 수 있는 공간( 커뮤니티(o), 뉴스(x)

사용된 주요 기능

react, firebase, redux


고민한 내용

 

처음 팀장을 맡아서 뼈대 만드는 작업을 하는 것부터 쉽지 않았다.

다들 작업을 바로 할 수 있게 빠르게 넘겨줘야하는데 무엇들이 필요할지 몰라 고민을 많이했다.

그리고 뼈대를 넘겨줬지만 디자인 작업을 추후에 하자곤 했지만 뼈대만 두고 작업하기엔 다들 너무 힘이 들거같았다.

그래서 큰 틀을 잡으면서 아예 로고나 전체적인 UI는 대략적이지만 잡은 상태로 넘겼다.

메인 컬러나 서브 컬러 등도 다들 컴포넌트로 사용하기 좋게끔..그래서 언제든 바꿀 수 있게..

나중에 시간이 나는 누군가가 바꾸길 했지만, 아무도 시간이 안나 디자인과 컬러 그대로 간건 안비밀..

 

Firebase?

파이어베이스도 듣기만 했지만 실제로 한번도 사용해보지 못했다.

작업에 앞서 작업을 들어가기 좋게끔 설명이 굉장히 상세하게 적혀있어서 어려움은 없겠다 싶었지만,

처음 해보는 것에 대한 두려움이 컸다. 일단은 부짖혀보잔 마음으로 시작

 

Authentication? Cloud Firestore? Storage?

파이어베이스에서 다루는 데이터들은 총 3가지로 나뉘게 된다.

Authentication은 사용자 계정정보
Cloud Firestore은 기본 데이터 정보
Storage는 파일 업로드 정보

 

일단 내가 맡은 꼭지가 마이페이지의 프로필 정보와 변경을 다루게 되서 두가지만 사용해볼 생각이었다.

하지만 하다보니 내 게시물도 보게되는 부분이 필요해서..

그리고 나중에 수정삭제도 맡게되면서 세가지 다 경험해볼 수 있었다. 오히려 좋아...좋아..


주요 기능들

 

주요 작업한 코드들은 주제별로 크게 3개로 나뉘게 됐다.

 

1. 프로필 수정

 

작업하기 전에 로그인 작업이 끝나지 않았기에 임의의 정보를 가지고 테스트를 해봤었다. 

파이어베이스에서는 임의의 데이터를 넣고 지워볼 수 있어서 테스트하기가 수월했다.

// 사용자 프로필 업데이트
  const updateProfileHandler = async (editName, downloadURL) => {
    try {
      const userCredential = await updateProfile(auth.currentUser, {
        displayName: editName,
        photoURL: downloadURL
      });
      setProfileName(editName);
      setProfileImg(downloadURL);
      console.log(userCredential, "userCredential");
    } catch (error) {
      console.error(error);
    }
  };

  const [userId, setUserId] = useState(auth.currentUser != null ? auth.currentUser.uid : null);
  const [selectedFile, setSelectedFile] = useState(null);
  const [profileImg, setProfileImg] = useState(auth.currentUser != null ? auth.currentUser.photoURL : null);
  const [profileEmail, setProfileEmail] = useState(auth.currentUser != null ? auth.currentUser.email : null);
  const [profileName, setProfileName] = useState(auth.currentUser != null ? auth.currentUser.displayName : null);

  const handleFileSelect = async (event) => {
    setSelectedFile(event.target.files[0]);
    console.log(event.target.files[0]);
    const reader = new FileReader();
    reader.readAsDataURL(event.target.files[0]);
    return new Promise((resolve) => {
      reader.onload = () => {
        setProfileImgChange(reader.result);
        setProfileImg(event.target.files[0]);
        resolve();
      };
    });
  };

  // 프로필 수정 접근
  const [desc, setDesc] = useState("");
  const [profileImgChange, setProfileImgChange] = useState(profileImg);

  const editProfileHandler = () => {
    setDesc(profileName == null ? "" : profileName);
    setProfileImgChange(profileImg == null ? "" : profileImg);
    setModalSwitch(true);
  };

  // 프로필 수정 확인
  const editProfileChange = async () => {
    console.log(selectedFile);
    let downloadURL = null;
    if (selectedFile != null) {
      // ref 함수를 이용해서 Storage 내부 저장할 위치를 지정하고, uploadBytes 함수를 이용해서 파일을 저장합니다.
      const imageRef = ref(storage, `profile/${auth.currentUser.uid}/${selectedFile.name}`);
      await uploadBytes(imageRef, selectedFile);
      // 파일 URL 가져오기
      downloadURL = await getDownloadURL(imageRef);
    }
    updateProfileHandler(desc, downloadURL);

    setModalSwitch(false);
  };

 

 

2. 내 게시물 보기 + 내 게시물 삭제

 

내 게시물을 확인하기만 하면 될 줄 알았는데, 생각해보니 메인에서도 내 게시물을 수정 삭제할 수 있는데

마이페이지에서 수정삭제가 안되면 이상한게 당연.

해당 게시물을 클릭하면 데이터를 가져온 후 수정,삭제 기능 후에 실제 데이터에서도 삭제 되게끔 작업

메인에서도 삭제 기능은 그대로 사용했다.

 

  // 내 게시물 확인
  const [writes, setWrites] = useState([]);
  useEffect(() => {
    const fetchData = async () => {
      const q = query(collection(db, "writes"), orderBy("fullDate", "desc"));
      const querySnapshot = await getDocs(q);
      const initialWrites = [];
      querySnapshot.forEach((doc) => {
        const data = {
          id: doc.id,
          ...doc.data()
        };

        initialWrites.push(data);
      });

      // firestore에서 가져온 데이터를 state에 전달
      setWrites(initialWrites);
    };

    fetchData();
  }, []);

  const [writeTextEdit, setWriteTextEdit] = useState("");
  
  // 내 게시물 삭제
  const deleteWrite = async (write) => {
    const writeRef = doc(db, "writes", write.id);
    await deleteDoc(writeRef);

    setWrites((prev) => {
      return prev.filter((element) => element.id !== write.id);
    });
  };
  
  // 게시물 수정
  const editWrite = (write) => {
    setModalSwitchMyWrite(true);
    setWriteTextEdit(write.text);
  };

  // 게시물 수정 취소
  const cancelEditWrite = () => {
    setModalSwitchMyWrite(false);
  };

  // 게시물 수정 확인
  const submitEditWrite = async (write) => {
    if (writeTextEdit === write.text) return alert("기존 내용과 같습니다.");

    const writeRef = doc(db, "writes", write.id);
    await updateDoc(writeRef, { text: writeTextEdit });
    setWrites((prev) => {
      return prev.map((element) => {
        if (element.id === write.id) {
          return { ...element, text: writeTextEdit };
        } else {
          return element;
        }
      });
    });

    setModalSwitchMyWrite(false);
    setModalDetailSwitch(false);
  };

  // 게시물 수정 텍스트 확인
  const onChangeText = (event) => {
    setWriteTextEdit(event.target.value);
  };

  
  const [modalDetailSwitch, setModalDetailSwitch] = useState(false);
  const [modalDetailContent, setModalDetailContent] = useState({});
  
  // 리스트 상세보기 관련
  const detailItem = (write) => {
    setModalDetailSwitch(true);
    setModalDetailContent({ id: write.id, email: write.email, date: write.date, text: write.text });
  };

 

 

 


결과 화면

 


회고

 

다른 것보다 좋아요 기능이나 여러가지 기능을 더 넣어보고 싶었는데, 시간이 안되서 못한게 아쉽다.

그리고 시간이 쫓기다보니 코드가 쓸데없이 길어지는 느낌을 많이 받았고,

무엇보다!

이번 프로젝트를 진행하면서 와이어프레임을 좀 더 디테일하게 했어야하는구나..라는 생각을 많이 했다.

중간 중간 '아! 이거 필요한데!' 하면서 팀원들과 다시 소통하며 맞추는 딜레이들이 많았다

다음에는 초반 시간이 많이 뺏기더라도 디테일하게 짜보는게 필요할거 같다.

반응형