오늘은 팀프로젝트 구현 첫 날이였는데 나는 회원가입, 로그인, 로그아웃 부분을 맡았다.
처음엔 세션으로 구현하다가 JWT로 바꾸게 됐는데 진짜 캠프 시작 이래로 이렇게 머리가 빠개질 뻔한 건 처음이였다.
세션을 어려워 했던 나에게 인증, 인가 부분이 쉬운 내용도 아닌데다가 배우지도 않은 내용을 몇 시간만에 개념도 안 잡힌채로 구현 하려니까 진짜 곤욕이였다.
그래도 부딪히면서 해보니까 배우는 게 많은 거 같아서 좋다.
아직 JPA 연관관계 부분이나 JPQL, 페이징 부분, 비즈니스 로직 구현도 많이 부족한데 빨리 로그인 구현 끝내고 얘네도 같이 공부 해야할 것 같다.
오늘 하루종일 진짜 몸통박치기로만 구현을 해서 개념을 좀 정리 해보려고 한다.
간단하게 JWT가 뭔지 부터 알아보자.
JWT(JSON Web Token)는 JSON 객체를 사용해서 두 당사자 간에 정보를 안전하고 간결하게 전송하기 위한 개방형 표준(RFC 7519)이다.
JWT는 디지털 서명을 통해 토큰의 무결성과 신뢰성을 보장한다.
JWT는 점(.)으로 구분된 세 마디로 구성되어 있다.
{
"alg": "HS256",
"typ": "JWT"
}
토큰의 유형(보통은 JWT)과 서명에 사용된 알고리즘 정보를 담고 있다.
이 JSON 객체는 Base64Url로 인코딩 되어 JWT의 첫 번째 부분을 형성한다.
{
"sub": "user1",
"name": "Jane Doe",
"admin": true
}
사용자 정보나 토큰의 만료 시간 등 실제 전송하려는 데이터를 포함한다.
페이로드에는 클레임(Claims)이 포함되며, 이는 사용자 또는 엔티티에 대한 정보이다.
이 JSON 객체 역시 Base64Url로 인코딩 되어 JWT의 두 번째 부분을 형성한다.
✅ 클레임의 종류
등록된 클레임 (Registered Claims)
iss (발급자), exp (만료 시간), sub (주제)공개 클레임 (Public Claims)
비공개 클레임 (Private Claims)
userId, rolesHMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
헤더와 페이로드를 결합하고, 비밀 키를 사용하여 생성된 서명이다.
서명은 토큰이 변조되지 않았음을 확인하는데 사용한다.
xxxxx.yyyyy.xxxxx
✅ 실제 예시
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT는 클라이언트와 서버 간에 신뢰할 수 있는 정보 전달을 위해 사용한다고 했다.
하지만 JWT는 암호화 되지 않고, 그렇기에 누구나 페이로드의 내용을 볼 수 있다.
그럼 JWT는 어떻게 토큰의 무결성과 신뢰성을 보장할까? 바로 서명(Signature) 덕분이다!
JWT 서명 방식은 대표적으로 HS256(대칭)과 RS256(비대칭)이 있다.
나는 대칭을 사용했으므로 대칭에 대해서만 더 자세히 알아본다.
대칭 서명 방식은 오직 하나의 비밀 키(Secret Key)를 사용하여 서명을 생성하고 검증한다.
핵심은 서버만이 비밀 키를 알고 있다는 것이다.
클라이언트는 비밀 키를 알지 못하고, 토큰의 서명만을 가진다.
1️⃣ 서명 생성 (토큰 발행 시)
2️⃣ 서명 검증 (토큰 검증 시)
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "user1",
"role": "admin"
}
비밀 키: mysecretkey123456789
서명 생성
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
"mysecretkey123456789"
)
header.payload.signature
mysecretkey123456789로 서명을 재생성한다.대칭 서명 방식은 비밀 키 하나만으로 서명 생성과 검증이 가능해 간단하고 연산이 빠르지만, 비밀 키가 노출되면 보안에 큰 위협이 되고 여러 서버나 서비스 간에 비밀 키를 공유해야 하는 경우 보안 위험이 증가한다.
그렇기에 비밀 키는 서버 내 안전한 공간에만 저장하고, 비밀 키에 접근할 수 있는 권한은 최소 인원에게만 부여해야 하며, 주기적으로 변경해야한다.