안녕하세요🙌! 개발자 갈레입니다!
이번 글에서는 사용자의 UX를 고려한 로그인(세션, 쿠키) 보안 전략 수립에 대해 다뤄볼겁니다!
들어가며
컨텐츠만 보면 막 궁금증이 있는 분들이 있으실거에요!
보통 기술 구현에만 집중하다 보면 잊을 수 있는 중요한 질문들입니다:)
Q. 로그인에 사용자 UX를 고려할게 있나?
Q. 로그인 보안 전략이랄게 있나?
실제로 로그인을 구현하다보면 사용자 UX를 고려한 여러 보안 전략🔒을 세울일이 많답니다!
사용자 UX를 고려하지 않으면, 사용자가 자주 로그인😡해야할 수도 있습니다. (사용자는 친절하지 않습니다:)😬)
그렇다고 사용자 UX만을 고려하자니 사용자의 의 정보 탈취 가능성이 높아집니다!
편의와 보안은 Trade off인 경우가 많습니다.
글을 읽으면서 여러분들이 스스로의 프로젝트에 맞는 적절한 사용자 편의와 로그인 정보 보안을 선택할 수 있는 시야 혹은 사고 과정 틀을 얻을 수 있으면 합니다. 이를 얻으면 여러분의 프로젝트가 제것과 다를지 몰라도, 기술 선택 시 사고 과정은 큰 틀을 벗어나지 않기 때문에 분명 도움이 될거라 생각합니다. 그럼 시작해볼까요!
궁금증(호기심)을 가지면 좋은 컨텐츠
- 로그인은 어떤 방식으로 할까?
- 쿠키, 세션은 뭘까? 왜 사용할까? 장단점은?
- 세션의 단점을 보완하는 전략은?
글을 읽으시면서 핵심 부분(노란)과 꼬리질문(초록) 부분에 집중하며 읽어주세요! 개인적으로 키워드에서 꼬리질문을 하는게 개념을 깊이있게 이해하는 과정이라고 생각합니다:)
목차
1. 문제 상황 분석
- 로그인
2. 선택 가능한 기술 분석
- 쿠키
- 세션
- 세션 로그인 보완 방식과 한계점
1. 문제 상황 분석
로그인
사용자 로그인 요구 사항이 내려왔습니다! 어떤 요구사항인지 확인해볼까요!
요구 사항
- 사용자는 아이디와 비밀번호로 로그인한다.
- 사용자가 로그인한 이후엔 로그인 유지되도록 한다.
- 로그인은 일정 시간 동안 유지할 수 있다.
- 로그아웃을 하면 사용자는 재로그인 해야 한다.
요구 사항을 분석해보도록하죠!
요구 사항 분석
- 사용자는 아이디와 비밀번호로 로그인한다.
- 로그인에 필요한 데이터 : 아이디, 비밀번호
- 서버 작동 방식
- 아이디, 비밀번호를 받기
- DB 내 사용자 데이터를 확인
- 로그인 완료 or 실패 응답
- 사용자가 로그인한 이후엔 로그인이 유지되도록 한다.
- 로그인 유지에 필요한 데이터 : 데이터A
- 서버 작동 방식
- 로그인 유지에 필요한 데이터를 받기
- 서버에서 데이터가 유효한 요청인지 확인
- OK 응답
- 로그인은 일정 시간 동안 유지할 수 있다.
- 로그인 유지에 필요한 데이터 : 데이터A + 만료 기한
- 서버 작동 방식
- 로그인 유지에 필요한 데이터 받기
- 서버에서 데이터가 만료 기한이 다됐는지 확인
- OK or 재로그인 응답
- 로그아웃을 하면 사용자는 재로그인 해야 한다.
- 로그아웃에 필요한 데이터 : 데이터A
- 서버 작동 방식
- 로그 아웃 요청 들어옴
- 로그 아웃 요청에 맞는 처리
- OK 응답
필요 데이터
- 사용자 로그인이 됐다는 것을 인증할 수 있는 (데이터A + 만료기한) 정보
필요 기능
- 로그인 기능
- 로그인 유지 로직
- 로그아웃 기능
요구사항을 분석해보니 저희가 현재 필요한 데이터는 사용자 로그인이 됐다는 것을 인증할 수 있는 (데이터A + 만료기한) 정보군요! 사용자가 로그인 됐다는 것을 알려주는 주체는 서버입니다! 따라서 데이터A는 서버가 인증한 데이터야합니다. 해당 데이터를 클라이언트가 가지고 있는 채로 서버 접근 시 전달하는 방식이겠군요! <그림1>은 이를 표현한 대표적인 예시입니다. access_token은 추후에 다룰테니 잊어주세요! (데이터A + 만료기한)이라고 생각해도 무방합니다! 이를 어떻게 구현할까 고민해보면 쿠키, 세션 등을 쉽게 떠올릴 수 있을겁니다.
2. 선택 가능한 기술 분석
로그인 구현 시 선택 가능한 기술을 분석해보죠! 문제 상황 분석에서 얻은 low level 데이터를 가지고 선택할 기술을 찾아내는 Bottom up 방식 혹은 유명한 기술에서 시작해서 저희가 얻은 low level 데이터가 적용되는지 살펴보는 top down 방식이 있습니다. 로그인과 같은 잘 알려진 구현 구조는 이미 알려진 좋은 기술들이 많으니 Top down으로 접근하는게 좋습니다! 조금만 검색해도 로그인 구현 방식에는 쿠키, 세션, jwt token이 있군요! 각각 기술들의 특징과 장단점을 분석해보도록하죠!
쿠키
쿠키를 사용하여 로그인하는 방식입니다. <그림2>에서 보시다 싶이 클라이언트에서 아이디와 비밀번호를 서버에 전송하면(그림2는 아이디만 전송하지만, 비밀번호도 같이 전송한다 생각해주세요), 서버가 해당 유저를 식별하는 데이터를 클라이언트에게 보냅니다. 클라이언트는 이를 저장하고 있다가 로그인 유지 기능에 활용하는거죠
쿠키를 이용한 로그인 방식은 구현 로직이 간단합니다. 서버는 유저 정보가 담긴 쿠키를 발행만 하면 됩니다. 서버 내에 저장되는 메모리도 없기 때문에 서버에게 부담도 없습니다. 하지만 악의적인 사용자가 악용할 수 있는 가능성이 매우 높습니다. 적절한 서버 인증과 보안 로직이 없기 때문이죠. 이러한 로직이 추가되면 jwt 토큰이 됩니다! 아직은 어려운 개념이니 '그렇구나~' 정도로 넘어가주시면 됩니다. 장단점을 정리 해보도록하죠!
장점
- 구현 로직이 간단함.
- 서버에 지속적으로 저장되는 메모리가 없음.(스케일 아웃 쉬움)
단점
- 악용될 가능성이 높음.
세션
세션을 사용한 로그인 방식입니다. 세션이란 서버에 저장되는 유저 상태 데이터입니다. 즉 로그인 상태를 서버에게 저장해두는거죠! 서버는 유저가 아이디와 비밀번호를 보내면 DB 정보와 확인한 뒤 세션에 세션ID를 키로 유저 접속 정보를 저장합니다. 세션ID만 클라이언트에게 보내죠. 클라이언트는 쿠키와 같은 방식으로 요청 시 세션ID를 가지고 요청하게 됩니다.
세션은 쿠키와 같이 구현 로직이 간단하지만 악용될 가능성이 큽니다! 악의적인 사용자 입장에선 세션ID만 탈취하면 되기 때문에 쿠키와 비슷한 보안 정도입니다(보안이라고 하기도 어려울정도로 공격에 취약합니다ㅠㅠ). 또한 세션을 사용한 로그인 방식은 서버에 메모리를 저장하기 때문에 스케일 아웃이 어렵다는 단점이 있습니다. 스케일 아웃을 할 수 있는 방법은 있나요? 궁금증을 가질 수 있습니다. 이에 대한 답변은 조금만 아래로 내려가면 알 수 있습니다. 스크롤 다운!
장점
- 구현 로직이 간단함.
단점
- 악용될 가능성이 높음.
- 서버에 저장되는 메모리가 존재함.(스케일 아웃이 어려움)
세션 로그인 보완 방식과 한계점
앞에서 session은 서버에 저장되기 때문에 scale out이 어렵다는 단점에 대해 언급했습니다. 해당 단점을 보완하는 방식은 크게 3가지가 있습니다. 이들에 대해 알아보도록 하죠:)
1. Sticky session
sticky session은 클라이언트 요청과 session이 들어있는 was를 의도적으로 연결시켜주는겁니다! 끈적끈적한 연결고리를 만드는거죠! 해당 방식을 이용하면 scale out은 할 수 있지만, 로드 밸런서가 추가적인 일을 하기 때문에 비효율적입니다. 또한 특정 서버에 세션이 집중되는 단점이 존재합니다! 서비스에서 새로운 이벤트를 열었다고 가정해보죠! 트래픽이 많아져서 서버를 증설했습니다! 그렇다면 새 유저들은 증설된 서버로 가겠죠! 특정 서버에 세션이 집중되는 현상이 발생했습니다. 세션은 서버에 골고루 분포돼있어야 좋은 저장 방식입니다. 한 서버만 과도하게 일하는건 좋지 않은 현상:)
2. Session clustering
세션 클러스터링은 한 WAS의 변경된 세션 데이터를 다른 WAS에도 전파하는 방법입니다. 마치 봉화대를 이용해서 데이터를 공유하는 것과 비슷합니다! 일일히 알려주는거죠! 하지만 이를 이용하는 방법 또한 비효율적입니다. 세션을 다른 저장소에 복사하는 행위 자체가 서버에겐 추가적인 연산입니다. 심지어 톰캣 내부의 세션 map은 ConcurrentHashMap입니다. 세션 변경 요청이 일정 시간을 기다려야 하는 상황까지 발생하는 군요!
3. 공유 세션 서버
공유되는 세션 서버를 사용하는 방법이 있습니다. 공유 세션 서버를 사용하게 되면 WAS들은 매 로그인마다 redis에 접근해서 로그인 정보를 저장하면 됩니다. Redis는 single thread 아닌가요? 그럼 느리지 않나요?라고 생각할 수 있지만 redis는 aws.amazon.com에 따르면 sub-milisecond의 latency를 보장하기 때문에 굉장히 빠릅니다. 그럼에도, 결국 redis를 쓰는 것 자체가 서버에게 부담입니다. 결국 서버를 하나 더 두게 되기 때문이죠. 또한 가끔이 아닌, 매 요청마다 redis에 접근하게 되므로 redis엔 병목현상이 일어나겠죠.
OK! 결국 세션을 사용하게 되면 서버에 데이터를 저장하게 되어 스케일 아웃이 어렵군요. 스케일 아웃을 잘 하기 위한 방법들(sticky session, session clustering, 공유 세션 서버)이 있지만, 이들도 결국 서버에게 추가적인 연산이나 메모리 공간을 요구하는 방법들입니다. 따라서 서버에게 부담이 거의 없는 로그인 방법(JWT)에 대해 알아볼겁니다. JWT를 이용한 로그인 방법에 대해 살펴보죠!
드디어 로그인이 무엇인지 알아보고 대표적인 구현 방식인 쿠키와 세션과 그 한계점에 대해 알아봤습니다😃!
긴 여정을 따라 와주셔서 감사합니다🙇♂️.
부디 여러분들이 해당 글을 읽으셨을 때 초기에 제가 말씀 드렸던, 왜? Bullet point는? 색깔의 의미를 잘 이해하며 읽으셨으면 합니다. 사실상 두개를 하는 능력이 전 정말 중요하다고 생각합니다. 개념을 제대로 이해할 수 있기 때문이죠.
그럼 다음 번에 또 봅시다👋👋!
Thanks, im 김민석(갈레)!
출처
'TIL > 개발 칼럼' 카테고리의 다른 글
#3 타행 이체 기능 성능 개선기, 속도(아웃박스 스케줄러 전략 선정 및 구현) (0) | 2023.04.08 |
---|---|
#2 타행 이체 기능 성능 개선기, 데이터 정합성(아웃박스 패턴) (1) | 2023.04.07 |
#1 타행 이체 기능 성능 개선기, 프로젝트 소개 (0) | 2023.04.07 |
야크 털은 어디까지 깎아야 할까? JWT, 비대칭키, RSA, 유클리드 호제법, 정수론 (0) | 2022.11.10 |
사용자의 UX를 고려한 로그인(JWT, 세션, 쿠키) 보안 전략 수립 및 구현(2) (0) | 2022.07.02 |