설모의 기록

jsonwebtoken 모듈 본문

언어/Javascript

jsonwebtoken 모듈

HA_Kwon 2018. 1. 16. 11:48

서버와 클라이언트 간 통신할 때 식별하기

  어플리케이션 또는 웹페이지를 만들 때 클라이언트와 서버가 통신을 해야하는 경우가 있습니다. 이 때, 어떤 사용자가 서버에게 요청을 걸었는지 알기 위해 사용자마다 식별할 수 있는 정보를 서버에게 넘겨 서버가 사용자에 맞는 정보를 보내주어야 합니다. 그렇게 하기위해 로그인을 하는 것이겠죠? 기본적인 웹페이지 구현에서는 클라이언트와 서버가 각각 쿠키와 세션에 정보를 저장하고, 통신할 때 정보를 주고 받습니다. 사용자가 로그인을 하면 서버에서 세션ID 를 생성해 클라이언트에게 보내주고, 클라이언트는 그 세션ID 를 쿠키에 저장합니다. 쿠키는 서버와 통신을 할 때 request header에 자동으로 넣어져 서버에 전송됩니다. 서버는 클라이언트가 요청을 하면 그 요청의 header 에 있는 쿠키 중 세션ID 쿠키를 보고 어느 사용자인지 안 후 요청을 처리하는 것입니다. 이렇게 통신을 하면 사용자가 로그인을 계속 하지 않아도 로그아웃하기 전 혹은 오랜시간동안 다시 로그인하지 않기 전(쿠키가 삭제되기 전) 까지 로그인 상태가 유지됩니다. 

  세션은 서버 메모리에 저장된다고 앞서 말씀드렸는데요. 이렇게 통신을 하다보면 사용자가 늘어날 경우 서버가 가지고 있는 세션 정보가 많아져 과부하 상태가 될 수 있습니다. 그렇다고 데이터베이스에 세션값을 저장하려해도 유저가 많아진다면 데이터베이스 성능이 낮아집니다.




토큰 기반 통신

  토큰을 기반으로 통신을 하게 되면 서버 메모리 때문에 과부하가 걸리지 않을까 하는 걱정이 사라집니다. 클라이언트가 로그인을 요청하면 서버는 로그인 정보를 검증한 후 존재하는 유저라면 토큰을 생성해 클라이언트에 넘겨줍니다. 클라이언트는 받은 토큰을 서버에 요청할 때마다 request header 에 실어서 같이 보내줍니다. 그 요청을 보며 서버는 유저를 식별하게 되는 것이죠. 어찌보면 쿠키 / 세션 과 비슷한 이야기지만 서버의 메모리 공간을 이용하지 않기 때문에 각광받고 있는 통신 방법입니다. 서버에 세션과 같은 정보를 저장하지 않는다면 서버를 확장하기에 용이합니다. 세션을 저장하고 있는 경우를 생각해보면, 유저1의 세션정보가 서버1에 저장되어 있다고 가정해보자. 서비스가 엄청 잘 돼서 서버를 5개까지 늘리는 경우가 생길 수 있습니다. 그렇지만 유저1은 항상 서버1에 요청을 보내야 하기 때문에 매우 불편합니다. 그러나 토큰 기반 방식은 정보를 서버에 저장하지 않기 때문에 서버를 확장해도 무방합니다.




JWT(Json Web Token) Module 

  이제 본격적으로 jwt 모듈을 사용하는 방법을 알아볼까요? 우선 jwt 모듈을 설치하고 파일 상단에 변수로 선언합니다.

// 모듈 설치
$ npm install -g jsonwebtoken


// 파일 상단에서 모듈 선언
const jwt = require('jsonwebtoken');

   


  jwt 모듈에서 토큰을 만들어 반환하는 내용은 다음과 같습니다. 

header.payload.signiture

  헤더는 토큰을 만들 때 사용하려는 알고리즘 종류, 토큰이 유효한 기간등을 이용해 만듭니다. payload 는 토큰을 생성하려는 정보를 이용해 만듭니다. 마지막으로 signiture 는 header 와 payload 를 base64로 인코딩해 합친 정보입니다.


  저는 node.js 프로젝트에서 jwt 모듈을 사용하는 방법을 소개하겠습니다. jwt.sign() 메소드에는 4개의 인자를 넘깁니다. payload, sercetKey, options, callback 이렇게 네개를 넘기게 되는데요. 아래의 예제로 이해해 볼까요?

1
2
3
4
5
6
7
8
9
10
11
const secretKey = "secret_key";
 
//JWT 토큰 설정값
const option = {
  algorithm : 'HS256',  // 토큰 암호화 방식
  expiresIn :  "7d"     // 토큰의 유효기간
};
 
const payload = {
  memberId : user_id    // 토큰값으로 만드려는 정보들
};

  secretKey 는 signiture 를 만들 때 사용하는 알고리즘에서 사용할 문자열입니다. 말 그대로 비밀이니까 공개되지 않도록 하는게 좋겠죠?option 에는 토큰을 암호화할 알고리즘 정보와 토큰의 유효기간을 설정합니다. option 의 프로퍼티 키값에 오타가 나면 안되니까 조심해주세요. algorithm, expiresIn 외에도 프로퍼티를 더 넣을 수 있습니다. payload 에는 토큰값을 생성할 정보입니다. 저는 회원의 아이디를 토큰으로 만들겠습니다. 

1
var token = jwt.sign(payload, secretKey, option);

  토큰을 생성하는 방법은 위의 예제처럼 하시면 됩니다. 콜백메소드를 추가하시려면 option 다음에 callback 인자를 추가하시면 됩니다. 그러면 token 변수에 토큰값이 담기게 됩니다. 로그인 시 서버에서 이렇게 토큰값을 생성해 클라이언트에 넘겨주면, 클라이언트가 이후에 서버에게 요청을 할 때마다 request header 에 토큰값을 실어 요청하면 됩니다.


1
var decoded = jwtModule.decodeToken(request.headers.token);
d

  로그인 이후 들어오는 요청에서 서버는 클라이언트의 요청 header  에서 토큰값을 읽어 디코딩을 해야합니다. jwtModule.decodeToken() 메소드를 이용해 토큰값을 디코딩하면 decoded 변수에 그 값이 담기게 됩니다. 저는 회원아이디를 payload 값에 넣었기 때문에 이제 decoded.memberId 이렇게 접근하시면 처음에 넣었던 회원아이디를 얻을 수 있습니다. 그 값을 통해 요청을 처리하면 되겠죠?


이상으로 jsonwebtoken 모듈에 대해 알아보았습니다.

'언어 > Javascript' 카테고리의 다른 글

[javascript] 정규식 체크  (0) 2018.02.15
[ES6] var, let, const 변수 선언  (0) 2018.02.01
nodemailer 모듈 사용하기  (0) 2018.01.13
async.waterfall() 메소드  (1) 2018.01.08
bcrypt-nodejs 모듈 사용하기  (0) 2018.01.08
Comments