티스토리 뷰
반응형
✅ 프론트엔드에서 JWT 토큰을 안전하게 관리하는 방법
JWT(JSON Web Token)는 토큰 기반 인증 방식으로, 주로 API와 클라이언트 간의 인증에 사용됩니다.
프론트엔드에서 JWT를 안전하게 관리하지 않으면 토큰 탈취, 세션 하이재킹 등 보안 문제가 발생할 수 있습니다.
이번 글에서는 JWT 구조와 위험성, 안전한 저장과 전송 방법, 실무 적용 사례를 중심으로 정리합니다.
📌 1. JWT의 구조와 특징
✅ JWT의 구조
JWT는 세 부분으로 구성됩니다:
- 헤더(Header): 토큰 타입과 암호화 알고리즘 정보
- 페이로드(Payload): 사용자 정보(클레임) 및 데이터
- 서명(Signature): 비밀 키를 이용해 서명한 부분
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.PpYoWyxDr8ij5qZ-6IlcGe9xOF3KbR2H9_K2mZ8yLJk
✅ JWT의 특징
- Stateless: 세션 저장소 없이 서버에 부담을 주지 않음
- Self-contained: 모든 정보가 토큰 안에 있어 DB 조회 불필요
- 만료 시간 설정: exp 클레임을 통해 토큰 만료 설정 가능
📌 2. JWT의 위험성
🔥 1) 토큰 탈취
- 토큰이 브라우저에 평문으로 저장될 경우 탈취 위험
🔥 2) CSRF(Cross-Site Request Forgery) 공격
- JWT를 쿠키에 저장하면 CSRF에 취약
🔥 3) 토큰 위변조
- 서명 검증이 제대로 이루어지지 않으면 무단 접근 가능
📌 3. JWT 토큰 안전 관리 방법
🔹 1) 안전한 저장 위치 선택
저장소 장점 단점 사용 권장
LocalStorage | 쉽고 직관적 | XSS 공격에 취약 | 비권장 |
SessionStorage | 페이지를 닫으면 삭제 | XSS 공격에 취약 | 비권장 |
HTTP-Only 쿠키 | XSS 방어 가능 | CSRF에 취약 | 권장 |
✅ 토큰을 쿠키로 저장 (HTTP-Only 설정)
// 서버 응답 시
res.cookie('access_token', token, {
httpOnly: true,
secure: true, // HTTPS에서만 전송
sameSite: 'Strict', // CSRF 방어
});
🔹 2) 토큰 저장 시 주의사항
반응형
- LocalStorage 사용 금지: XSS 공격에 취약
- HTTP-Only 쿠키 사용: JS로 접근 불가
- SameSite 속성 설정: CSRF 방어
✅ Next.js API Route 예시
export default function handler(req, res) {
const token = generateToken({ username: 'admin' });
res.setHeader('Set-Cookie', `jwt=${token}; HttpOnly; Secure; SameSite=Strict`);
res.status(200).json({ message: '로그인 성공' });
}
🔹 3) JWT를 안전하게 전송하기
- HTTPS 사용: 토큰 전송 시 암호화 보장
- CORS 정책 강화: 허용 도메인에서만 API 호출 가능
- 토큰을 헤더로 전송: Authorization: Bearer <token>
✅ Axios를 이용한 안전한 요청
axios.get('/api/user', {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
🔹 4) 토큰 갱신 전략 (Refresh Token)
- Access Token은 짧게, Refresh Token은 길게 설정
- Refresh Token은 HttpOnly 쿠키에 저장
- 만료 시 Access Token 재발급 API 호출
✅ Refresh Token 사용 예시
// Refresh 토큰으로 Access 토큰 재발급
async function getNewAccessToken() {
const response = await axios.post('/api/refresh');
localStorage.setItem('access_token', response.data.accessToken);
}
🔹 5) 토큰 검증 및 로그아웃 처리
✅ 서버에서 서명 검증
const verifyToken = (token) => {
try {
return jwt.verify(token, process.env.JWT_SECRET);
} catch (err) {
return null;
}
};
✅ 만료된 토큰 처리
- 401 Unauthorized 응답 시 로그아웃 처리
- 클라이언트에서 토큰 갱신 시도
📌 4. 실무에서 겪은 문제와 해결
🧪 문제
- 사용자가 로그아웃 후에도 토큰이 남아있어 자동 로그인 유지 문제가 발생
✅ 해결
- 쿠키를 사용하지 않고 LocalStorage에 토큰을 저장한 것이 문제
- HTTP-Only 쿠키로 변경하여 토큰을 서버에서 직접 삭제
✅ 로그아웃 API 수정
export default function handler(req, res) {
res.setHeader('Set-Cookie', 'jwt=; HttpOnly; Secure; SameSite=Strict; Max-Age=0');
res.status(200).json({ message: '로그아웃 성공' });
}
📌 5. JWT 사용 시 베스트 프랙티스
- 쿠키 사용 권장: XSS로부터 보호
- HTTPS 필수: 네트워크 전송 중 암호화
- 토큰 유효 기간 설정: 짧게 설정하여 위험성 감소
- 토큰 탈취 방지: IP 또는 User-Agent 검증
- 로그아웃 시 쿠키 삭제: 잔여 토큰 제거 필수
📌 면접에서 이렇게 답하세요
JWT는 서버 상태를 저장하지 않는 인증 방식으로,
세션 관리 없이 클라이언트가 토큰을 가지고 인증하는 방식입니다.
프론트엔드에서 JWT를 관리할 때는 HTTP-Only 쿠키를 사용하여 XSS 공격을 방어하고,
SameSite 설정으로 CSRF를 예방합니다.
실무에서는 Refresh Token을 이용해 만료 시 자동 갱신하며,
보안을 위해 HTTPS와 토큰 검증 로직을 함께 사용합니다.
JWT,프론트엔드보안,토큰관리,HTTP-Only쿠키,JWT보안,토큰갱신,RefreshToken,토큰저장,API보안,프론트엔드면접
'AI + Career' 카테고리의 다른 글
✅ RESTful API의 정의와 좋은 REST API 설계 원칙 (0) | 2025.05.20 |
---|---|
✅ XSS(Cross Site Scripting)와 CSRF(Cross Site Request Forgery)의 개념과 방지 방법 (0) | 2025.05.14 |
✅ 프론트엔드 코드의 유지보수성과 확장성을 높이기 위한 설계 패턴 (0) | 2025.05.13 |
✅ E2E(End-to-End) 테스트의 필요성과 사용하는 도구 (0) | 2025.05.12 |
✅ Jest와 React Testing Library를 이용한 테스트 방법론 (0) | 2025.05.09 |
※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- fastapi
- Docker
- AI챗봇
- REACT
- Python
- PostgreSQL
- LangChain
- rag
- nextJS
- 파이썬 알고리즘
- Webpack
- nodejs
- 프론트엔드면접
- kotlin
- github
- 웹개발
- seo 최적화 10개
- 백엔드개발
- Ktor
- Prisma
- 관리자
- NestJS
- SEO최적화
- App Router
- 개발블로그
- llm
- Next.js
- gatsbyjs
- CI/CD
- 프론트엔드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함
반응형