비상 초비상
[로그아웃 기능 구현 빵꾸]
로그아웃 기능 구현을 그냥 아예 잘못했다. 잊고 있었다. 내가 구현한게 아니었던 건데, 내가 테스트를 안하고있었다.
생각을 해보니 로그아웃은 jwt에서 방법이 없다. 왜냐? 클라이언트에게 넘겨준 토큰은 서버의 손을 떠났기 때문에(무상태성) 컨트롤 할 수 없다. 클라이언트가 가지고 있는 토큰에는 jwt 사인이 된 토큰이 있다. 사인이 된 토큰을 서버에 가져온다면 인증은 오케이다. 언제까지? 만료기한이 지나기 전까지! 그렇다면 서버는 만료 기한을 짧게 줄 수 밖에.. 그렇다면 유저는 불편한 경험을 하겠지? 조금밖에 사용을 안했는데 벌써 나가라고 하는게 마치 내가 노래방 다닐적 경험같군.. 그렇다면 토큰을 계속해서 갱신하면 된다. 솔루션은 토큰의 만료기한을 줄이고, 계속 리프래쉬 토큰을 클라이언트에게 던져주는 것.
그렇다면 다시 원점으로 돌아가자. 로그아웃은 어떻게 구현해야 할까? 위에서 말했던 무상태성을 조금 깨야한다. 바로 Acess Token(인증 토큰)을 저장하는 DB를 하나 만드는 것. 그리고 로그아웃 요청이 클라이언트에서 온다면 그때의 Acess Token을 블랙리스트로 DB에 추가한다. 이후 재로그인이 되어 서버에서 클라이언트로 Acess Token을 재발급 하기 전까지 모든 Acess Token은 무시하는 것. (로그아웃 요청이 된 후 Refresh Token은 재발급 안한다. 로그아웃한 토큰의 만료기한이 끝나면 이제 모든 Acess Token은 만료기한이 끝난다.)
[트레이드 오프]
그렇다면 우리는 이 트레이드 오프가 어떨지를 따져보자. 리턴값이 크다면 조금 손해를 보는것도 나쁘지 않다. 무상태성을 조금 깨면 우리가 얻을 수 있는 이득은 다음과 같다.
1. 만료기한이 짧기 때문에 토큰이 갈취 당했을 때 해커에게 공격받는 시간을 줄일 수 있다.
2. jwt 토큰으로는 불가능한 로그인을 처리할 수 있다.
그렇다면 무상태성을 깨면서 가져가야할 불이익은 뭘까?
1. 서버에 토큰을 저장할 db가 필요해진다.
2. 이에 따라 서버에 부하가 추가된다.
이 불이익을 어떻게 처리해야 하냐? 바로 래디스 환경을 통해 로그인/로그아웃을 구현하는 것. 레디스 환경의 속성들은 이 불이익들을 가볍게 처리해준다. 레디스는 NoSql을 기반으로 한 DB이다. NoSql은 우리가 사용하는 RDBMS와 다른 특성을 가지고 있다. 그중 레디스는 메모리 기반으로 빠르게 데이터를 읽어올 수 있는 Key-Value Store메모리다. 빠르게 데이터를 읽어올 수 있으며, 메모리는 RDBMS가 아닌 새로운(가벼운) DB를 사용하기 때문에 위의 트레이드오프에서 얻는 불이익이 더 작아진다.
그렇다면 이제는 어떻게... 구현하느냐가 문제다... 이 이슈를 너무 늦게 알아차렸다. 오늘은 필터단에서 나오는 예외를 어떻게 처리하는지 공부를 하고 있었는데 내일 로그아웃 기능을 구현하면서 같이 처리를 하면 좋겠다.