
"서버와 클라이언트 간에 데이터를 안전하게 주고받기 위한 토큰(Token)"
➿JWT 구조
JWT는 3개의 부분으로 나뉘어 있다:
1. Header
타입(typ)과 해시 알고리즘(alg) 정보가 들어있다.
{
"alg": "HS256", // 서명 알고리즘 (예: HMAC SHA-256)
"typ": "JWT" // 토큰 타입 (JWT 고정)
}
2. Payload
실제 담고 싶은 사용자 정보(Claim)가 들어간다.
{
"userid": "apple",
"role": "user",
"iat": 1697682149,
"exp": 1697685749
}
| userid | 사용자 고유 ID |
|---|---|
| role | 사용자 권한(예: user, admin) |
| iat | 토큰 발급 시간 (issued at, 초 단위) |
| exp | 토큰 만료 시간 (expiration, 초 단위) |
3. Signature
비밀 키(secret)를 이용해서 Header와 Payload를 암호화한 값이다.
HMACSHA256(
Base64UrlEncode(header) + "." + Base64UrlEncode(payload),
secret
)
➿ JWT 사용 흐름
사용자가 로그인하면 서버가 JWT를 발급한다.
클라이언트(브라우저, 앱)는 이 토큰을 저장한다. (보통 localStorage나 cookie에)
클라이언트가 서버에 API 요청할 때마다 토큰을 같이 보낸다. (주로 Authorization: Bearer 헤더로)
서버는 토큰을 검증해서 요청을 허용하거나 거부한다.
✅ JWT 장점
⚠️ JWT 주의점

설치
npm install jsonwebtoken
import jwt from "jsonwebtoken";
const secretKey = "!@#$%^&*()";
// 1. 토큰 생성
const token = jwt.sign({ userid: "apple", role: "admin" }, secretKey, {
expiresIn: "1h",
});
console.log("생성된 토큰: ", token);
// 2. 토큰 검증
try {
const decoded = jwt.verify(token, secretKey);
console.log("검증된 토큰 내용: ", decoded);
} catch (error) {
console.log("토큰 검증 실패: ", error.message);
}
C:\Hsgo\Nodejs>node 18_JWT.mjs
생성된 토큰: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJhcHBsZSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc0NTgwMDU5MywiZXhwIjoxNzQ1ODA0MTkzfQ.1Rz6iyzQD_C7VD3-CsC01iHVb7Hva1KFmXlQPbHWmQ4
검증된 토큰 내용: { userid: 'apple', role: 'admin', iat: 1745800593, exp: 1745804193 }
밑에는 실패했을 때!
C:\Hsgo\Nodejs>node 18_JWT.mjs
생성된 토큰: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJhcHBsZSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc0NTgwMDU4MCwiZXhwIjoxNzQ1ODA0MTgwfQ.5Z6k7farDkAy8a8ENCZi9roz0_KXn7hg-Hzv4Qaf2pI
6k7farDkAy8a8ENCZi9roz0_KXn7hg-Hzv4Qaf2pI
토큰 검증 실패: tokeb is not defined
| 개념 | 의미 |
|---|---|
| Encode (인코딩) | 데이터를 다른 형식으로 변환해서 전송하거나 저장할 수 있도록 바꾸는 것 |
| Decode (디코딩) | 인코딩된 데이터를 다시 원래 형태로 복원하는 것 |
비밀번호 같은 민감한 데이터를 안전하게 암호화(해시) 하기 위해 사용하는 알고리즘이다.
➿ bcrypt를 쓰는 이유
비밀번호를 평문(plain text) 으로 저장하면, 데이터베이스가 해킹당했을 때 큰 사고로 이어질 수 있다.
bcrypt는 단방향 해시 함수라 복호화(원래 비밀번호 복원)가 불가능하다.
추가로 salt(솔트) 라는 랜덤 데이터를 붙여서 해시하기 때문에, 같은 비밀번호라도 해시 결과가 다르게 나온다.
✅ 비밀번호를 비교할 때는 "비밀번호를 다시 해시해서 결과를 비교" 한다.
설치
npm install bcrypt
import bcrypt from "bcrypt";
const password = "apple1004";
const saltRounds = 10;
// 1. 비밀번호 해시화
async function hashPassword(password) {
const hashed = await bcrypt.hash(password, saltRounds);
console.log("해시된 비밀번호 : ", hashed);
return hashed;
}
// 2. 비밀번호 검증
async function verifyPassword(inputPassword, hashedPassword) {
const isMatch = await bcrypt.compare(inputPassword, hashedPassword);
console.log("비밀번호 일치 여부: ", isMatch);
return isMatch;
}
async function runExample() {
const hashed = await hashPassword(password);
await verifyPassword("apple1004", hashed);
await verifyPassword("apple8282", hashed);
}
runExample();
C:\Hsgo\Nodejs>node 19_bcrypt.mjs
해시된 비밀번호 : $2b$10$wACiuhcCxDSEijykNwHAkObMRYI2UWw8dHjAlBcy3rX6iT/j/kQo.
비밀번호 일치 여부: true
비밀번호 일치 여부: false