본문 바로가기

카테고리 없음

supabase 셋업 (서버 및 DB 셋업)

회원 가입과 로그인 등 회원 관리를 구현하려면 백엔드와 데이터베이스(DB)가 필요하다.

하지만 이러한 기능을 직접 구현하는 데는 많은 시간이 걸린다.

다행히도, 이러한 작업을 쉽게 구현할 수 있는 플랫폼들이 있다.

 

 

superbase란

Supabase는 Firebase와 유사한 기능을 제공하는 오픈 소스 백엔드 플랫폼이며 웹 및 모바일 애플리케이션을 쉽고 빠르게 구축할 수 있도록 다양한 도구와 서비스를 제공한다.

쉽게말해 BaaS (Backend as a Service)로써 백엔드(+DB) 기능을 제공한다.

 

 

 

프로필사진변경 기능구현하기

1. Supabase 설정

Supabase를 사용하여 파일을 저장하고 사용자 프로필을 관리할 수 있습니다. Supabase는 백엔드 서비스로, 데이터베이스와 스토리지 기능을 제공합니다.

 

2. Supabase 클라이언트 설정

먼저, Supabase 클라이언트를 설정하여 프로젝트에서 Supabase와 통신할 수 있도록 한다.

 

supabaseClient.js

import { createClient } from '@supabase/supabase-js';

const supabaseKey = 'your-supabase-anon-key';

export const supabase = createClient(supabaseUrl, supabaseKey);

Supabase 클라이언트를 설정하여 프로젝트에서 Supabase API를 사용할 수 있게 합니다.

 

3. 파일 업로드 기능 추가 및 모달 수정

프로필 수정 모달에서 파일 업로드 입력을 추가한다. 사용자가 파일을 선택하면, 해당 파일을 Supabase 스토리지에 업로드하고, 업로드된 파일의 URL을 사용자 프로필에 저장한다.

 

MyPageModal 컴포넌트

import React, { useState } from 'react';
import { supabase } from '../supabaseClient';

export default function MyPageModal({ isVisible, onClose }) {
    const [file, setFile] = useState(null);

    const handleFileChange = (e) => {
        setFile(e.target.files[0]);
    };

    const handleSubmit = async (e) => {
        e.preventDefault();
        if (!file) return;

        // Upload file to Supabase
        const { data, error } = await supabase.storage
            .from('profiles')
            .upload(`public/${file.name}`, file);

        if (error) {
            console.error('Error uploading file:', error);
            return;
        }

        const fileUrl = supabase.storage
            .from('profiles')
            .getPublicUrl(`public/${file.name}`).publicURL;

        // Update user profile with new image URL
        const { error: updateError } = await supabase
            .from('profiles')
            .update({ avatar_url: fileUrl })
            .eq('id', 'user-id');  // Update with the correct user ID

        if (updateError) {
            console.error('Error updating profile:', updateError);
        } else {
            onClose();  // Close the modal on success
        }
    };

    if (!isVisible) return null;

    return (
        <div className="fixed inset-0 flex items-center justify-center z-50">
            <div className="bg-white p-5 rounded shadow-lg">
                <h2 className="text-xl mb-4">프로필 수정</h2>
                <form onSubmit={handleSubmit}>
                    <div>
                        <label className="block mb-2">프로필 사진 업로드</label>
                        <input type="file" onChange={handleFileChange} />
                    </div>
                    <button type="submit" className="mt-4 p-2 bg-blue-500 text-white rounded">저장</button>
                    <button type="button" onClick={onClose} className="mt-4 ml-2 p-2 bg-gray-500 text-white rounded">취소</button>
                </form>
            </div>
        </div>
    );
}
  • 파일 선택: 사용자가 파일을 선택할 수 있도록 <input type="file" /> 요소를 추가
  • 파일 업로드: supabase.storage.from('profiles').upload() 메서드를 사용하여 파일을 Supabase 스토리지에 업로드
  • URL 저장: 업로드된 파일의 URL을 Supabase 데이터베이스에 사용자 프로필의 avatar_url 필드에 저장

 

4. 마이페이지 컴포넌트 수정

마이페이지 컴포넌트에서 MyPageModal을 호출하고, 프로필 정보를 Supabase에서 가져와서 렌더링한다.

 

