본문 바로가기

Node.js 도전기

Node.js_로그인 기능 구현하기

앞서 정리한 쿠키, 세션, jwt토큰을 정리했는데, 

관련 내용을 활용하여 로그인 기능을 간단하게 구현해보도록 하겠다 ! 

(물론 실제 로그인 기능은 훨씬 고도화되겠지만 간단한게 체험한다는 느낌으로다가 ~)

[로그인 기능의 간단한 로직 !]
1. 클라이언트가 email과 password를 body에서 입력한다.

2. 입력받은 정보를 DB에서 찾아 일치할 경우 인증 토큰을 보내준다.

3. 토큰을 보유 여부를 확인하여 보유하지 않고 있으면 다시 로그인을 요청한다.

 

구현할 때 초기 세팅은 아래와 같다.

 

1) express 프레임 워크 사용

2) Users라는 모델이 구축하여 user데이터 저장

3) Users 모델에는 아래와 같은 컬럼을 가진다.

- userId 

- userName

- email

- password

4) 인증 토큰으로 jwt토큰을 사용하여 userId를 담아 준다.

// auth.router.js 파일로 만들었다고 가정 !

const express = require('express');
const authRouter = express.Router();
const Users = require('유저 모델을 가져오는 경로')
const jwt = require('jsonwebtoken')

// express, jsonwebtoken 라이브러리를 설치해야 한다.

 

#1.  클라이언트가 입력한 정보 확인하기 !

클라이언트(유저)는 프론트에서 로그인 화면을 보고 이메일과 비밀번호를 입력할 것이다. 

입력된 정보들을 DB와 비교하는 부분을 구현해보자 ! 

// auth.router.js

// /sign-in 경로에서 POST 메서드로 요청을 받을 경우
authRouter.post('/sign-in', (req,res) => {

  // body에서 입력받은 데이터를 email, password라는 변수로 저장한다.
  const { email, password } = req.body;  
    
  // 입력받은 데이터를 가지고 Users 안에 있는 user 중 일치하는 요소를 찾는다.
  const user = Users.find(user => user.email === email && user.password === password);
  
  // 찾은 user가 없을 경우 에러 반환
  if(!user) {
    return res.status(401).json({message:"이메일 또는 비밀번호를 확인해주세요"});
  };
  
})

 

위 코드 블럭에 주석으로도 써놓긴 했지만 조금 더 풀어서 설명해보자면, 

 

  1. 프론트(req.body)에서 입력한 email 과 password값을 동일한 변수 이름인 email과 password로 저장하고자 구조분해할당을 진행했다.
      
  2. Users라는 모델에서 입력받은 이메일과 비밀번호가 일치하는 요소를 찾아 user라는 변수에 할당한다.
    Users 모델은 배열 형식으로 구성되어 있기 때문에 find 메서드를 사용할 수 있다.

    그 전에 ! 회원가입 단계에서 Users라는 모델에 유저 정보가 올바르게 담겨야한다 !
  3. 찾은 유저가 없는 경우는 이메일 혹은 비밀번호가 잘못된 요청이기 때문에 에러 메시지를 반환한다. 
    여기서 !! 이메일이 잘못되었습니다 or 비밀번호가 잘못되었습니다.
    라고 개별적으로 알려줄 경우 보안 상 좋지 않음으로 한번에 알려주는것이 바람직하다. 

#2.  일치하는 유저가 있다면 토큰을 만들어 주기

// auth.router.js

// 상단 코드 생략 ...
  
  // 일치하는 경우가 있다면 jwt토큰 생성
  const token = jwt.sign({userId},"Secret Key",{expiresIn : "12h"});
})

 

DB에서 확인된 유저가 있다면 유저를 인증할 수 있는 토큰을 발행해야하는데 

JWT 토큰을 생성했다. 

 

.sign 메서드를 이용해서

첫 번째 인자 : 페이로드에 담을 정보 (userId) - 누구나 디코딩해서 볼 수 있기에 딱 유저를 식별할 수 있는 정보만 담아야한다.

두 번째 인자 : 시크릿 키 - .env 파일로 관리하여 노출되지 않게 하는 것이 필요하나 위 예시는 그냥 이해하기 쉽게 기재했다. 

세 번째 인자 : 옵션 값 - 여기서는 expiresIn이라는 키 값으로 유효기간을 명시했다. 

 

만들어진 토큰을 백엔드에서 쿠키에 담아서 줄 수도 있고, 

토큰 자체를 전달하여 프론트에서 처리할 수도 있다. 

(프론트에서 처리하게 하는 이유는 쿠키는 브라우저에만 존재하기 때문에 만약 브라우저가 아닌 곳에서 로그인 요청이 왔을 때 쿠키에 토큰값을 담아서 주면 여러 처리가 필요하기 때문이다.) 

 

하지만 우리는 웹 개발이기 때문에 브라우저를 이용하는 서비스로 백엔드에서 쿠키에 담아서 주는 것을 구현해보겠다. 

#3. 만든 토큰을 쿠키에 담아서 전달하기 

// auth.router.js

// 상단 코드 생략 ...
  
  // 일치하는 경우가 있다면 jwt토큰 생성
  const token = jwt.sign({userId},"Secret Key",{expiresIn : "12h"});
  
  res.cookie("Authorization", `Bearer ${token}`);
  
  return res.status(200).json({message: "로그인에 성공했습니다."});
  
})

 

res.cookie라는 메서드를 사용하여 응답 시 쿠키에 만든 토큰을 저장하여 전달한다. 

 

첫 번째 인자는 쿠키의 이름(키)에 해당하고,

두 번째 인자는 쿠키의 값(벨류)에 해당한다. 

토큰 값 앞에 Bearer는 토큰의 타입을 의미한다. 

https://iu-corner.tistory.com/entry/JWT-%EC%9D%B8%EC%A6%9D%ED%86%A0%ED%81%B0-Bearer-%ED%86%A0%ED%81%B0%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC#Bearer

 

JWT 인증토큰, Bearer 토큰에 관하여.. for Node Express.

JWT 인증토큰, Bearer 토큰에 관하여.. for Node Express. JWT 란, JWT(Json Web Token)은 클라이언트와 서버 혹은 서비스 간의 통신시 정보를 JSON 객체를 통해 안전하게 전송하고 권한(Authorization)을 위해 사용하

iu-corner.tistory.com

 

다양한 토큰 타입이 있으니 참고해도 좋을듯 하다. 

 

이렇게 로그인이 성공하면서 서버는 JWT토큰을 쿠키에 저장하여 보내게 되고 

로그인 한 유저가 다른 요청을 보낼 때 쿠키를 함께 보내서 요청하게 되므로 로그인을 유지할 수 있다. 

(물론 그 토큰이 유효한 토큰인지 검사하는 단계가 필요하지만..) 

 

앞서 말한 것과 같이 쿠키가 없는 앱에서 요청할 경우에는 토큰 값만 response 값으로 보내고 관련된 처리는 프론트에서 하는 경우도 있으니 꼭 백엔드에서 쿠키를 만들어줘야한다는 생각은 하지 않아야겠다.