Express 로그인 회원가입 기능 구현

서나무·2022년 10월 10일
3
post-thumbnail

나는 먼저 기능을 구현한 후에 데이터베이스와 연동해서 데이터를 저장했다. 데이터베이스에 연동하기 전까지는 우선 메모리에 저장하도록 했다.

📝 회원가입 기능

회원가입을 하는데 2가지 조건이 있다.

  1. id, password, name는 필수로 입력해야 한다.
  2. id는 중복되지 않도록한다.

만약 두가지 조건에 부합하지 않는다면 회원가입에 실패한다.

app.js

// 사용자 정보를 담을 배열
const users = [];

// 회원가입
app.post('/user/register', (req, res) => {
  const { id, password, name } = req.body;
  // TODO id, password, name이 있는지 체크한다.
  if (!id || !password || !name) {
    res.status(400).send({ message: 'id, password, name은 필수입력 사항입니다.' });
    return;
  }
  
  // TODO id는 중복되지 않도록한다.
  const user = users.find((user) => user.id === id);
  if (user) {
    res.status(400).send({ message: '이미 존재하는 아이디입니다.' });
    return;
  }

  // TODO 사용자를 추가한다.
  users.push(req.body);
  res.send({ message: '사용자를 등록했습니다.' });
});

📑 REST Client를 사용해서 API 테스트하기

회원가입 기능을 구현했으니, 잘 되는지 확인해보기 위해 API 테스트를 해보자.

Postman, Talend API 등 좋은 툴들이 많지만 나는 vscode에서 바로 사용할 수 있는 확장앱인 REST Client를 자주 사용하고 있다.

확장앱을 설치하고 나서, .http 확장자를 사용해서 파일을 생성하고 아래처럼 http request를 작성해보자.

# Method, Path
POST http://localhost:3001/user/register 
# Headers
Content-Type: application/json
# Body
{
  "id": "test1",
  "name": "테스트1",
  "password": "qwer"
}

메소드 위에 'Send Request' 버튼을 클릭해서 http 요청을 보낼 수 있다.

처음 요청을 보내면, test1이라는 id를 사용하는 사용자가 없기때문에 무사히 회원가입에 성공한다.

요청을 한번 더 보내면 이미 존재하는 아이디이기 때문에 회원가입에 실패한다.

📝 로그인 기능

로그인을 할 때는 id와 password를 받아서 두 가지를 체크한다.

  1. 존재하는 아이디인지 확인한다.
  2. 존재하는 아이디일 경우, 비밀번호가 일치하는지 확인한다.

만약 아이디가 존재하지 않거나, 비밀번호가 일치하지 않으면 로그인에 실패한다. 로그인 성공 시, 토큰을 반환해서 프론트엔드에서 로그인을 오래동안 유지할 수 있도록 할 예정이다.

app.js

app.post('/user/login', (req, res) => {
  const { id, password } = req.body;
  // TODO id, password가 있는지 체크한다.
  if (!id || !password) {
    res.status(400).send({ message: 'id, password는 필수입력 사항입니다.' });
    return;
  }

  // TODO 입력받은 id의 사용자를 찾는다.
  const user = users.find((user) => user.id === id);
  if (!user) {
    res.status(400).send({ message: '존재하지 않는 사용자입니다.' });
    return;
  }

  // TODO 입력받은 password와 찾은 사용자의 password가 일치하는지 체크한다.
  if (user.password !== password) {
    res.status(400).send({ message: '비밀번호가 일치하지 않습니다.' });
    return;
  }

  // TODO 토큰을 발급한다.
  res.status(200).send({ token: 'token' });
});

🚀 JWT

나는 토큰 발급을 위해 jsonwebtoken 라이브러리를 사용했다.

$ npm i jsonwebtoken

서버는 토큰이 유효할 경우에만 로그인 상태라고 생각하고, 토큰이 유효하지 않으면 글 등록, 수정, 삭제 등의 기능을 제한할거다.

토큰 기능은 따로 jwt 폴더에 파일을 생성해서 관리했다.

jwt/index.js

const jwt = require('jsonwebtoken');

const tokenService = {
  // TODO 토큰 발급
  getToken(user_id) {
  // 토큰에 담을 정보, 사용할 키 (아무 값이나 가능), 토큰 옵션
    return jwt.sign({ user_id }, 'SECRET_KEY', {
      expiresIn: '1d' // 만료시간
    });
  },
  // TODO 토큰이 유효하다면 토큰에 담긴 정보를 반환
  getPayload(token) {
    return jwt.verify(token, 'SECRET_KEY');
  }
}

module.exports = tokenService;

이제 로그인 기능에서 토큰 발급을 해서 반환하도록 하면 된다.

app.js

const tokenService = require('./jwt');
app.post('/user/login', (req, res) => {
  const { id, password } = req.body;
  // ...
  // TODO 토큰을 발급한다.
  res.status(200).send({ token: tokenService.getToken(id) });
});

로그인 API를 테스트 하려고 하는데, 서버를 계속해서 재시작해서 기존 데이터가 사라져서 불편하다. 기본 사용자 정보를 배열에 저장한 후에 테스트를 진행했다.

const users = [
  {
    id: 'test',
    name: 'tester',
    password: 'test'
  }
];

.http

POST http://localhost:3001/user/login 
Content-Type: application/json

{
  "id": "test",
  "password": "test"
}

응답으로 토큰을 잘 발급해주고 있다.

그런데 서버를 실행시키는 app.js 파일이 꽤 복잡해졌다. app.js는 서버를 실행시키는 코드만 남기고, 라우터를 관리하는 파일을 따로 생성해서 관심사를 분리해보자!

🔌 라우터 분리하기

user 폴더를 생성하고 index.js 파일을 만들었다.

라우터를 분리하기 위해서는 express의 Router 함수로 라우터를 생성해서 사용하면 된다.

user/index.js

const express = require('express');
const router = express.Router();

// app이 아닌 router!
router.post('/login', (req, res) => {
  // ...
});
router.post('/register', (req, res) => {
  // ...
});

module.exports = router;

그리고 기존에 app.js에서는 userRouter를 불러와서 넣어주기만 하면 된다.

app.js

const userRouter = require('./user');
app.use('/user', userRouter);

app.js가 매우 깔끔해졌다. ^0^

profile
주니어 프론트엔드 개발자

0개의 댓글