최근 스터디에서 JWT를 주제로 발표할 기회가 있었다. 이번 기회에 제대로 설명하기 위해 준비했다가, JWT를 더 잘 이해하기 위해선 쿠키나 세션 방식을 알아야 이해가 더 쉬웠다. 그래서 순서대로 정리하며 JWT를 설명하려한다.
JWT란 인가(Authorization)에 필요한 정보들을 암호화시킨 JSON 형태의 토큰을 의미한다.
아 이러한 인증과 인가를 처리하기 위해 JWT를 쓰는구나 ~ 근데 JWT로 쓰면 끝인건가?
아쉽게도 아니다. 인증과 인가를 처리하는 JWT 토큰 이전의 방식이 쿠키, 세션 방식이다.
그렇다면, JWT라는 토큰방식이 나오기 이전의 방식들에 단점이나 문제가 있었나보다. 어떤건지 알아보자.
간단한 로직을 살펴보자.
내가 Kang이라는 user로 로그인 요청을 보내면 서버에서 확인 후 문제가 없을 시 필요한 정보를 쿠키에 담아 보내주게 된다. 이 데이터를 브라우저의 쿠키에 저장하게 된다.
나라는 사람임을 확인하는 상황이 있을 때면, 쿠키에서 조회한 값을 HTTP요청 할 때 쿠키에 담아 보낸다. 문제가 없다면 서버는 문제가 없다는 응답을 해주고 나는 다음 행동을 할 수 있게 된다.
이러한 쿠키의 단점을 보완하기 위해 세션 방식이 나오게 됐다.
쿠키와 비슷하지만 간단한 예시를 또 살펴보자.
- User Kang으로 로그인 요청을 보내면
- 서버는 확인 후 해당 유저에 맞는 SessionId를 생성한다.
- 그리고 SessionID를 쿠키에 전달하고,
- 나는 이 SessionId를 브라우저 쿠키에 저장한다.
- 또 나라는 사람이 확인되어야 하는 상황이라면, 쿠키에서 SessionID를 서버 요청시에 함께 전달한다.
- 서버는 해당 SessionID값을 조회하고
- 문제가 없다면 다음 행동을 진행하게 된다.
앞서 말했듯, 세션 방식은 쿠키만을 사용한 방식보다 안전하다.
하지만 당연하게도 완벽한 기술은 없다. 세션 방식은 다음과 같은 단점이 있다.
1. 메모리 사용에 대한 리스크
- 일단 메모리라는 곳은 에러가 나게 되면 다 날아가게 되는 큰 위험이 있다. 그렇기에 하드디스크나 데이터베이스에 담기도 하지만, 하드디스크나 데이터베이스는 메모리보다 느리다.
2. 다중 서버일 때 세션 구분
- 만약 서비스가 커서 서버가 여러대라면 ? 내가 로그인했을 때 내 SessionId가 A에 저장됐는데, 조회할 때는 B에서 조회하면 ? 당연하게도 문제가 된다. 이런걸 해결하기 위해 공용 메모리형 데이터베이스를 사용한다고 한다.
이렇게 세션 방식처럼 구현하려면 하겠지만 구현하기도 쉽지 않은 일. 좀 더 쉽게 할 수 없을까? 해서 나온게 토큰 방식이다.
토큰방식은 세션 방식처럼 서버에 SessionId를 저장하지 않으면서도 토큰이라는 것을 통해 나를 인증/인가 해주는 방식이다.
토큰 방식은 크게 세 가지의 특징이 있다.
1. 상태유지를 하지 않는다. - 상태 유지를 하지 않는데 어떻게 상태를 알고 있냐 ? 토큰에 필요한 정보들이 들어있기에 된다.
2. 확장성 있다. - 세션처럼 따로 저장하는 게 없으니, 확장에 유리하다.
3. 확장성 있다22 - 네이버로 로그인, 카카오톡으로 로그인 같은 것들도 모두 토큰을 활용한 기능이고, 이때 선택적인 권한을 부여해서 발급하는 것, 로그인의 기능이 확장된다고 볼 수 있다.
JWT는 이러한 토큰 방식중의 하나이다.
앞에서 본 JWT를 다시 보자. JWT란, 로그인 이후에 발생하는 '인가'에 필요한 정보들을 암호화시킨 JSON형태의 토큰이다.
Claim
이라고 한다.아주 간단하게 보자면, JWT는 위와 같은 방식이다. 크게 보자면 쿠키 방식과 크게 다를 게 없어 보인다.
유효기간이 짧은 토큰을 Access Token
, 조금 긴 토큰을 Refresh Token
이라고 부르며, 보통 긴 토큰은 유효기간을 2주 정도로 준다.
구현 방법은 다양한데,
- 리프레시토큰 상응값을 데이터베이스에 저장.
- 로그인 한 유저는 엑세스토큰 수명 다하면 리프레시 토큰을 보낸다. →
- 서버는 데이터베이스에 저장된 값과 대조, 맞으면 새 엑세스 토큰 발급해줌
이렇게 리프레시 토큰만 안전하게 관리되면 이게 유효 할 동안은 엑세스토큰이 만료될때마다 다시 로그인 할 필요없이 새로 발급 가능하다.
근데 리프레시 토큰을 데이터베이스에 저장하면 세션 방식과 뭐가 다른가?
세션은 사용자가 로그인 한 경우, 사용자 정보가 서버 메모리에 계속 상주해 있어 매번 crud 할때마다 서버 메모리에 접근해서 인증을 하지만,
토큰은 서버 메모리에 저장 없이 넘어오는 토큰으로 인증만 진행 하기 때문에 가볍다. 그리고 refresh token은 access token 기간이 다 지났을 때만 갱신, 조회 하므로 db에도 큰 무리가 없다.
조사하다보니 JWT 암호화 방식도 찾아보게 되고, 곁가지로 알아보게 되는 개념들이 많아졌다.
추가적으로, 이러한 정보를 저장하는 쿠키나 웹 스토리지의 내용도 필요함을 느꼈다.
틀린 부분을 보신다면 꼭 알려주시면 감사하겠습니다