웹 개발을 하다 보면 로그인, 인증, 사용자 정보 보호와 관련된 문제를 반드시 마주하게 된다. 기존에는 쿠키와 세션으로 상태를 관리했지만, 특히 SPA(Single Page Application)나 API 기반 서비스에서는 서버에 상태를 저장하지 않고도 안전하게 인증과 정보 교환을 처리할 필요가 있다.
바로 이때 등장하는 것이 JWT(Json Web Token)다.
JWT를 이해하면 다음과 같은 장점을 활용할 수 있다:
- 서버에 상태를 저장하지 않고도 사용자를 인증할 수 있다.
- 클라이언트와 서버 간 정보를 안전하게 전달할 수 있다.
- SPA나 모바일 앱 등 비동기 통신 환경에서 편리하게 사용 가능하다.
즉, 현대 웹과 앱 개발에서 JWT는 필수 기술이다.
1. JWT의 구조
JWT는 헤더(Header), 페이로드(Payload), 서명(Signature) 3부분으로 이루어져 있으며, 점(.)으로 구분된다.
xxxxx.yyyyy.zzzzz
1. 헤더(Header)
헤더에는 JWT의 타입과 해싱 알고리즘 정보가 담긴다.
{
"alg": "HS256", // 토큰 서명에 사용된 알고리즘(HMAC SHA256, RSA 등)
"typ": "JWT" // 토큰 유형(JWT)
}
이 JSON 객체는 Base64Url로 인코딩되어 JWT의 첫 번째 부분을 구성한다.
2. 페이로드(Payload)
페이로드에는 클레임(Claims)이라는 데이터가 포함된다. 클레임은 JWT가 전달하는 정보 조각이며, 세 가지 유형이 있다:
- 등록된 클레임(Registered Claims): 사전에 정의된 필드 (예: iss 발행자, exp 만료시간, sub 주제, aud 대상자)
- 공개 클레임(Public Claims): URI 또는 JWT 레지스트리에서 정의되어 충돌 방지
- 비공개 클레임(Private Claims): 서버와 클라이언트가 합의한 정보, 예를 들어 userId나 권한 정보
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
페이로드도 Base64Url로 인코딩되어 JWT의 두 번째 부분을 구성한다.
3. 서명(Signature)
서명은 JWT의 무결성과 신뢰성을 보장한다. 인코딩된 헤더와 페이로드, 그리고 비밀 키를 조합해 생성한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
최종 JWT 형태는 다음과 같다:
xxxxx.yyyyy.zzzzz
2. JWT의 사용 사례
1. 인증(Authentication)
JWT는 주로 인증에 사용된다.
- 사용자가 로그인하면 서버는 JWT를 생성하여 클라이언트에게 반환한다.
- 클라이언트는 이후 요청 시 JWT를 HTTP 헤더에 포함시켜 서버에 보낸다.
- 서버는 토큰을 검증하고 요청을 처리한다.
Authorization: Bearer xxxxx.yyyyy.zzzzz
Node.js + Express 예시
const jwt = require('jsonwebtoken');
// 로그인 시 JWT 발급
app.post('/login', (req, res) => {
const user = { id: 1, username: 'john' };
const token = jwt.sign(user, 'secretKey', { expiresIn: '1h' });
res.json({ token });
});
// JWT 검증 미들웨어
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, 'secretKey', (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
// 보호된 라우트
app.get('/profile', authenticateToken, (req, res) => {
res.json({ message: 'Profile data', user: req.user });
});
2. 정보 교환(Information Exchange)
JWT는 서명(Signature) 덕분에 데이터를 안전하게 전달할 수 있다. 발신자가 주장하는 대로 정보가 변조되지 않았음을 보장하며, 서버 간 또는 클라이언트-서버 간 안전한 데이터 교환에 적합하다.
3. JWT의 장단점
장점
- 컴팩트함: URL, POST 파라미터, HTTP 헤더 등 어디든 쉽게 포함이 가능하다.
- 자체 포함(self-contained): 필요한 정보를 토큰 안에 담아 DB 조회를 최소화한다.
- 안전성: 디지털 서명으로 무결성이 보장된다.
단점
- 만료 이전 무효화 어려움: 서버에 저장되지 않기 때문에 한 번 발급된 토큰은 만료 전까지 취소가 어렵다. 블랙리스트 또는 짧은 만료 시간을 활용해야 한다.
- 페이로드 크기: 데이터가 많으면 토큰이 커지고 네트워크 부담이 증가한다.
4. JWT 저장 위치와 선택 기준
JWT 토큰은 보안과 편의성을 고려해 저장해야 한다.
| 저장 방식 | 장점 | 단점 | 사용 예 |
| 로컬 스토리지 | 브라우저 종료 후에도 유지, 용량 5MB | XSS 공격 취약 | 자주 로그아웃하지 않는 SPA |
| 세션 스토리지 | 탭 종료 시 삭제, 상대적 안전 | 브라우저 종료 시 삭제 | 탭 단위 로그인 상태 관리 |
| 쿠키(HttpOnly + Secure) | JS 접근 차단, HTTPS 전송, 요청 시 자동 전송 | 용량 4KB 제한, CSRF 공격 가능 | 보안 중요한 서비스 |
정리하면 아래와 같다.
- 보안 중심인 경우, 쿠키(HttpOnly, Secure) + CSRF 토큰
- 편의성 중심이라면, 로컬 스토리지 + XSS 대비책
- 세션 기반 인증이면, 세션 스토리지 사용
CSRF·XSS 방어하는 방법
- CSRF: 서버에서 CSRF 토큰 발급, 요청 시 전송하여 이를 서버에서 매번 확인, 쿠키에 SameSite 속성 설정
- XSS: 입력 값 유효성 검증, 특수문자 제거, CSP(Content-Security-Policy) 설정, HTTPS 사용
5. 마무리
JWT는 서버 상태를 최소화하면서도 안전하게 인증과 정보 교환을 가능하게 하는 현대적인 기술이다. 특히 SPA, 모바일 앱, API 서버 환경에서는 기존의 쿠키와 세션만으로는 처리하기 어려운 인증 요구 사항을 효율적으로 지원한다. 하지만 JWT가 쿠키나 세션을 완전히 대체하는 것은 아니며, 상황에 따라 기존 인증 방식과 함께 사용될 수 있다.
즉, JWT는 클라이언트 중심 환경에서 서버 부담을 줄이면서도 보안과 편의성을 동시에 확보할 수 있는 핵심 도구이다. 적절한 저장 위치 선택과 보안 설정을 통해 XSS, CSRF 공격에 대비할 수 있으며, 토큰 기반 인증 시스템을 구현하면 사용자 경험을 높이는 동시에 서버 측 리소스를 효율적으로 관리할 수 있다.
결국, JWT를 이해하고 활용하는 것은 현대 웹과 앱 개발에서 필수적인 역량이며, SPA, 모바일, API 등 다양한 환경에서 인증과 정보 교환의 기준을 새롭게 정의한다는 점에서 그 중요성이 더욱 커지고 있다.
'Computer Science > Web Development' 카테고리의 다른 글
| 웹 서버(Nginx, Apache..) 의 역할 (0) | 2025.10.18 |
|---|---|
| CORS Error 는 왜 자주 발생할까? — 교차 출처 리소스 공유 (0) | 2025.10.18 |
| SPA, CSR, SSR, 그리고 Hybrid Rendering — 웹 렌더링의 진화 (0) | 2025.10.17 |
| z-index가 같아도 겹치는 순서가 달라지는 이유 (0) | 2025.10.16 |
| Document Object Model(DOM) (0) | 2025.10.16 |