본문 바로가기
  • 삽질하는 자의 블로그
메인-프로젝트/React - Do-Health 프로젝트

9. [ 기능 ] FireBase DB 를 이용하기 위해, 데이터 마이그레이션

by 이게뭐당가 2023. 1. 4.

1. 데이터의 틀을 정한다.

    1) 운동방법

     [how-to-workout Page] -> [8개의 부위 Component 들] -> [각 Item은 DesCard 에 데이터]

        [DB "exercise"]
            운동파트 : chest, back, shoulders, biceps, triceps, abs, legs, glutes
            카테고리 : part, name, img, des:[{text}], warn:[{text}]
            
            [ {part:chest, name:체스트프레스, img:"...", 
                des  : [{text:"..."}, { text:"..."}], 
                warn : [{text:"..."}, { text:"..."}],
              },
              {part:back, name:풀업, img:"...", 
                des  : [{text:"..."}, {text:"..."}], 
                warn : [{text:"..."}, { text:"..."}],
              },
              {part:triceps, name:킥백, img:"...", 
                des  : [{text:"..."}, { text:"..."}], 
                warn : [{ text:"..."}, {text:"..."}],
              },
            ]
            
    ** "본래 description 과 warning 은 id 와 text 가 있는 객체값이었으나"
        "DB 의 특성상, id 가 따로 필요 없어서, 제거하고, text 만 남았다."

    2) 음식 리스트

        [DB "foods"]
            category : 다이어트, 벌크업, 린매스업
            name : xxxxxx, 닭가슴살
            majorNutri : 단백질, 지방, 탄수화물
            id : f1, f2 ...
            nutri : 지방 15g ...
            price : 1000 ...
            id / img / category / title / majorNutri / nutri / price

 

2. 데이터베이스에서 직접 하나씩 마이그레이션 하는 것은 너무나 힘들다. 추후 관리를 위해서라도, 

마이그레이션할 페이지를 따로 만든다.

 

< component >

// 아이디 :  e1, e2 ...
// 파트 : chest, back, shoulders, biceps, triceps, abs, legs, glutes
// des : [{id:1, text:"..."}, {id:2, text:"..."}]
// warn : [{id:1, text:"..."}, {id:2, text:"..."}]

    import { FormEvent, useState, useRef } from "react";
    import styles from "./add-exercise.module.css";
    import { postExercise } from "../../helper/add-exercise-fetch";

    const AddExercise = () => {
        const desTextRef = useRef<HTMLInputElement>(null);
        const warnTextRef = useRef<HTMLInputElement>(null);

        const [id, setId] = useState<string>("");
                    ...
        const [warn, setWarn] = useState<{ text: string }[]>([]);

        const AddDes = (event: FormEvent) => {              // description Array 추가
            event.preventDefault();
            const desText = desTextRef.current!.value;

            setDes([...des, { text: desText }]);

            desTextRef.current!.value = "";
        };

        const AddWarn = (event: FormEvent) => {             // warning Array 추가
            event.preventDefault();
            const warnText = warnTextRef.current!.value;

            setWarn([...warn, { text: warnText }]);

            warnTextRef.current!.value = "";
        };
 

        const submitHandler = async (event: FormEvent) => {     // fetch 시작
            event.preventDefault();

            const exerciseData = { id, part, name, img, des, warn };    // fetch 할 데이터
            await postExercise(exerciseData);                // "fetch 아웃소싱"
            setId(() => "");                                // 초기화
                    ...
            setDes(() => []);
            setWarn(() => []);
        };

        return (
            <div className={styles.main_div}>
                <form onSubmit={submitHandler}>
                    <div>
                        <label htmlFor="id"> 아이디 </label>
                        <input
                            placeholder="e1,e2..."
                                ...
                        <label htmlFor="name"> 운동이름 </label>
                        <input
                            placeholder="벤치 프레스, 킥 백, 숄더 프레스..."
                            type={"text"}
                            id="name"
                            value={name}
                            onChange={(e) => setName(e.target.value)}
                        />
                    </div>
                            ...
                    <div>
                        <label htmlFor="des"> 설명 </label>
                                ...
                        <label htmlFor="warn"> 유의사항 </label>
                            <input
                                placeholder="1.xxx, 2.xxx ..."
                                type={"text"}
                                id="warn"
                                ref={warnTextRef}
                                style={{ width: "25rem" }}
                            />
                            {warn.map((item) => (
                                <p key={item.text}>{item.text}</p>
                            ))}
                            <button onClick={AddWarn}> 추가 </button>
                    </div>
                    <div>
                        <button> 제출</button>
                    </div>
                </form>
            </div>
        );
    };

    export default AddExercise;
    

// "des 와 warn 은 배열형태이므로, 배열에 추가하는 버튼과 함수를 따로 만들었다."
// "최종적으로는, 데이터가 전부 담긴 배열이, DB로 넘어갈 것이다"

    <helper - fetch.tsx>

        export type PostType = {
            id: string;
            part: string;
            name: string;
            img: string;
            des: {text: string }[];
            warn: {text: string }[];
        };
        
        export const postExercise = async (exerciseData: PostType) => {
            await fetch("https://do-health-project-default-rtdb.firebaseio.com/exercise.json", {
                method: "POST",
                body: JSON.stringify(exerciseData),
                headers: {
                    "Content-Type": "application/json",
                },
            });
        };
        
// 따로, helper 함수 아웃소싱하여, 컴포넌트의 코드를 줄였다.

댓글