6/11 TIL (jwt 로그인, 회원가입 구현)

Hwi·2024년 6월 11일

TIL

목록 보기
45/96

📖 진행한 공부 📖

  • jwt 로그인, 회원가입 구현

과제 필수 구현 사항

로그인과 회원가입 페이지에 대한 라우터 돔은 설정을 마쳐둔 상태고


AuthContext.jsx라는 파일을 하나 만들어 context api로 전역 상태 관리를 하려고 한다.

로그인 기능에 앞서 회원가입 기능을 구현했다.

Register.jsx

import axios from 'axios';
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';

const Register = () => {
  const [id, setId] = useState('');
  const [password, setPassword] = useState('');
  const [nickname, setNickname] = useState('');
  const [errors, setErrors] = useState({});
  const navigate = useNavigate();

  // 유효성 검사
  const validation = () => {
    const newError = {};
    if (id.length < 4 || id.length > 10) {
      newError.id = 'ID는 4글자 이상, 10글자 미만이어야만 합니다.';
    }
    if (password.length < 4 || password.length > 15) {
      newError.password = '비밀번호는 4글자 이상, 15글자 미만이어야만 합니다.';
    }
    if (nickname.length < 1 || nickname.length > 10) {
      newError.nickname = '닉네임은 1글자 이상, 10글자 미만이어야만 합니다.';
    }
    setErrors(newError);
    return Object.keys(newError).length === 0; // 에러가 비어있는지 확인
  };

  const handleRegister = async (e) => {
    e.preventDefault();
    if (validation()) {
      try {
        const response = await axios.post("https://moneyfulpublicpolicy.co.kr/register", {
          id,
          password,
          nickname,
        });
        const tokenId = response.data.token;
        localStorage.setItem("token", tokenId);
        alert("회원가입을 성공적으로 마쳤습니다!");
        navigate("/login");
      }
      catch (error) {
        console.error("Register Error =>", error);
      }
    }
  };

  const LoginPage = () => {
    navigate("/login");
  }

  return (
    <SignUpContainer>
      <Title>회원가입</Title>
      <form onSubmit={handleRegister}>
        <FormGroup>
          <Label htmlFor="id">아이디:</Label>
          <Input
            type="text"
            id="id"
            value={id}
            onChange={(e) => setId(e.target.value)}
            required
          />
          {errors.id && <ErrorMessage>{errors.id}</ErrorMessage>}
        </FormGroup>
        <FormGroup>
          <Label htmlFor="password">비밀번호:</Label>
          <Input
            type="password"
            id="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
          />
          {errors.password && <ErrorMessage>{errors.password}</ErrorMessage>}
        </FormGroup>
        <FormGroup>
          <Label htmlFor="nickname">닉네임:</Label>
          <Input
            type="text"
            id="nickname"
            value={nickname}
            onChange={(e) => setNickname(e.target.value)}
            required
          />
          {errors.nickname && <ErrorMessage>{errors.nickname}</ErrorMessage>}
        </FormGroup>
        <Button type="submit">회원가입하기</Button>
        <Button type="button" onClick={LoginPage} >로그인으로 돌아가기</Button>
      </form>
    </SignUpContainer>
  );
};

export default Register;

스타일 컴포넌트의 코드는 제외하고 기능적인 부분을 하는 코드만 올려봤음

axios의 post 메서드를 통해 서버로 회원가입 정보를 전송하고 로컬스토리지에 토큰을 저장해줬음

Login.jsx

import axios from 'axios';
import React, { useContext, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import { AuthContext } from '../context/AuthContext';

const Login = () => {
  const [id, setId] = useState('');
  const [password, setPassword] = useState('');
  const navigate = useNavigate();
  const { login } = useContext(AuthContext);


  const RegisterPage = () => {
    navigate("/register");
  }

  const handleLogin = async (e) => {
    e.preventDefault();
    try {
        const response = await axios.post("https://moneyfulpublicpolicy.co.kr/login", {
            id,
            password,
        });
        const tokenId = response.data.token;
        localStorage.setItem("token", tokenId);
        login(tokenId);
        alert(`${response.data.nickname}님 환영합니다!`);
        navigate("/");
    } 
    catch (error) {
        console.error("Login Error =>", error);
        alert("올바르지 않은 정보입니다! 다시 시도해주세요.");
    }
  }
  return (
    <LoginContainer>
      <Title>Login</Title>
      <form onSubmit={handleLogin}>
        <FormGroup>
          <Label htmlFor="id">아이디:</Label>
          <Input
            type="text"
            id="id"
            value={id}
            onChange={(e) => setId(e.target.value)}
            required
          />
        </FormGroup>
        <FormGroup>
          <Label htmlFor="password">비밀번호:</Label>
          <Input
            type="password"
            id="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
          />
        </FormGroup>
        <Button type="submit">로그인</Button>
        <Button type="button" onClick={RegisterPage}>회원가입</Button>
      </form>
    </LoginContainer>
  );
};

export default Login;

로그인 페이지 또한 post 메서드로 서버에 로그인 정보를 전송한 후 인증 context에 토큰을 넘겨 로그인 상태를 업데이트했음


그런데 로그인을 하고 로컬스토리지를 보면 token, accessToken 전부 undefined로 나오는 걸 볼 수가 있는데

해당 부분의 문제를 확인하려면 로그인을 할 때 token을 제대로 가져와지는지 부터 확인을 해봐야 한다

console.log(respose) 를 통해 확인을 해봤다.

해당 콘솔을 보니 response는 문제가 없는데 내가 지정을 잘못했던 것이다.

// 수정 전 
const tokenId = response.data.token 

// 수정 후 
const tokenId = response.data.accessToken

해당 부분을 수정해준 후에 다시 로그인을 후 로컬스토리지를 확인해봤음

정상적으로 값이 담겨있는 걸 확인할 수 있음 야호~

profile
개발자가 되고 싶어~~~

0개의 댓글