useState를 사용하여 이메일 로그인 구현하기

hoon·2023년 5월 8일
0

지금까지 로그인 모달창을 Redux를 사용하여 전역 상태관리 하였다. 이번에는 useState를 활용하여 이메일 로그인을 구현해 보자. 이메일 로그인 로직은 다음과 같다.

  1. 사용자가 이메일 주소와 비밀번호를 입력한다.
  2. 입력 값이 변경될 때마다, handleChangeEmailhandleChangePassword 함수가 호출되어 이메일과 비밀번호 상태가 업데이트된다.
  3. 이메일 유효성 검사: handleChangeEmail 함수에서 이메일이 비어있지 않고 형식이 잘못된 경우 경고 메시지가 표시된다.
  4. 비밀번호 입력 확인: handleChangePassword 함수에서 비밀번호가 비어있는지 확인한다. 비어있는 경우 경고 메시지가 표시된다.
  5. 사용자가 로그인 버튼을 클릭한다.
  6. handleSubmit 함수가 호출되어 입력된 이메일과 비밀번호를 검사한다.
    a. 입력이 올바르지 않은 경우 (비어있거나, 이메일 형식이 잘못된 경우), 경고 메시지를 표시하고 로그인 시도를 중단한다.
    b. 입력이 올바른 경우, 로그인 요청을 진행한다. (이 부분은 추후에 백엔드와 연동한다.)
  7. 로그인 요청이 성공하면, 사용자를 인증하고 로그인 세션을 시작한다. (이 부분은 추후에 백엔드와 연동한다.)
  8. 로그인 요청이 실패하면, isLoginError 상태를 true로 설정하여 경고 메시지를 표시한다.

이 과정을 통해 사용자는 이메일 주소와 비밀번호를 입력하여 로그인을 시도할 수 있으며, 입력 값에 문제가 있는 경우 적절한 경고 메시지를 통해 피드백을 받을 수 있다.

실제 구현된 코드를 보자.

예시코드

// src/components/Login/EmailLogin.jsx

import React from 'react';

import WarningMsg from '../WarningMsg/WarningMsg.jsx';
import {
  EmailLoginContainer,
  EmailLabel,
  PasswordLabel,
  EmailInput,
  PasswordInput,
  LoginBtn,
} from './EmailLoginStyle.js';

const EmailLogin = ({
  email,
  password,
  handleChangeEmail,
  handleChangePassword,
  isEmailEmpty,
  isEmailInvalid,
  isPasswordEmpty,
  isLoginError,
}) => {
  return (
    <EmailLoginContainer>
      <EmailLabel htmlFor='user-email'>이메일</EmailLabel>
      <EmailInput
        type='text'
        id='user-email'
        name='user-email'
        placeholder='이메일을 입력해주세요.'
        value={email}
        onChange={handleChangeEmail}
        error={isEmailEmpty || isEmailInvalid}
      />
      <WarningMsg show={isEmailEmpty} message='이메일을 입력해 주세요.' />{' '}
      <WarningMsg
        show={isEmailInvalid}
        message='이메일 형식에 맞게 입력해 주세요.'
      />{' '}
      <PasswordLabel htmlFor='user-pw'>비밀번호</PasswordLabel>
      <PasswordInput
        type='password'
        id='user-pw'
        name='user-pw'
        placeholder='비밀번호를 입력해주세요.'
        value={password}
        onChange={handleChangePassword}
        error={isPasswordEmpty || isLoginError}
      />
      <WarningMsg show={isPasswordEmpty} message='비밀번호를 입력해 주세요.' />{' '}
      <WarningMsg
        show={isLoginError}
        message='로그인 정보가 올바르지 않습니다. 다시 시도해 주세요.'
      />
      <LoginBtn type='submit'>로그인</LoginBtn>
    </EmailLoginContainer>
  );
};

export default EmailLogin;
// src/components/Login/LoginModal/LoginModal.jsx

import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { hideLoginModal } from '../../../store/actions';
import BaseModal from '../../helpers/BaseModal.jsx';
import EmailLogin from '../EmailLogin.jsx';

import {
  LoginModalContent,
  LoginModalText,
  SignupBtn,
  // KakaoBtn,
  OrText,
} from './LoginModalStyle';
import KakaoLoginBtn from '../KakaoLoginBtn.jsx';

