백엔드 개발을 하다 보면 사용자 인증은 필수적인 요소 중 하나입니다. 특히 RESTful API를 구현할 때는 JSON Web Token(JWT)을 활용한 인증 방법이 많이 사용됩니다. 이번 글에서는 Node.js를 활용하여 간편하게 JWT 인증을 구현하는 미니 프로젝트를 진행해 보겠습니다.

프로젝트 환경 설정

우선, Node.js와 npm이 설치되어 있어야 합니다. 프로젝트를 시작하기 전에 새로운 디렉토리를 만들고, 해당 디렉토리로 이동한 후 npm을 통해 새로운 Node.js 프로젝트를 초기화합니다.

mkdir jwt-auth-example
cd jwt-auth-example
npm init -y

이후 JWT 인증을 구현하기 위해 필요한 패키지를 설치합니다. express, jsonwebtoken, bcrypt, dotenv 패키지를 설치합니다.

npm install express jsonwebtoken bcrypt dotenv

기본 구조 설정

index.js 파일을 생성하고, Express 서버를 설정한 후 기본적인 라우팅을 추가합니다.
// index.js
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());

let users = []; // 사용자 정보를 저장할 배열

app.listen(PORT, () => {
    console.log(서버가 ${PORT} 포트에서 실행되고 있습니다.);
});

회원가입 기능

사용자가 회원가입을 할 수 있는 API 엔드포인트를 추가합니다. 비밀번호는 bcrypt를 사용하여 암호화합니다.

app.post('/signup', async (req, res) => {
    const { username, password } = req.body;

    const hashedPassword = await bcrypt.hash(password, 10);
    users.push({ username, password: hashedPassword });

    res.status(201).json({ message: "회원가입 성공" });
});

로그인 기능

이제 사용자가 로그인할 수 있는 API 엔드포인트를 추가합니다. 로그인 성공 시 JWT를 발급합니다.

app.post('/login', async (req, res) => {
    const { username, password } = req.body;
    const user = users.find(u => u.username === username);

    if (!user) {
        return res.status(404).json({ message: "사용자를 찾을 수 없습니다." });
    }

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) {
        return res.status(401).json({ message: "비밀번호가 일치하지 않습니다." });
    }

    const token = jwt.sign({ username: user.username }, process.env.JWT_SECRET, { expiresIn: '1h' });

    res.status(200).json({ token });
});

보호된 라우트 설정

이제 JWT가 필요한 보호된 라우트를 설정해 보겠습니다. 인증된 사용자만 접근할 수 있도록 미들웨어를 구현합니다.

const authenticateJWT = (req, res, next) => {
    const token = req.headers['authorization']?.split(' ')[1];

    if (!token) {
        return res.sendStatus(403);
    }

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
        if (err) {
            return res.sendStatus(403);
        }
        req.user = user;
        next();
    });
};

app.get('/protected', authenticateJWT, (req, res) => {
    res.status(200).json({ message: "이 보호된 라우트에 접근하셨습니다." });
});

.env 파일 설정

JWT 비밀 키를 안전하게 관리하기 위해 .env 파일을 생성하고, 여기에 비밀 키를 저장합니다.

JWT_SECRET=mysecretkey
PORT=3000

테스트 및 실행

이제 모든 설정이 완료되었습니다. 서버를 실행하고 Postman과 같은 도구를 사용하여 API를 테스트할 수 있습니다.

node index.js
  1. 회원가입: POST /signup
  2. - 요청 본문:

         {
           "username": "testuser",
           "password": "password123"
         }
  3. 로그인: POST /login
  4. - 요청 본문:

         {
           "username": "testuser",
           "password": "password123"
         }
  5. 보호된 라우트 접근: GET /protected
- Authorization 헤더에 Bearer <JWT_TOKEN>을 추가하여 요청합니다.

마무리

이번 글에서는 Node.js를 사용하여 간단한 JWT 인증 미니 프로젝트를 구현해 보았습니다. JWT는 간편하게 사용자 인증을 처리할 수 있는 좋은 방법으로, 특히 API를 개발할 때 유용합니다. 이 프로젝트를 통해 JWT의 기본 개념과 실제 구현 방법을 익힐 수 있었기를 바랍니다. 이제 이 코드를 기반으로 더 복잡한 인증 시스템으로 발전시켜 보세요!