Next.js로 간단한 로그인 만들기

Myeongjun Park·2022년 10월 10일
4
post-thumbnail

📖 시작하기에 앞서,

이번에 진행한 프로젝트는 Next Auth와 같은 라이브러리는 사용하지 않았고,
DB를 사용하지 않고 유저 정보가 담긴 JSON을 사용했다.
그렇다보니 DB를 사용해서 구현한 로그인과는 조금 다르겠지만,
기본적인 원리는 동일하다고 생각하기에 블로그에 기록해둔다.

✅ 기본적인 구조는 어떻게 되는가?

  1. 클라이언트에서 ID,PW를 담아 Request 한다.
  2. 서버에서 ID, PW를 받고 JSON에서 일치하는 ID를 찾는다.
  3. ID가 일치한다면 그 ID의 PW가 일치하는지 확인한다.
  4. 모두 일치한다면 토큰을 생성한 뒤 해당 ID의 유저 데이터와 토큰을 함께 Response 한다.

✅ 클라이언트 부분 구현

React-hook-form과 axios, React-cookie를 사용했다.

npm install axios

npm install react-hook-form

npm install react-cookie

다음으로 index에는 아래처럼 작성했다.

//index.tsx

import type { NextPage, NextPageContext } from "next";
import { useForm, SubmitHandler } from "react-hook-form";
import { useRouter } from "next/router";
import axios from "axios";

const cookies = new Cookies();//쿠키 사용을 위해 선언

interface FormValue {
  id: string;
  password: string;
}


const Home: NextPage = () => {
  const router = useRouter(); //router를 사용하기 위해 선언

  /**
   * React-hook-form을 사용하기 위해 import 후 선언한 변수
   * register: input이 받을 값을 정의
   * handleSubmit: 각 항목이 입력되었을 때 submit 이벤트를 처리
   * watch: register 한 항목의 변경사항을 추적
   * errors: 유효성이 통과되지 않으면 에러 상태를 내보내줍니다.
   */
  const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>();

  /**
   * Form에서 summit을 하게 되면 실행되는 함수
   * 이 때 form에서 받아온 data를 매개변수로 사용하여 값을 받아온다.
   * 비밀번호를 BASE64로 변환하고, 이후 객체를 새로 만든다.
   */
  const onSubmitHandler: SubmitHandler<FormValue> = (data) => {
    const loginId = data.id;
    const base64Pw = btoa(data.password);
    const newLoginArray = {
      id: loginId,
      password: base64Pw,
    };

    /**
     * axios를 사용하여 로그인 정보를 담아 POST 한다.
     * 이 후 응답 받은 accessToken을 cookie에 저장한다.
     * 그리고 comment 컴포넌트를 출력할 수 있도록 replace 한다.
     */
    axios
      .post("/api/user", newLoginArray)
      .then((response) => {
        const { accessToken } = response.data;
        cookies.set("LoginToken", accessToken, {
          path: "/",
          secure: true,
          sameSite: "none",
        });

        router.replace("/comment");
      })
      .catch((error) => {
        alert("아이디 또는 비밀번호를 확인해주세요.");
      });
  };

  return (
    <div className="wrap">
       <form onSubmit={handleSubmit(onSubmitHandler)}>
          <div>ID</div>
          <input {...register("id")} placeholder="ID"/>
          <div>PASSWORD</div>
          <input {...register("password")} type="password" placeholder="PASSWORD" />
          <button>로그인</button>
       </form>
    </div>
  );
};

export default Home;

✅ 서버 부분 구현

Next.js의 api를 활용하여 구현했다.

npm install jsonwebtoken
import type { NextApiRequest, NextApiResponse } from "next";
import userData from "./userData.json";
import jwt from "jsonwebtoken";

const userArray = userData.users;

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "POST") {
    const { id, password } = req.body;
    var userItem = userArray.find((object) => object.id == id);
    console.log(userItem);
    if (userItem != null) {
      if (userItem.password == password) {
        const secret = "Secret_Key";
        try {
          const accessToken = await new Promise((resolve, reject) => {
            jwt.sign(
              {
                memberId: userItem?.id, //payload에 담을 id
                memberName: userItem?.name, //payload에 담을 name
              },
              secret,
              {
                expiresIn: "5m", //토큰 유효 시간
              },
              (err, token) => {
                if (err) {
                  reject(err);
                } else {
                  resolve(token);
                }
              }
            );
          });
          res.json({ success: true, accessToken }); //토큰을 담아서 Response
        } catch (err) {
          console.log(err);
          res.json({ success: false, errormessage: "토큰 서명에 실패했습니다." });
        }
      } else {
        res.json({ success: false, errormessage: "아이디와 비밀번호가 일치하지 않습니다." });
      }
    } else {
      res.json({ success: false, errormessage: "아이디와 비밀번호가 일치하지 않습니다." });
    }
  }
}

✅ JWT(JSON Web Token) ?

⭐️ JWT 토큰에 대한 설명과 생성 방법은 이전 포스트에 작성했다.
JWT(JSON Web Token) 모듈 사용법

📌 참고
node.js 웹사이트 개발 - 회원가입, 로그인,로그아웃 구현
[react-hook-form + TypeScript] 리액트 훅 폼 사용법과 타입 주기

profile
머릿속에 잘 들어갔는지 확인하는 곳

1개의 댓글

comment-user-thumbnail
2023년 3월 1일

안녕하세요 정말 궁금해서 여쭤보는건데
혹시 중간중간 var로 변수를 선언하는 이유가 있을까요?

답글 달기