안녕하세요, 즐로그 운영자입니다!
오늘은 Node.js+Express 기반 REST API에서 **JWT(Json Web Token)**를 활용해
“인증(Authentication)‧권한 관리(Authorization)”를 구현하는 방법을 단계별로 소개합니다.
코드 스니펫을 그대로 복사해 붙여넣기만 하면 직접 테스트해볼 수 있어요~ 😉
⸻
📋 목차
1. 왜 JWT인가?
2. 프로젝트 세팅
3. JWT 발급‧검증 미들웨어 작성
4. 회원가입·로그인 라우트 구현
5. 보호된 라우트(권한 검사) 구현
6. 실전 팁 & 보안 고려사항
7. 마무리
⸻
1️⃣ 왜 JWT인가?
• 자체 토큰 기반: 서버에 세션 저장 없이도 클라이언트 검증 가능
• 확장성: 분산 시스템·마이크로서비스 간 인증 공유
• 표준 규격: 헤더(Header)·페이로드(Payload)·서명(Signature) 구조로 가독성·안정성 확보
⸻
2️⃣ 프로젝트 세팅
# 1) 새 프로젝트 생성
mkdir express-jwt-auth && cd express-jwt-auth
npm init -y
# 2) 필수 패키지 설치
npm install express jsonwebtoken bcryptjs dotenv
# 3) 개발 편의용
npm install --save-dev nodemon
// package.json (scripts 부분)
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
}
# 4) .env 파일 생성
echo "JWT_SECRET=your_super_secret_key" >> .env
echo "PORT=4000" >> .env
⸻
3️⃣ JWT 발급·검증 미들웨어 작성
// auth.js
require('dotenv').config();
const jwt = require('jsonwebtoken');
// 토큰 발급 함수
function signToken(user) {
// 페이로드에 최소 정보만 담기 (예: userId, role)
const payload = { id: user.id, role: user.role };
return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });
}
// 토큰 검증 미들웨어
function verifyToken(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader) return res.status(401).json({ error: '토큰 누락' });
const token = authHeader.split(' ')[1];
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) return res.status(403).json({ error: '유효하지 않은 토큰' });
req.user = decoded; // req.user.id, req.user.role 사용 가능
next();
});
}
// 권한 검사 미들웨어 (예: admin 전용)
function requireRole(role) {
return (req, res, next) => {
if (req.user.role !== role) {
return res.status(403).json({ error: '권한이 없습니다' });
}
next();
};
}
module.exports = { signToken, verifyToken, requireRole };
⸻
4️⃣ 회원가입·로그인 라우트 구현
// index.js
require('dotenv').config();
const express = require('express');
const bcrypt = require('bcryptjs');
const { signToken, verifyToken, requireRole } = require('./auth');
const app = express();
app.use(express.json());
const users = []; // 예시용 메모리 DB
// 1. 회원가입
app.post('/signup', async (req, res) => {
const { username, password, role } = req.body;
const hashed = await bcrypt.hash(password, 10);
const user = { id: users.length + 1, username, password: hashed, role: role || 'user' };
users.push(user);
res.json({ message: '회원가입 완료' });
});
// 2. 로그인
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user) return res.status(400).json({ error: '유저 없음' });
const valid = await bcrypt.compare(password, user.password);
if (!valid) return res.status(400).json({ error: '비밀번호 불일치' });
const token = signToken(user);
res.json({ token });
});
// 3. 공개 라우트
app.get('/public', (req, res) => {
res.json({ message: '모두 접근 가능' });
});
// 4. 보호된 라우트 (인증 필요)
app.get('/protected', verifyToken, (req, res) => {
res.json({ message: `안녕하세요, 유저 #${req.user.id}` });
});
// 5. 관리자 전용 라우트
app.get('/admin', verifyToken, requireRole('admin'), (req, res) => {
res.json({ message: '관리자 전용 페이지' });
});
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => console.log(`🚀 서버 실행 중: http://localhost:${PORT}`));
⸻
5️⃣ 실전 팁 & 보안 고려사항
• 비밀 키 관리: .env에 절대 노출 금지, Vault·Secret Manager 활용
• 토큰 만료: 짧은 수명(1h) + 리프레시 토큰 별도 구현
• HTTPS 적용: 전송 구간 암호화로 토큰 탈취 방지
• CORS 설정: 신뢰할 수 있는 도메인만 허용
• JWT 페이로드 최소화: 민감정보·장문 데이터 금지
⸻
6️⃣ 마무리
지금까지 Node.js+Express+JWT 기반 REST API에서
• 회원가입·로그인
• JWT 발급·검증
• 권한(Role) 검사
과정까지 포괄적으로 다뤄봤습니다.
코드 스니펫만 따라 해도 인증·권한 관리 기본 골격이 완성되니,
여러분 프로젝트에 바로 적용해 보세요!
다음 포스트에서 “비동기 작업 큐 처리(Python+Celery)” 편으로 이어갑니다~
행복한 개발 되세요! 👋
'IT & Tech 정보' 카테고리의 다른 글
🚀 GraphQL 서버 설계 및 구현: Apollo Server + TypeScript (0) | 2025.05.25 |
---|---|
🚀 비동기 작업 큐 처리: Python + Celery + RabbitMQ (0) | 2025.05.25 |
🚀 실무자를 위한 AI 도구 사용 가이드 & 핵심 코드 스니펫 (0) | 2025.05.25 |
🚀 RPA 고도화: 에러 복구·셀프 모니터링 설계 (0) | 2025.05.25 |
OCR·NLP·CV 서비스: Azure vs GCP 활용법 (0) | 2025.05.25 |