본문 바로가기

Supabase 회원가입 기능 구현하기

codeConnection 2024. 6. 18.

사전 셋업

- 환경변수 처리

- supabase 변수 만들어서 export

- 이메일 인증 풀기

이메일 회원가입 함수

수파베이스에서 제공하는 코드는 아래와 같다.

const { data, error } = await supabase.auth.signInWithPassword({
  email: 'example@email.com',
  password: 'example-password',
})

이를 그대로 사용하는 것이 아니고, useEffect훅을 사용해서 비동기 함수로 컴포넌트가 마운트 됐을 때 로그인 함수를 실행하도록 해주면 된다.

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

const SignUp = () => {
  useEffect(() => {
    const signUp = async () => {
      const { data, error } = await supabase.auth.signInWithPassword({
        email: 'example@email.com',
        password: 'example-password',
      });

      if (error) {
        console.error('Error signing in:', error.message);
      } else {
        console.log('Sign in data:', data);
      }
    };

    signUp();
  }, []);

사용자의 정보 받는 방법과 전체 코드

  • 각 입력 필드 별 상태 생성
  • onChange 이벤트 핸들러를 각 입력 필드에 연결
  • Form 태그로 전체 입력 필드를 감쌈
  • 버튼에 submit 속성 부여. (안 해도 기본 값이긴 하나 시멘틱한 목적)
const SignUp = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [error, setError] = useState('');
  const [isButtonDisabled, setIsButtonDisabled] = useState(true);
  const navigate = useNavigate();

  // 이메일 형태 정규식으로 선언
  const validateEmail = (email) => {
    return /\S+@\S+\.\S+/.test(email);
  };

  const handleSignUp = async (event) => {
    event.preventDefault(); // 폼 제출 시 페이지 리로드 방지
	
    // 유효성 검사 통과 못할 시 띄울 에러 초기화
	let errorMessage = '';

	// 입력 필드 유효성 검사
    if (!validateEmail(email)) {
      errorMessage = '이메일 형식을 확인해주세요';
    } else if (password.length < 6) {
      errorMessage = '비밀번호는 6자리 이상으로 설정해주세요';
    } else if (password !== confirmPassword) {
      errorMessage = '비밀번호 재입력이 일치하지 않습니다';
    }

	// 에러 메시지가 있으면 error
    if (errorMessage) {
      setError(errorMessage);
      return;
    }

    setError('');

	// supabase 회원가입 내장 함수
    // try...catch로 에러 상황 발생 시 처리를 한다. 에러가 없으면 성공으로 간주하고
    // 성공 이후 홈으로 이동시키는 로직.
    try {
      const { data, error } = await supabase.auth.signUp({
        email: email,
        password: password,
      });

      if (error) {
        const signUpError = `회원가입 중 에러가 발생했습니다.: ${error.message}`;
        setError(signUpError);
        console.error(signUpError);
      } else {
        alert(`${data.user.email} 님 회원가입을 축하드립니다!`);
        console.log('회원가입 완료:', data);
        navigate('/');
      }
    } catch (error) {
      const signUpError = `회원가입 중 에러가 발생했습니다.: ${error.message}`;
      
      // 에러 메시지가 영얼 되어 있으니 번역하여 반환하는 스위치문을 작성하면 좋을 듯.
      setError(signUpError);
      console.error(signUpError);
    }
  };

  const handleEmailChange = (e) => {
    setEmail(e.target.value);
    if (!validateEmail(e.target.value)) {
      setError('이메일 형식을 확인해주세요');
    } else {
      setError('');
    }
  };

  // 유효성 검사를 하기 위한 함수임. 필요 없으면 입력 필드에 곧바로 setState를 연결해도 됨.
  const handlePasswordChange = (e) => {
    setPassword(e.target.value);
    setError('');
  };

  const handleConfirmPasswordChange = (e) => {
    setConfirmPassword(e.target.value);
    setError('');
  };

  useEffect(() => {
    // 버튼 활성화/비활성화 상태 업데이트 : 유효성 검사를 통과 못하면 버튼을 클릭 못하게 막음
    // 의존성 배열에 담긴 것들은 입력 필드이고 이것들이 바뀔 때마다 실행되어야 함.
    if (email && password && confirmPassword && !error && password === confirmPassword && validateEmail(email)) {
      setIsButtonDisabled(false);
    } else {
      setIsButtonDisabled(true);
    }
  }, [email, password, confirmPassword, error]);

  return (
    <Container>
      <Content>
        <ImgWrapper>
          <img src="https://kmfvncclriiektxphias.supabase.co/storage/v1/object/public/images/public/Festiall_Model.png?t=2024-06-18T03%3A56%3A18.517Z" alt="user login" />
        </ImgWrapper>
        <Forms>
        
          {/* Form 태그에 이벤트 핸들러로 회원가입 함수를 연결 해주어야 함 */}
          <Form className="block" id="login-up" onSubmit={handleSignUp}>
            <Title>회원가입 페이지</Title>
            <InputBox>
              <Icon className='bx bx-at'></Icon>
              <Input
                type="email"
                placeholder="이메일"
                value={email}
                onChange={handleEmailChange}
              />
            </InputBox>
            <InputBox>
              <Icon className='bx bx-lock'></Icon>
              <Input
                type="password"
                placeholder="비밀번호"
                value={password}
                onChange={handlePasswordChange}
              />
            </InputBox>
            <InputBox>
              <Icon className='bx bx-lock'></Icon>
              <Input
                type="password"
                placeholder="비밀번호 재입력"
                value={confirmPassword}
                onChange={handleConfirmPasswordChange}
              />
            </InputBox>
            {/* 입력 필드 바로 밑에 경고문을 실시간으로 출력하는 조건부 렌더링임 */}
            {password !== confirmPassword && confirmPassword && (
              <ErrorMessage>
                비밀번호가 일치하지 않습니다
              </ErrorMessage>
            )}
            {error && (
              <ErrorMessage>
                {error}
              </ErrorMessage>
            )}
            {/* 마지막으로 회원가입 버튼의 타입을 submit으로 해주고, (안 해도 기본값인데 시멘틱하게) */}
            {/* disabled라는 속성에 실시간으로 변경되는 상태를 연결해주면 됨. 불리언값. */}
            <Button type="submit" disabled={isButtonDisabled}>
              회원가입
            </Button>
          </Form>
        </Forms>
      </Content>
    </Container>
  );
};

export default SignUp;

 

댓글