JWT를 이용한 사용자 인증 구현: 회원가입 및 로그인 기능
이번 강의에서는 **JWT(Json Web Token)**를 사용해 사용자 인증 및 권한 부여를 구현하는 방법을 다룹니다. JWT는 웹 애플리케이션에서 사용자 인증에 널리 사용되는 방식으로, 사용자가 로그인할 때 서버에서 토큰을 발급하고, 클라이언트는 이를 저장해 이후의 요청에서 인증을 유지합니다.
1. JWT란?
**JWT(Json Web Token)**는 JSON 형식의 데이터를 기반으로 사용자 인증 및 권한 부여를 위한 표준입니다. JWT는 세 가지 부분으로 나뉩니다:
- Header: 토큰의 타입(JWT)과 해싱 알고리즘(예: HS256) 정보.
- Payload: 사용자 관련 정보(예: 사용자 ID, 권한 등)가 포함됨.
- Signature: Header와 Payload를 해싱한 값으로, 토큰의 무결성을 검증.
JWT는 주로 Bearer 토큰 방식으로 HTTP 헤더에 포함되어 클라이언트에서 서버로 전달됩니다.
2. JWT 설치 및 설정
2.1 필요한 라이브러리 설치
JWT를 사용하기 위해 jsonwebtoken과 bcryptjs(비밀번호 해싱을 위한 라이브러리)를 설치합니다.
npm install jsonwebtoken bcryptjs
3. 회원가입 및 로그인 기능 구현
3.1 MySQL에 사용자 테이블 생성
MySQL 데이터베이스에서 사용자 정보를 저장할 users 테이블을 생성합니다.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100),
password VARCHAR(255)
);
3.2 회원가입 기능 구현
회원가입 시 사용자가 입력한 비밀번호는 bcryptjs를 사용해 해싱된 상태로 저장합니다.
// server.js
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const db = require('./db');
const app = express();
app.use(express.json());
// JWT 시크릿 키
const JWT_SECRET = 'your_jwt_secret_key';
// 회원가입 API
app.post('/register', (req, res) => {
const { username, password } = req.body;
// 비밀번호 해싱
const hashedPassword = bcrypt.hashSync(password, 8);
// MySQL에 사용자 정보 저장
const query = 'INSERT INTO users (username, password) VALUES (?, ?)';
db.query(query, [username, hashedPassword], (err, result) => {
if (err) {
return res.status(500).send('Error registering user');
}
res.status(201).send('User registered successfully');
});
});
3.3 로그인 기능 구현
로그인 시 입력한 비밀번호를 bcrypt를 사용해 해싱된 비밀번호와 비교한 후, 인증에 성공하면 JWT를 생성하여 클라이언트에 전달합니다.
// 로그인 API
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 사용자 확인
const query = 'SELECT * FROM users WHERE username = ?';
db.query(query, [username], (err, results) => {
if (err || results.length === 0) {
return res.status(404).send('User not found');
}
const user = results[0];
const passwordIsValid = bcrypt.compareSync(password, user.password);
if (!passwordIsValid) {
return res.status(401).send('Invalid password');
}
// JWT 생성
const token = jwt.sign({ id: user.id }, JWT_SECRET, {
expiresIn: '1h' // 토큰 만료 시간 설정
});
res.json({ auth: true, token });
});
});
3.4 인증 미들웨어
JWT를 검증하는 미들웨어를 만들어, 보호된 API에서 인증된 사용자만 접근할 수 있도록 설정합니다.
// 인증 미들웨어
function verifyToken(req, res, next) {
const token = req.headers['authorization'];
if (!token) {
return res.status(403).send('No token provided');
}
jwt.verify(token.split(' ')[1], JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(500).send('Failed to authenticate token');
}
req.userId = decoded.id;
next();
});
}
// 보호된 라우트 예시
app.get('/protected', verifyToken, (req, res) => {
res.send(`Hello User ${req.userId}, you are authenticated`);
});
4. 프론트엔드에서 JWT 사용
4.1 로그인 후 토큰 저장
로그인 후 JWT를 받아 localStorage 또는 sessionStorage에 저장할 수 있습니다. 이 토큰은 이후 API 요청 시 인증에 사용됩니다.
// src/components/Login.js
import React, { useState } from 'react';
import axios from 'axios';
function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleLogin = (e) => {
e.preventDefault();
axios.post('/login', { username, password })
.then((response) => {
localStorage.setItem('token', response.data.token);
alert('Logged in successfully');
})
.catch((error) => {
console.error('Error logging in:', error);
});
};
return (
<form onSubmit={handleLogin}>
<h2>로그인</h2>
<div>
<label>아이디</label>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div>
<label>비밀번호</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<button type="submit">로그인</button>
</form>
);
}
export default Login;
5. 보호된 API에 접근
프론트엔드에서 보호된 API에 접근할 때, 저장된 JWT를 Authorization 헤더에 추가하여 요청을 보냅니다.
// 보호된 API 호출 예시
axios.get('/protected', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
})
.then((response) => {
console.log('Protected data:', response.data);
})
.catch((error) => {
console.error('Error accessing protected API:', error);
});
6. JWT 기반 인증 흐름 요약
- 회원가입: 사용자가 회원가입 시 비밀번호는 해싱된 상태로 MySQL에 저장됩니다.
- 로그인: 사용자가 로그인하면 JWT가 생성되어 클라이언트에 전달됩니다.
- JWT 저장: 클라이언트는 JWT를 localStorage 또는 sessionStorage에 저장하여 이후 요청에서 사용합니다.
- 인증 미들웨어: 서버에서는 보호된 API에 접근할 때 JWT를 검증하여 사용자의 권한을 확인합니다.
결론
이번 강의에서는 JWT를 사용해 사용자 인증 및 권한 부여를 구현하는 방법을 배웠습니다. 회원가입, 로그인, JWT 생성 및 검증, 그리고 보호된 API 접근까지의 흐름을 통해, 웹 애플리케이션에서 안전한 인증 시스템을 구축할 수 있습니다.
'React와 Node.js를 사용한 웹 애플리케이션 개발' 카테고리의 다른 글
React와 Node.js를 사용한 웹 애플리케이션(게시판) 개발 강좌(17) (1) | 2024.09.21 |
---|---|
React와 Node.js를 사용한 웹 애플리케이션(게시판) 개발 강좌(16) (1) | 2024.09.21 |
React와 Node.js를 사용한 웹 애플리케이션(게시판) 개발 강좌(15) (1) | 2024.09.19 |
React와 Node.js를 사용한 웹 애플리케이션(게시판) 개발 강좌(12) (3) | 2024.09.19 |
React와 Node.js를 사용한 웹 애플리케이션(게시판) 개발 강좌(14) (2) | 2024.09.19 |