const LoginModal = () => {
  const isLoginModalVisible = useSelector(state => state.isLoginModalVisible);
  const dispatch = useDispatch();

  const handleHideLoginModal = () => {
    dispatch(hideLoginModal());
  };

  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [isEmailEmpty, setIsEmailEmpty] = useState(false);
  const [isEmailInvalid, setIsEmailInvalid] = useState(false);
  const [isPasswordEmpty, setIsPasswordEmpty] = useState(false);
  const [isLoginError, setIsLoginError] = useState(false);

  const handleChangeEmail = event => {
    setEmail(event.target.value);
    console.log(event.target.value);

    // 이메일이 비어있지 않고 형식이 잘못된 경우에만 경고 메시지 표시
    if (event.target.value !== '' && !validateEmail(event.target.value)) {
      setIsEmailInvalid(true);
    } else {
      setIsEmailInvalid(false);
    }

    // 이메일이 비어있는지 여부 확인
    setIsEmailEmpty(event.target.value === '');
  };

  const validateEmail = email => {
    const regex = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
    return regex.test(email);
  };

  const handleChangePassword = event => {
    setPassword(event.target.value);
    console.log(event.target.value);

    // 패스워드가 비어있는지 확인
    setIsPasswordEmpty(event.target.value === '');
  };

  const handleSubmit = async event => {
    event.preventDefault();
    if (email === '') {
      setIsEmailEmpty(true);
    } else {
      setIsEmailEmpty(false);
    }

    if (email !== '' && !validateEmail(email)) {
      setIsEmailInvalid(true);
    } else {
      setIsEmailInvalid(false);
    }

    if (password === '') {
      setIsPasswordEmpty(true);
    } else {
      setIsPasswordEmpty(false);
    }

    // 입력이 올바르지 않은 경우에는 로그인 시도를 중단
    if (isEmailEmpty || isEmailInvalid || isPasswordEmpty) {
      return;
    }

    // 이메일과 패스워드가 존재하지 않을떄 로직 추가

    try {
      console.log(email, password);
    } catch (error) {
      setIsLoginError(true);
    }
  };

  return (
    <BaseModal
      isVisible={isLoginModalVisible}
      onClose={handleHideLoginModal}
      title='로그인 또는 회원가입'
    >
      <LoginModalContent onSubmit={handleSubmit}>
        <LoginModalText>☕️ 카페골목에 오신 것을 환영합니다.</LoginModalText>
        <EmailLogin
          email={email}
          password={password}
          handleChangeEmail={handleChangeEmail}
          handleChangePassword={handleChangePassword}
          handleSubmit={handleSubmit}
          isEmailEmpty={isEmailEmpty}
          isEmailInvalid={isEmailInvalid}
          isPasswordEmpty={isPasswordEmpty}
          isLoginError={isLoginError}
        />
        <OrText>또는</OrText>
        <KakaoLoginBtn />
        <SignupBtn type='button'>카페골목 회원가입 하기</SignupBtn>
      </LoginModalContent>
    </BaseModal>
  );
};

export default LoginModal;
// src/components/WarningMsg/WarningMsg.jsx

import React from 'react';
import styled from 'styled-components';
import { palette } from '../../styles/globalColor';

export const WarningMsgContainer = styled.strong`
  display: block;
  margin-left: 5px;
  margin-bottom: 10px;
  font-size: 13px;
  color: ${palette.redColor};
  display: ${props => (props.show ? 'block' : 'none')};
`;

const WarningMsg = ({ show, message }) => (
  <WarningMsgContainer show={show}>{message}</WarningMsgContainer>
);

export default WarningMsg;

추후에 구현할 내용

  1. 실제 로그인 처리: 현재 예제 코드에는 이메일과 비밀번호를 사용하여 실제로 로그인 요청을 처리하는 부분이 구현되어 있지 않다. 이 부분은 백엔드와 연동하여 로그인 요청을 처리하고, 요청 결과에 따라 성공/실패 처리를 해야 한다.
  2. 로그인 성공 후 처리: 로그인이 성공하면, 사용자 인증 및 로그인 세션을 시작하는 등의 추가 작업이 필요하다. 또한, 사용자에게 로그인 성공을 알리는 메시지를 표시하고, 원하는 페이지로 리다이렉션할 수 있도록 처리해야 한다.
profile
프론트엔드 학습 과정을 기록하고 있습니다.

0개의 댓글