물론 프로젝트에 적용하고 있진 않지만, 예전에 했던 고민인데 완벽한 해결 방법도 모르고 급한대로 마무리했던게 아쉬워서 가져와봄
다들 어떤 생각을 가지고 있는지 서로 이야기 해보면 어떨까 싶어서 똥글 싸봄
------------------------------------------------------------------------------------------------------------------
JWT를 사용하는 서버에서 Stateless하게 유지해야하다보니, 서버 자체 세션은 시큐리티를 사용하여 끈 상태임. 근데 알다시피 JWT는 보안 상 문제가 많다고 생각했음
그래서 가장 흔한 방법인 블랙리스트 토큰을 우리 쪽에서 관리하면 어떨까 생각해봤음.
1. 가장 먼저 생각했던 방식은 회원이 만약 요청하거나 로그아웃을 하게 되면, JWT 토큰을 우리 쪽 DB에서 관리해보자 였음.
문제 :
- 이런 방식은 JWT 특성 상 클라이언트가 가지고 있는 토큰을 DB에 접근해서 이상이 없는지 확인해야 하다보니 DB 요청 수가 너무 많이 증가함.
- Access 토큰과 Refresh 토큰을 둘 다 관리해야되며, 만료될 때마다 데이터를 주기적으로 지워줘야함. 근데 토큰마다 만료가 다르니 계속 확인하거나, 특정 시점으로 지난건 확인해서 지워야하지만 이것 또한 DB 자원을 불필요하게 사용하는 것 같았음.
2. 그래서 이후에 Redis를 추가를 해봄
블랙리스트 토큰에서만의 관계를 따졌을 때의 그림임. 이렇게 데이터를 가지고 있으니 엄청 많은 데이터를 확인했던건 아니지만, 기존 DB에 접근하는 횟수가 현저히 낮아짐. 하지만 피드백에서 다음과 같은 문제에 대한 답변이 어려웠음
문제 :
- 별 생각없이 개별적으로 TTL 설정을 했는데 앞서 이야기한 것처럼 각각의 토큰은 유효시간이 다 다름. 이걸 그때 그때마다 지우는 건 좋은 방향이 아님.
- 레디스는 알다시피 메모리기반 데이터로 데이터가 휘발성임. 레디스가 재시작 됐을 경우 블랙리스트로 등록되어있던 데이터가 사라져 로그인이 가능해질 수 있음.
- 레디스도 결국 서버와 통신하고 있는 하나의 인프라이므로 예상치 못한 장애가 발생했을 때의 대처 방법이 필요함.
-------------------------------------------------------------------------------------
아쉽게도 해당 문제는 실질적으로 해결하진 못했지만 TTL 관련은 배치를 사용하고, 두 번째는 백업, 세 번째는 레디스 클러스터링? 을 이용하면 된다는 정도만 이해했었음.
다들 동일한 이유는 아니더라도 비슷한 이유로 레디스를 많이 사용했을텐데 솔직히 내가 적절히 쓴지도 모르겠음. 그냥 이런게 있으면 좋을거 같다는 생각으로 만든거라서.. 어떤 문제가 있었고 어떻게 해결했는지 궁금하고 듣고 싶음.
진짜 문제는 외면하고 이상한 부분으로 파고들고 있네 db에서 읽던걸 redis로 읽는게 대체 뭔 해결책임?
진짜 문제를 알려주세욧!
진짜 문제는 stateless를 stateful로 바꿔버렸다는거지 redis라고 부하를 무한히 처리할 수 있는게 아님 그럼에도 불구하고 session이 아닌 jwt를 써야하는 이유가 뭔지를 고민해봐야하는거 아냐?
블랙리스트란 데이터의 성질도 고민해봐
애초에 jwt, 세션 같은 기술은 써야하는 이유가 중요한데, 그런건 고민해보지 않고 무작정 써버리니까 후속 고민도 이상한 방향으로 이어지는거임
해당 프로젝트가 꽤 오래 전 국비 팀 프로젝트였고 특별한 이유 없이 취업을 목적으로 이것저것 해보자는 취지에서 팀원이 도입하자고 했었어요ㅋㅋ 결국 문제는 많이 발생했지만, 장점은 찾기 어려웠어서 써야 했던 이유가 아닌 변명을 찾았던 걸로 기억합니다 ㅠ 그부분은 반성하고 있어요 ㅠㅠ
나도 질문 하나만 해도 될까 대기형 어떤 부분이 stateless가 stateful이 된 거야? 블랙리스트 등록자체는 사용자가 지금 어떤 상태인지는 모르고 토큰을 건네면 그걸 검증하는 느낌이라고 생각했는데 이 부분이 stateful한 건가? 아니면 다른 부분이야?
블랙리스트가 stateful임
저도 도움되긴 하는데 다른 분들한테도 도움되는거 같아서 욕먹더라도 똥글 2탄으로 돌아올게요
stateful의 수준을 나눠서 보자면 낮은 수준의 stateful이긴 하지, 근데 0과 1은 아예 다른거야
stateless는 서버가 사용자 상태를 유지하지 않는 것으로 알고 있는데, 블랙리스트가 "사용자 상태를 유지"하는 행위가 되어 stateful 이 된다는 의미로 말씀하신 것 같습니다! 해당 레디스를 사용한 블랙리스트 구현에서 빠지지 않고 나오는 얘기라 검색하셔도 재밌는 글 많습니당!
아하 이해했어 고마워
나도 잘 모르지만 글을 읽다보니 궁금한 점이 생겨서 남김 1. Jwt 토큰으로 만료시간을 확인 할 수 있는데 왜 db에서 만료시간까지 관리하는 거야? 불필요한 데이터를 주기적으로 삭제하기 위함인거야? 2. Access token의 시간을 짧게 가져가고 refresh token으로 계속 재발행한다면 블랙리스트는 refresh token만 관리해도 충분하지 않아?
1. JWT토큰에서 만료시간이 존재하지만 회원이 로그아웃할 때 토큰만 삭제한다면 해당 토큰을 가지고 있는 사용자는 이를 사용하여 로그인할 수 있다고 생각했어요. 블랙리스트 토큰을 관리하다보면 계속 쌓이기만할거라구 생각해서 토큰의 만료시간이 지나면 삭제하려고 했었습니당 2. 해당 방식도 생각은 했었어요! 실제로 설명에 빠뜨리긴했는데 액세스를 둘다 관리하다가 레디스에서 엑세스를 짧게 가져가고 리프레시만 관리하도록 변경했었습니다!
요즘 왜케 시큐리티+jwt의 이해는 동떨어지고 무조건 쓰는것에 초점을 둔거지 - dc App
그리고 jwt가 왜 보안성으로 안좋다는거임? https에서 토큰탈취때문이라고 생각하는거? - dc App
위 답글처럼 그 당시 기술스택충이였어서 무지성 스택은 반성하고 있어요 ㅠㅠ 솔직히 특별해 보여서 써봤었습니다 ㅋㅋ 보안성으로 안좋다고 생각했던 점은 탈취만 된다면 사용자를 검증할 수 없다고 생각했었습니다 세션과 다르게 탈취 당했을 때를 고려하여 중요한 정보를 넣을 수 없으니 오히려 인가가 간단한 데이터로만 이뤄지다보니 이렇게 생각했던거 같아요! 제가 워낙 부족해서 틀릴 수 있는데 틀린부분 있다면 지적 해주세요!
밑에 질문이 궁금해서 그런데.. redis가 ttl에서 쓰기 꺼려지는게 그 내용이 미친듯이 늘어나면 해당 블랙리스트의 삭제관련으로 부담되서 다른 방법을 고려해보라고 한것같은데 싸피임? - dc App
아뇨 그냥 쭈구리 국비예요
근본 문제를 해결하고 싶은건가 아니면 지금 상태가 이러한데 레디스를 사용하기로 했고, 레디스를 쓰나마냐는 별로 알고싶지 않고, 나는 이런 상황에서 레디스 운영법을 알고싶은거다 라고 확실히 질문해야 원하는 답변을 얻지~ 제목은 레디스 사용관련 질문이라는데
제가 핀트를 잘못잡은거 같아요 말씀하셨던 후자를 생각하고 질문을 올렸었던건 맞습니다 ㅠ
후자로 질문한건 알아, 전자가 맛집이라 어그로가 끌린 것 뿐임 근데 레디스 클러스터링이랑 백업은 맞는데 TTL은 왜 좋은 방향이 아니라고 생각한거임?
하단의 문제점은 피드백을 해주셨던 분의 내용이었습니당 ㅠ 저희는 TTL로 설정하면 간단하다고 생각했지만 이 부분에 대해서 위와 같이 좋은 방향은 아니라고 하셨어요 데이터 특성 상 그럴 리 없지만 블랙 리스트가 많이 쌓이게 된다면 TTL을 관리하는 것조차 부담이 될 수 있다는 이유였고, 다른 해결 방법도 고민해보라고 하셨었어요
그쯤 되면 배치를 위한 스캔 비용도 문제가 되지 않을까? 피드백 이상하게 준거같은데
형님이 말씀해준 덕분에 피드백 방향이 잘 못 됐다곤 하지만 질문하지 못했다는 점에서 레디스에 대해 잘 모르고 있었다는 걸 다시 한번 느꼈습니다ㅋㅋ 공부할게 늘었네요
레디스 설정값을 만져서 어느정도 최적화할수는 있겠지만, 니가 배치를 돌리건 redis가 알아서 주기적으로 삭제하건, 결과적으로 redis 부하는 증가함 외부 기능인 배치는 최적화가 불가능하니 오히려 문제가 더 커지겠지 내가 봤을때 저건 해결해야하는 문제가 아니고 분산 redis를 쓰던 해야하는 문제임 aws 프리티어로 10만tps 처리해내라는거랑 뭐가 달
ttl 성능 이슈가 없다는 소린 아닌데, 적어도 블랙리스트 데이터 패턴에서 발생할 문제는 아님