본문 바로가기
개발/Backend

[Node.js] JWT 사용해서 인증하기

by du.it.ddu 2025. 2. 1.

요즈음 사이드 프로젝트를 하면서 Firebase를 백엔드로 활용하고 있습니다.
Functions와 Node.js의 조합으로 백엔드를 구현하고 있고 그 외에 필요한 서비스들을 붙여가고 있습니다.

서비스를 개발하면 회원가입, 로그인과 같은 인증을 구현하는것이 거의 필수적이다보니 Firebase에서 제공해주는 인증 서비스를 사용하여 구현하였습니다만, 속도가 매우매우 느려서 전체적인 API 퍼포먼스가 너무 안좋았습니다.

그래서 Firebase의 인증을 버리고 직접 DB와 인증 토큰 처리를 구현했습니다.

JWT란?

JWT는 Json Web Token의 약어로, 인터넷 표준 인증 방식입니다.
이름을 봤을때에는 인증에 필요한 정보들이 Json 처럼 생겨있을 것 같고, 암호화된 Token 형식일 것 같이 느껴지죠.

JWT는 {Header}.{Payload}.{Signature} 의 구조로, 세가지 요소가 점(.)으로 구분되어 있는 형태입니다.

 

Header

Header는 토큰의 타입과 해시에 사용된 알고리즘 정보 등의 정보를 담는 영역으로 base64로 인코딩되어 있습니다.

{
    "typ": "JWT",
    "alg": "HS512"
}

만약 Header가 위와 같다면 토큰의 타입은 JWT, 해시 알고리즘은 HS512 입니다.
여기서 해시 알고리즘이 필요한 이유는 JWT는 토큰의 위변조 방지를 위한 서명이 포함되어 있는데, 서명을 암호화하기 위해 해시 알고리즘이 필요합니다.

 

Payload

토큰에서 사용할 정보의 조각들인 Claim이 담겨있습니다.
즉, JWT를 통해 실제로 알 수 있는 데이터를 뜻하며, 서버와 클라이언트간에 주고받는 사용자 정보입니다.

{
    "sub": "12345678",
    "userId": "abcdefg",
    ...
}

Payload는 base64로 인코딩되어 있으며, 누구나 읽을 수 있는 정보이기 때문에 민감한 정보를 삽입하면 안됩니다.

클레임 중에는 토큰을 위해 미리 정의된 등록된 클레임(Registered Claim) 들이 존재합니다.
예를 들면 iss(토큰 발급자), sub(토큰 제목), aud(토큰 대상자), exp(토큰 만료 시간) 등이 있습니다.
Payload에 어떤 데이터를 삽입할 때 이 클레임들과 중복되지 않도록 합시다.

 

Signature

시그니처(서명)은 토큰의 유효성을 검증할 때 사용하는 암호화 코드입니다.
시그니처는 Header와 Payload를 Base64로 각각 인코딩한 뒤 점(.) 으로 잇습니다.
그리고 그 값을 암호화 알고리즘으로 해싱하는데, 이 때 서버의 비밀키를 사용합니다.
마지막으로 해싱된 값을 Base64로 인코딩한 값이 Signature가 됩니다.

 

Node.js에서 사용하기

아주 고맙게도 Node.js에서 JWT를 편하게 사용할 수 있는 패키지가 있습니다.

https://www.npmjs.com/package/jsonwebtoken

 

jsonwebtoken

JSON Web Token implementation (symmetric and asymmetric). Latest version: 9.0.2, last published: a year ago. Start using jsonwebtoken in your project by running `npm i jsonwebtoken`. There are 32516 other projects in the npm registry using jsonwebtoken.

www.npmjs.com

패키지 설치

먼저 npm을 사용하여 jsonwebtoken 패키지를 설치해줍니다.

 npm install jsonwebtoken

 

암호화에 사용할 키 정의

서버에서 암호화에 사용할 비밀키를 정의합시다.
샘플 또는 사이드 프로젝트에서는 온라인에서 제공되는 제네레이터를 사용하는데, 불안한다면 다른 방법을 써도 됩니다.
회사와 같은 곳이라면 서버에서 직접 생성하는 것이 옳습니다.
https://jwtsecret.com/generate

 

JwtSecret.com - Generate JWT Secrets Online

Full secret is hidden for security.

jwtsecret.com

이 키를 dotenv 등을 사용해서 불러오도록 하면 되겠습니다.

 

토큰 생성

const jwt = require('jsonwebtoken');

// 토큰 만료시간을 적절하게 설정하세요. ex) "60", "2 days", "10h", "7d"
const TOKEN_EXPIRATION = "2h";
const SECRET_KEY = process.env.SECRET_KEY;

function sign(value) {
    const token = jwt.sign({ field: value }, SECRET_KEY, { expiresIn: TOKEN_EXPIRATION });
    return token;
};

토큰은 sign 함수로 생성합니다.
sign 함수에 필요한 정보들을 json 형태로 전달하고, 비밀키, 토큰 만료시간 같은 것들을 전달하면 토큰이 생성됩니다.

토큰 인증

jwt.verify(token, secretKey, (err, decoded) => {
    if (err) {
        // 에러 처리
    } else {
        // 성공 처리
        // decoded가 Payload를 의미합니다.
    }
});

토큰 인증은 verify 함수로 합니다.
검증할 토큰과 비밀키를 전달하면 에러 또는 복원된 Payload 값을 콜백해줍니다.

 

이렇게 직접 서버와 클라이언트의 인증을 JWT를 통해 구현하면 관리 비용은 늘어나겠지만, Firebase 인증과 같은 서비스를 사용함으로써 발생하는 성능 저하를 개선할 수 있습니다.

또한 실제 서비스에서 어플리케이션을 개발한다면 사용자 관리와 인증을 대부분 직접 개발하게 되므로 JWT를 이해하고 있다면 큰 이점이 될 수 있습니다.

반응형