MyPage 컴포넌트

 
import React, { useState, useEffect } from 'react';
import MyPageModal from '../components/MyPageModal';
import { supabase } from '../supabaseClient';

export default function MyPage() {
    const [showModal, setShowModal] = useState(false);
    const [profile, setProfile] = useState(null);

    useEffect(() => {
        const fetchProfile = async () => {
            const { data, error } = await supabase
                .from('profiles')
                .select('*')
                .eq('id', 'user-id')  // Fetch profile for the logged-in user
                .single();

            if (error) {
                console.error('Error fetching profile:', error);
            } else {
                setProfile(data);
            }
        };

        fetchProfile();
    }, []);

    return (
        <>
            <div>헤더</div>

            {/* 프로필 사진 */}
            <div className="container mx-auto py-40 flex gap-20">
                <div className="relative">
                    <div className="h-full rounded-full overflow-hidden object-contain h-48 w-48">
                        <img
                            src={profile?.avatar_url || "default-avatar-url"}
                            alt="프로필 사진"
                        />
                    </div>
                </div>

                {/* 프로필 내용 */}
                <div className="my-auto flex flex-col gap-3">
                    <h1 className="text-3xl font-medium">{profile?.name || "홍길동"}</h1>
                    <p className="text-gray-400">{profile?.status || "즐거운 날입니다."}</p>
                    <div className="flex item-stretch gap-4 ">
                        <button
                            data-modal-target="default-modal"
                            data-modal-toggle="default-modal"
                            className="p-2 ring-1 ring-gray-400 rounded-full"
                            onClick={() => setShowModal(true)}
                        >
                            프로필 수정
                        </button>
                        <button className="p-2 ring-1 ring-gray-400 rounded-full">비밀번호 변경</button>
                    </div>
                    <MyPageModal isVisible={showModal} onClose={() => setShowModal(false)} />
                </div>
            </div>

            {/* 내가 쓴 리뷰 */}
            <div>
                <div className="container mx-auto">
                    <h1 className="text-3xl font-medium">내가 작성한 리뷰</h1>
                </div>
            </div>
            <div className="p-5 flex flex-wrap">
                {/* 리뷰 내용 반복 렌더링 */}
            </div>

            <div>푸더</div>
        </>
    );
}
  • 프로필 정보 가져오기: useEffect 훅을 사용하여 컴포넌트가 마운트될 때 Supabase에서 사용자 프로필 정보를 가져오기
  • 프로필 사진 표시: profile?.avatar_url을 사용하여 사용자의 프로필 사진을 표시
  • 프로필 수정 모달 호출: "프로필 수정" 버튼을 클릭하면 모달을 표시하고, 모달에서 파일 업로드와 프로필 수정을 처리

 

코드 흐름 설명

  1. Supabase 클라이언트 설정: supabaseClient.js 파일에서 Supabase 클라이언트를 설정하여 프로젝트에서 Supabase API를 사용할 수 있게 한다.
  2. MyPage 컴포넌트:
    • useEffect를 사용하여 컴포넌트가 마운트될 때 Supabase에서 사용자 프로필 정보를 가져와 profile 상태에 저장한다.
    • 프로필 사진과 프로필 정보를 화면에 표시한다.
    • "프로필 수정" 버튼을 클릭하면 showModal 상태를 true로 설정하여 MyPageModal을 표시한다.
  3. MyPageModal 컴포넌트:
    • 사용자가 파일을 선택하면 handleFileChange 함수가 호출되어 선택한 파일을 file 상태에 저장한다.
    • 사용자가 "저장" 버튼을 클릭하면 handleSubmit 함수가 호출되어 파일을 Supabase 스토리지에 업로드하고, 업로드된 파일의 URL을 Supabase 데이터베이스에 사용자 프로필의 avatar_url 필드에 저장한다.
    • 프로필 수정이 완료되면 모달을 닫고, 업데이트된 프로필 정보를 MyPage 컴포넌트에서 다시 표시한다.

 

이렇게 하여

사용자가 마이페이지에서 프로필 사진을 수정할 수 있고,

수정된 사진은 Supabase 스토리지에 저장되며,

사용자 프로필에 반영된다.