개인 프로젝트(고민 상담소)

개인 포트폴리오 고민 상담소 #2

해기97 2023. 8. 5. 19:16

저번 시간에 이어서 계속 ..

 

일단 저번 시간에는 간단한 라이브러리들을 설치 및 세팅? 을 끝내두고 헤더와 사이드 메뉴를 완성했고

 

사이드 메뉴에는 리덕스 툴킷을 사용해서 관리해주고있다. 리덕스 툴킷을 사용한 이유는 이제와 생각해보니 실수로 인한..것..

 

사이드 메뉴의 사이즈를 높이 100퍼를 주어야하는 것 때문에 header에서 관리하지않고 layout으로 옮겨서 작업을했는데

생각해보니 높이 100퍼가 제대로 안먹었던 이유가 position abolute를 줘버렸기 때문이었다...........(fixed를 사용했어야 했는데)

 

이 부분을 새롭게 수정한 뒤 다시 작업을 해줘야겠다. (그래도 그 덕에 리덕스 툴킷에 대한 간단한 사용방법은 익히게됐다.)

 

좋게좋게 생각하고 새롭게 작업하자..

 


사이드 메뉴 옮겨주기

 

내 실수를 인정하고 후다닥 헤더로 옮겨버리자.

(리덕스 툴킷을 사용한 이유가 layout에 헤더와 사이드 메뉴 둘 다 존재했었고 그 상태를 관리하기위해 layout에 코드를 작성하기 싫고 state를 넘겨주기 번거로울 것 같아서 그렇게 작업을 했었다.)

 

그래도 이미 만들어 둔 사이드 메뉴 styled를 그대로 가져오면 뚝딱이라 쉽게 끝날 것 같다.

 

여기서 컴포넌트를 자주 분리해주면 좋다는 장점을 알게되었다..! 사이드 메뉴를 따로 컴포넌트로 만들어서 사용을 했었는데 헤더에서 그냥 사용만 해주면 끝이었다..! (기분이 좀 좋았음)

 

다만 여기서 이제 리덕스 툴킷을 사용한 것 까지 지워야할까? 라는 생각을 하긴했는데.. 콘솔창에 자꾸 에러가 뜨는게 보기싫어서 한번 바꿔보기로 했다.

 

기존에 사용중이던 리덕스 툴킷에서 만들고 커스텀 훅으로 만든 버튼을 주석처리해주고 새롭게 만들어서

props로 상태를 넘겨주고 그 상태로 사이드 메뉴를 관리해줬는데 아직까지 콘솔창에 에러가 나고있다..

 

결론은 일단 리덕스 툴킷으로 인한 에러는 아니라는 것이기에 그냥 리덕스 툴킷으로 만든 기능은 그대로 사용해도 될 것 같다.

 

일단 이 콘솔창 에러를 해결하고 넘어가고싶은데

 

처음 발생한 이 에러는

styled components에 넘겨줄 props인 menuState를 menustate로 소문자로 변경해주니 해결이되긴했는데

다음으로는 이러한 에러가 나타났다.. 뭐지? 제대로 사용하고 있는 것 같은데

천천히 고쳐보자,,

 


파이어베이스 데이터베이스 가져오기

 

일단 supabase를 사용하려 했다가 빠르게 포기하고 다시 파이어베이스로 넘어왔는데 공식 문서를 참고해서 데이터베이스 데이터를 가져오는 것은 쉽게 해결 됐다.

 

평소에는 공식문서를 잘 안보는 인간이지만,, 공식문서가 중요하다는 얘기를 듣고 열심히 보려하는 편이고 이번에는 공식문서를 통해 해결이됐다.

 

https://firebase.google.com/docs/firestore/quickstart?hl=ko#read_data 

 

Cloud Firestore 시작하기  |  Firebase

Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Cloud Firestore 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 빠른

firebase.google.com

 

데이터 읽기 부분의 코드를 따라하며 해결을 했으며 나는 카테고리를 총 3개 익명 고민 게시판, 비밀 고민 게시판, 잡담소를 만들 예정이기에 한번 데이터를 가져오는 코드를 세 곳에서 사용할 수 있도록 만드는 걸 목표로 했다.

 

useFetchData 라는 커스텀 훅을 만들어 사용하기로했고

 

