
오늘은 JWT 와 .env 를 사용해 보안을 신경쓴 코드를 학습했다.
- 사용자가 로그인 정보를 입력
- 서버에서 유효성 검사를 수행하고 JWT 발급
- 클라이언트가 JWT를 저장 (쿠키 또는 로컬스토리지)
- 이후 요청마다 JWT를 포함해 인증된 사용자임을 증명
- 서버는 JWT의 서명을 검증하여 유효한 요청인지 판단
// 방식 1
const dotenv = require('dotenv');
dotenv.config();
console.log(`${process.env.PRIVATE_KEY}`); // 문자열 보간 필요
// 방식 2
require('dotenv').config();
console.log(process.env.PRIVATE_KEY); // 바로 사용 가능
✅ 차이점
1. const dotenv = require('dotenv');을 선언한 경우, dotenv.config();를 호출해야 환경변수가 로드됨.
2. require('dotenv').config();을 사용하면 즉시 환경변수가 설정됨.
3. 첫 번째 방식에서는 템플릿 리터럴 사용 시 ${process.env.KEY}로 접근해야 함.
users.js)router.post(
'/login',
[
body('email').notEmpty().isEmail().withMessage("이메일을 확인해주세요."),
body('password').notEmpty().isString().withMessage("패스워드를 확인해주세요."),
validate
],
(req, res) => {
const { email, password } = req.body;
let sql = `SELECT * FROM users WHERE email = ?`;
conn.query(sql, email, function (err, results) {
if (err) {
return res.status(400).json({ message: err });
}
let loginUser = results[0];
if (loginUser && loginUser.password === password) {
const token = jwt.sign({
email: loginUser.email,
name: loginUser.name
}, process.env.PRIVATE_KEY, {
expiresIn: '1h',
issuer: "Donggeon"
});
res.cookie('token', token, { httpOnly: true });
res.status(200).json({ message: `${loginUser.name}님 로그인 되었습니다.` });
} else {
res.status(404).json({ message: "이메일 또는 패스워드가 틀렸습니다." });
}
});
}
);

✅ 개선된 점
1. jwt.sign()을 사용해 로그인 시 JWT 생성 및 쿠키에 저장.
2. httpOnly 옵션으로 XSS 공격 방지.
오늘 학습한 내용 중 dotenv 를 사용하면서 많이 애를 먹었다.
정말 많은 시간을 할애해서 원인을 찾아봤는데
const dotenv = require('dotenv');
dotenv.config();
...
require('dotenv').config();
이 2개가 차이가 있었다는 점이다.
위처럼 하니까 process.env.PRIVATE_KEY 를 사용하지 못하고
${process.env.PRIVATE_KEY} 이렇게 문자열로 바꿔줘야만 사용 가능했다.
구글링 해본 결과 문자열로 지정해서 하는건 임시적인 해결이라
권장하지는 않는다고 했다.
이렇게 에러를 직접 구글링 해보고 팀원과 얘기를 나눠보면서
해결방안을 찾아보니 괜히 뿌듯함을 느끼고 재미를 느꼈다.