팀프로젝트

뉴스피드 프로젝트 작성폼 페이지 구현하기

choijming21 2024. 8. 30. 21:05

내가 맡은 부분은 작성폼 페이지이다! 오늘은 작성폼 페이지 기능구현에 대해서 블로그를 써보겠다.

 

 

 

진짜 뼈대만...... 디자인 빨리 고쳐주고 싶다..

 

 

 

 

 

 

 

1. 상태 관리

일단 상태관리는 useState 훅을 사용하여 폼데이터를 관리한다. 각 입력 필드에 대한 상태를 하나의 객체로 관리하고 있다.

const [formData, setFormData] = useState({
  storeName: '',
  image: null,
  address: '',
  region: '',
  rating: '',
  review: ''
});

 

 

 

 

 

2. Context 사용

PostContext를 통해 전역 상태를 관리하고 있다. 이를 통해 게시물 목록을 업데이트할 수 있다.

const { posts, setPosts } = useContext(PostContext);

 

 

 

 

 

 

3. 이벤트 핸들러

입력 변경 핸들러: 각 입력 필드의 변경을 감지하고 상태를 업데이트한다.

const handleChange = (e) => {
  const { id, value } = e.target;
  setFormData((prevData) => ({ ...prevData, [id]: value }));
};

 

 

 

 

 

 

4. 파일 변경 핸들러

이미지 파일 선택 시 상태를 업데이트한다.

const handleFileChange = (e) => {
  setFormData((prevData) => ({ ...prevData, image: e.target.files[0] }));
};

 

 

 

 

 

 

 

5. 폼 제출 처리

handleSubmit 함수에서 폼 제출 처리를 한다. 

만약에 이미지 파일이 있으면 Supabase 스토리지에 보내고 없으면 null을 보낸다. 그다음 스토리지에서 이미지의 공개 URL을 가져온다.

그럼 다시 각종 폼 정보를 객체로 받아서 Supabase로 다시 보낸다. 스토어에서 보낼 때, data와 error값을 받는다. data는 업로드가 성공했을 때 반환되는 객체로 업로드된 파일에 대한 메타 데이터를 포함한다. error는 업로드 과정에서 문제가 발생했을 때 반환되는 객체이다. error가 만약있다면 오류 메세지를 띄어주도록 했다. 

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      let imagePath = null;

      // 이미지 업로드
      if (formData.image) {
        const fileName = `store_img_${Date.now()}.png`;
        const { error } = await supabase.storage.from('store_img').upload(`public/${fileName}`, formData.image);

        if (error) throw error;

        // 업로드 된 이미지의 공개 URL 가져오기
        imagePath = `${supabase.storage.from('store_img').getPublicUrl(`public/${fileName}`).data.publicUrl}`;
      }

      const { data, error } = await supabase.from('store').insert({
        writer: 'coolcat1',
        store_name: formData.storeName,
        image: imagePath,
        address: formData.address,
        location: formData.region,
        star: formData.rating,
        comment: formData.review
      });

      console.log('응답값', data);

      if (error) throw error;
      console.log('게시물이 성공적으로 생성되었습니다', data);

      setFormData({
        storeName: '',
        image: null,
        address: '',
        region: '',
        rating: '',
        review: ''
      });

      alert('게시물이 성공적으로 작성되었습니다!');
    } catch (error) {
      console.error('게시물 작성 중 오류 발생', error.message);
      alert('게시물 작성 중 오류 발생 다시 시도 바란다.');
    }
  };

 

 

 

 

 

 

 

 

6. 기본적인 UI

뼈대 정도만 잡아주었다. 여기서 새로 배운 내용은 <select>이다. 드롭다운 목록의 컨테이너 역할을 한다. <option>는 select 내부에 위치하며, 각각의 선택 가능한 항복을 나타낸다.

  return (
    <SyFormContainer>
      <h2>맛집 게시글 작성</h2>
      <form onSubmit={handleSubmit}>
        <div>
          <label htmlFor="storeName">가게 상호명</label>
          <input id="storeName" type="text" value={formData.storeName} onChange={handleChange} />
        </div>

        <div>
          <label htmlFor="image">이미지 업로드</label>
          <input id="image" type="file" accept="image/*" onChange={handleFileChange} />
        </div>

        <div>
          <label htmlFor="address">주소</label>
          <input id="address" type="text" value={formData.address} onChange={handleChange} />
        </div>

        <div>
          <label htmlFor="region">지역</label>
          <select id="region" value={formData.region} onChange={handleChange}>
            <option value="">선택하세요</option>
            <option value="지역1">지역1</option>
            <option value="지역2">지역2</option>
            <option value="지역3">지역3</option>
            <option value="지역4">지역4</option>
            <option value="지역5">지역5</option>
          </select>
        </div>

        <div>
          <label htmlFor="rating">별점</label>
          <select id="rating" value={formData.rating} onChange={handleChange}>
            <option value="">선택하세요</option>
            <option value="1">1점</option>
            <option value="2">2점</option>
            <option value="3">3점</option>
            <option value="4">4점</option>
            <option value="5">5점</option>
          </select>
        </div>
        <div>
          <label htmlFor="review">후기</label>
          <textarea id="review" rows="5" value={formData.review} onChange={handleChange}></textarea>
        </div>
        <div>
          <button type="submit">게시글 등록</button>
        </div>
      </form>

      {/* <div>
        {posts.map((post) => (
          <WriteList key={post.id} post={post} />
        ))}
      </div> */}
    </SyFormContainer>
  );
};

export default WriteFormContainer;

 

 

 

 

 

 

팀프로젝트 시 오류와 해결방안

 

❌ Supabase 접근 못하는 문제점

  • RLS를 비활성화하여 문제 해결
  • RLS(Row Level Security)는 supabase에서 제공하는 보안 기능이다.
  • 데이터베이스테이블의 각 행(row)에 대한 접근을 제한한다.
  • 사용자 권한에 따라 특정 데이터만 읽거나 수정할 수 있도록 제한한다.
  • 따라서 RLS를 비활성화하면 모든 사용자가 해당 테이블의 모든 데이터에 접근할 수 있게 된다.
  • https://github.com/orgs/supabase/discussions/3780
 

SOLVED Empty Array · supabase · Discussion #3780

SOLVED Hello i get empty array when i query my data? is anyone know how to fix i t ?

github.com

 

 

 SupabaseClient에 supabase URL,KEY 값을 불러오지 못하는 오류

  • .env.local 로 파일을 만들었는데 키값을 불러오지 못해서 .env로 파일명으로 바꿔주었더니 해결
  • .env.local은 로컬 환경에서만 사용되며, 일반적으로 버전 관리에서 제외된다.
  • .env는 모든 환경에서 사용되며, 일반적으로 버전 관리에 포함된다.
  • 따라서 .env 파일은 모든 환경에서 기본적으로 로드될 수 있어 키값을 불러올 수 있지만 이 파일은 버전 관리 시스템에 포함될 수 있으므로 주의가 필요하다.