import { collection, getDocs } from "firebase/firestore/lite";
import { db } from "../api/firebase";
import { useEffectOnce } from "usehooks-ts";

type useFetchDataProps ={
    collectionName: string
}

export default function useFetchData({collectionName}: useFetchDataProps) {
    useEffectOnce(()=>{
        const fetchData = async () => {
            try{
                const querySnapshot = await getDocs(collection(db,collectionName));
                querySnapshot.forEach((doc)=>{
                console.log(doc.data())
            })}catch(error){
                console.error(`${error}에러뜨는중`)
            }
        }

        fetchData()
    })
}

위와 같이 커스텀 훅이 완성이 되었다.

 

처음에는 useEffect를 사용하지 않고 만들었었으며 내가 사용하려는 컴포넌트에서 useEffect안에 커스텀 훅을 넣으니 에러가 발생했었다. (훅 규칙 위반인가..? 잘 모르겠다..)

 

그래서 커스텀 훅 만든 곳에서 useEffect를 사용해버리자 라는 생각에 만들어주니 제대로 작동을 하고있다.

 

collection에서 파이어베이스 데이터베이스에 컬렉션 이름을 미리 직접 박아두는 것이 아닌 이 커스텀 훅을 사용할 때

 

export default function HomePage(){

    useFetchData({ collectionName: 'anonymous' })

이 처럼 그 컴포넌트에서 사용할 컬렉션 이름을 넣어주기 위해 파라미터를 뚫어두었다.

 

위 커스텀 훅을 사용했을 때 정상적으로 작동하는지가 가장 중요하기에 시험해보기로 했다.

 

일단 아래와 같이 파이어베이스 데이터베이스에 컬렉션을 두가지만 미리 만들고 임시로 데이터로 사용할 문서를 하나씩 넣어두었다.

 

콘솔창에 데이터가 찍히게 끔 만들어 두었으니 익명게시판과 비밀게시판을 오가며 확인해봤을 때

 

그 페이지의 데이터를 그 페이지로 이동할 때 마다 불러오는걸 볼 수 있었다.

 

이제 화면을 구성해주고 글 쓰기 기능을 만들어주면 반 이상은 끝이라고 보면 될 것 같다..!

 


게시판 꾸미기

 

이제 게시판을 꾸며주어야한다.. 가장 고민되는 부분이기도 하며 시간을 많이 쓸 것 같은 부분이기도 하다.

 

포폴용이라 하지만 예쁜게 보기좋은법.. 그리고 카테고리 세 개의 글 목록이 모두 다른 모양을 띄고있기 때문에 고민이 더 많이되는 것 같다.

 

모든 게시판이 다 똑같이 표시가 된다면 한 컴포넌트를 간단히 만들어서 사용하면 되겠지만 지금 내가 구현하는 것은

 

익명 게시판은 닉네임이 익명이어야하기에 리스트 목록에서는 닉네임이 표시가 안될 것이고

비밀 게시판은 이 서비스의 고해성사마냥,, 서비스의 주인인 나만 볼 수 있게 표시가 될 것 이고 다른사람들은 모두 똑같은 제목으로 표시가 되게끔 만들어 둘 것..

잡담소는 말 그대로 잡담소라 유저의 닉네임, 제목, 사진? 등등 모든걸 표현해주어야하기에 게시판 마다 달라서 고민이 많이 되고있는 상태이다.

 

그냥 하나로 통일해버릴까 싶기도하고.. 일단 하나부터 완성을 해보자.

 

대충 일단 만들었고 코드를 살펴보면

import { styled } from "styled-components"
import { ListItemType } from "../types/types"

const ContainerUl = styled.ul`
    width: 100%;
    li{
        display: flex;
        justify-content: space-between;
        padding: 15px;
        border-bottom: 1px solid;
        margin-bottom: 10px;
        background-color: green;
        cursor: pointer;
        span:last-child{
            width: 20%;
            text-align: end;
        }
    }
`

type ListUlProps = {
    listData: ListItemType[]
}

export default function ListUl({listData}:ListUlProps){

    return(
            <ContainerUl>
                {listData.map((item:ListItemType)=>{
                    return(
                        <li key={item.title}>
                    <span>
                        {item.title}
                    </span>
                    <span>{item.date}</span>
                </li>
                    )
                })}
            </ContainerUl>
    )
}

이곳에서 관리해주기로 했다. 이 컴포넌트를 가지고 다른 카테고리에서 사용해준다면 넘겨주는 listData만 다르면 다른 아이템들을 불러올 수 있을 것 같다.

 

아직은 추측이니 시험해봐야겠다..

 

꽤나 생각한 대로 깔끔하고 제대로 작동하는 코드가 완성됐다..! 기분이 꽤 많이 좋을지도?

 

아마 추후 잡담소는 따로 리스트를 새로 디자인해서 만들까 하고 생각중이라 지금 바로 하지말고 나중에.. 하자.. 아이디어가 떠오를 때

 


오늘 해낸 것

 

오늘 이룬 것은 콘솔창에 뜨던 스타일드 컴포넌트에 대한 에러와 목록 리스트를 대충 만들어주기 그리고 데이터 가져오는 커스텀 훅 살짝 수정해주기

 

하나씩 살펴보면 스타일드 컴포넌트에서 정상적으로 작동하지만? 콘솔창에서 자꾸 에러를 띄워주는 상황이 발생했었다. GPT에게 물어봐도 해결이 안되는 상황이었고 오늘 다른 분들에게 물어보면서 props에 넘겨줄 때 boolean이 아닌 문자열로 넘겨주어야 한다는 html 속성값? 에 대한걸 얘기해주셔서 검색 조금 해보니 해결할 수 있는 글을 발견했다.

 

https://velog.io/@jiwonyyy/Styled-components%EC%97%90%EC%84%9C-props-%EB%98%91%EB%98%91%ED%95%98%EA%B2%8C-%EB%84%98%EA%B2%A8%EC%A3%BC%EA%B8%B0-feat.-Received-true-for-a-non-boolean-attribute

 

💅Styled-components에서 props 똑똑하게 넘겨주기 (feat. Received `true` for a non-boolean attribute)

styled-component에서 prefix를 사용하여 props를 전달해주자!

velog.io

 

접두사 $를 사용하게되면 이를 해결해줄 수 있다는 글이었다. 그리고 공식 문서에서도 $를 붙여서 사용하는걸 보고온 뒤 바로 사용해보았는데

 

props로 넘겨줄 때 $를 붙여서 이름을 지어주고 사용했더니 에러가 나타나지않게되었다..!

 

HTML 표준 속성때문이라는데 접두사 $를 사용하면 해결이 된다. 아주 유용하게 사용될 것 같으니 꼭 기억해두자

 

두번째로 데이터 받아오는 커스텀 훅을 약간 수정해줬다.

 

전에는 그냥 데이터만 받아와서 그냥 그 데이터 째로 넘겨주었기 때문에 무언가 꺼내쓰기가 애매했었다.

그래서 커스텀 훅에서 useState를 사용하여 그 데이터를 담아둘 곳을 만들고 담아 둔 뒤 state를 내보내주는 코드로 약간의 변경을 해주었다.

 

import { collection, getDocs } from "firebase/firestore/lite";
import { db } from "../api/firebase";
import { useEffectOnce } from "usehooks-ts";
import { useState } from "react";
import { ListItemType } from "../types/types";

type useFetchDataProps ={
    collectionName: string
}

export default function useFetchData({collectionName}: useFetchDataProps) {

    const [data,setData] = useState<ListItemType[]>([])

    useEffectOnce(()=>{
        const fetchData = async () => {
            try{
                const querySnapshot = await getDocs(collection(db,collectionName));
                const fetchedData: any = [];
                querySnapshot.forEach((doc)=>{
                    fetchedData.push(doc.data())
                setData(fetchedData)
            })}catch(error){
                console.error(`${error}에러뜨는중`)
            }
        }

        fetchData()
    })
    return data
}

이제 밖에서 사용할 때

위 처럼 받아와 사용하면 listData에 데이터가 잘 넘어와있는걸 볼 수 있고 listData를 사용해주면 끝이다.

 

아직까지는 코드가 깔끔하게 작성이 잘 되어가고 있는 듯 하고 모르던 부분에서도 이해가 하나씩 되어가고있다.

 

아마 스타일드 컴포넌트는 조금 더 예쁘게 사용하는 방법을 찾아봐야할 것 같다.