웹 프로젝트를 진행하면서, JWT 토큰을 활용하여 로그인과 로그아웃 기능을 구현했습니다. 함께 JWT 사용하는 방법을 알아볼까요?
JWT 토큰이란?
JWT(JSON Web Token)는 클라이언트와 서버간에 정보를 안전하게 전달하기 위한 간편한 방법 중 하나입니다. 이에 포함된 정보는 디지털 서명이 되어 있어, 전송 중 정보가 조작되지 않았음을 검증할 수 있습니다. JWT 토큰은 주로 웹사이트의 사용자 인증에 사용되며, 로그인 과정을 통해 발행된 토큰을 이용하여 사용자의 신원을 확인하는 방식입니다.
먼저 Node.js의 패키지 매니저인 npm을 이용하여 jsonwebtoken 패키지를 설치
$ npm i jsonwebtoken
JWT를 활용한 인증절차
1. 클라이언트는 서버에 로그인 요청을 하고, 서버는 유효한 사용자임을 확인한 후에 JWT를 생성
2. JWT는 클라이언트에게 전달되고, 클라이언트는 JWT를 이후 요청에서 사용하여 자신이 누구인지 인증
3. 클라이언트가 요청을 보낼 때마다 서버는 JWT의 유효성을 검증하여 요청을 처리
JWT(JSON Web Token)는 페이로드(payload)를 인코딩하고 서명(signature)하는 과정에서 사용하는 키(key)가 중요합니다. 유의할 점은 JWT를 생성할 때 사용한 키와 JWT를 검증할 때 사용하는 키는 동일해야 합니다. 다른 키를 사용하게 된다면 서버는 JWT의 서명을 검증하지 못하게 되어 인증 과정에서 실패합니다! 따라서 userId와 같은 정보를 추출할 수 없게 됩니다. JWT의 생성과 검증에 사용되는 키가 일치하는 것은 JWT의 안전성과 무결성을 보장하는 매우 중요한 부분입니다.
프로젝트에서의 실제 서비스 코드구현
secretKey는 보안을 위해 일반적으로 .env 파일에 작성
JWT_SECRET=Jwtsecretkey //예시 key이며 다르게 설정하는 것이 좋습니다!
인증(Authentication) 관련 로직을 처리할 auth.js에 작성
const jwt = require("jsonwebtoken");
require("dotenv").config(); //dotenv 패키지를 사용하여 .env 파일의 환경 변수 로드
try {
if (!token) {
throw new Error();
}
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findOne({ _id: decoded.userId }); // 토큰에서 추출한 userId를 이용해 데이터베이스에서 사용자 찾기
if (!user) {
throw new Error();
}
req.user = user; // 요청 객체에 사용자 정보를 추가
next();
} catch (error) {
// 토큰이 유효하지 않거나 사용자가 존재하지 않을 경우, 에러를 반환하여 접근을 차단
console.log(error);
res.status(401).send({ error: "잘못된 요청입니다." });
}
};
로그인 라우터
const jwt = require("jsonwebtoken");
require("dotenv").config(); //dotenv 패키지를 사용하여 .env 파일의 환경 변수 로드
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, {
expiresIn: "1h", // jwt.sign() 메서드를 통해 jwt 토큰 발행, 1시간 후 토큰이 만료되게 설정
});
res.status(200).json({ token, userId: user._id });
} catch (err) {
console.error("Error:", err.message);
console.error("Stack:", err.stack);
res.status(500).json({ message: "서버 오류" });
}
});
JWT의 장단점
장점
• 대부분의 개발 언어와 프레임워크에서 라이브러리를 제공하므로, 쉽게 구현하고 사용
• JWT는 인증에 필요한 모든 정보를 담고 있기 때문에 인증을 위한 별도의 저장소가 없어도 된다.
• 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능하다.
단점
• 쿠키/세션과 다르게 토큰의 길이가 길기때문에 인증 요청이 많아질수록 네트워크 오버헤드 발생
• Payload 자체는 암호화가 되지 않아 중요한 정보는 담을 수 없다.
• 토큰의 유출이나 변조가 발생할 경우 문제점이 생긴다.
보완할 점
프로젝트에서 JWT를 사용하여 엑세스 토큰만 구현한 결과, 엑세스 토큰의 만료 문제가 발생하여 만료될 때마다 로그인을 다시 해야합니다.
• 엑세스 토큰: 서버 API를 직접 요청할 때 사용한다.
• 리프레시 토큰: 엑세스 토큰이 만료되었을 때 엑세스 토큰을 재발급할 목적으로 사용한다.
다음 글에서는 리프레시 토큰을 이용한 방식을 함께 살펴보겠습니다!
'Framework > Node.js' 카테고리의 다른 글
[Node.js] Naver Oauth로 로그인 구현해보기 (0) | 2024.07.25 |
---|---|
[node.js] blocking vs nonblocking (2) | 2024.07.05 |
[node.js] JWT에서 Refresh Token의 필요성 (0) | 2024.07.05 |