세션
사용자가 웹 브라우저를 킨다고 가정해보자. 예를 들어서 http://www.naver.com을 웹 브라우저에 입력하였다. 최초로 웹브라우저에 들어가면 일단 서버는 해당 주소에 맞는 controller 메서드를 찾아서 html을 사용자에게 리턴해줄 것이다.
그런데 다음에 접속할 때는 상황이 다르다. 서버는 이제 사용자가 누구인지 알아서 거기에 따른 맞춤 광고나 정보들을 제공해준다. 다음에 요청할 때는 세션 ID라는 것이 같이 전송되기 때문이다. 여기서 세션 이라는 것을 처음 접할 수 있다.
웹 브라우저는 세션 ID를 받아서 특정한 설정을 안해주는데도, 자동으로 웹 브라우저에 쿠키라는 저장 영역에 세션ID가 담기게 된다. 이 쿠키라는 영역에 담기는 세션 ID는 언제 생기냐 하면, 최초로 사용자가 서버에 요청했을 때 생기게 된다.
만약에 최초 요청이 아니라, 두번째, 세번째 요청일 시 세션 ID를 header 영역에 달고 요청하게 되는 것이다. (header안에 쿠키라는 영역이 있다)
세션ID는 그럼 뭘 확인해주는가? 세션 ID는 처음 접속했는지, 아니면 2번째, 3번째 접속했는지를 알 수 있다.
여기서 그럼 이런 생각을 할 수도 있다. 세션 ID를 위조해서 header의 쿠키에 넣어서 전달하면, 내가 아닌 다른 사람으로 서버가 인식한다는 것이니까, 위조를 할 수 있는 것 아닐까?
그럼 세션 ID를 위조할 수는 없을까?
이를 방지하기 위해서 세션 ID를 만들어줄때마다 서버는 세션ID의 목록을 가지고 있어야 된다.
즉, 세션ID는 최초 요청 시에 만들어지고, 웹 브라우저는 계속 요청할때마다 세션ID를 들고간다.
그럼 세션ID는 언제 사라지게 되는 것일까? 3가지 경우가 있다.
- 서버 쪽에서 session 목록을 날려버릴 때
- 사용자가 브라우저를 닫을 때 (종료할 때) -> 서버에 값이 살아있지만 특정 시간(보통 30분)이 지나면 이것도 사라짐
- 특정 시간이 지났을 시 -> "우리가 세션이 종료되었습니다. 다시 로그인해주세요" 이런 메시지가 오는 경우 생각
세션을 사용한 로그인
세션을 로그인할 때 사용한다면 로직은 다음과 같다.
- 유저가 처음에 서버에 요청을 한다.
- 서버는 세션에 세션ID를 하나 만들어주고(ex> 1234) 서버 세션공간에 기록해둔다.
- 서버는 유저에게 응답(response)를 돌려준다.
- 유저가 다음 요청을 하게 될 때는 세션 1234를 쿠키에 넣어서 이번엔 로그인을 요청한다.
- 서버는 DB에 로그인 정보가 있는지 확인한다.
- 해당하는 user가 있다면, 서버의 세션에서 세션ID가 1234인 곳에 user 정보를 저장하게 된다.
- 그럼 이제 다음번에 사용자가 예를 들어 사용자 프로필 화면에 접속했다고 하면, 세션 있는지 먼저 확인한다
- 세션이 있다면 DB에서 사용자 정보를 찾아서 서버에 응답해준다.
- 해당 정보를 돌려준다!
즉, 세션을 통해서 그 사용자 인증도 할 수 있고, 민감한 정보를 요청할 때 세션을 통해서 세션값이 있는지 확인하고 정보가 존재하는지 확인한다.
세션의 단점
세션의 단점에 대해서 생각하려면 사용자가 많을 때를 가정해봐야 한다.
만약 서버가 100명을 처리할 수 있는 서버인데, 1000명이 동시에 접속했다고 가정해보자. 그럼 900명은 대기해야한다. 그래서 회사는 서버를 늘리고 싶어한다. 늘리면 당연히 1000명을 받을 수 있을텐데 문제는 세션이다.
세션은 서버에 같이 존재하는데, 만약 이전 서버에 로그인해서 세션에 기록되었다면 새로 늘린 서버에 접속하면 해당 서버의 세션에는 로그인 정보가 없기 때문에 로그인이 잘 되었는지 이용자에게 전달해줄 수 없는 문제가 생긴다.
이걸 해결하려면 몇 가지를 생각해볼 수 있다.
- 먼저 Sticky Server라는 것을 만든다. 이 서버는 이제 최초에 들어온 사람은 로드 밸런싱 이런거 없이 무조건 처음 접속한 서버로만 들어가게 강제하는 것이다.
- 아니면 세션 전체를 복제시켜서 서버마다 세션을 저장해줄 수 있다.
- 또, 세션에 저장하는 게 아니라 다른 한 군데 데이터베이스에 값을 넣고 이걸 세션이라고 생각해서 공유해서 사용하는 것이다.
문제는 해결책들이 기존의 세션의 장점을 사라지게 한다.
세션은 일단 서버에 인메모리 즉, 속도가 빠르다는 장점이 있는데, 3번째 방법은 데이터베이스를 따로 둔다는 것은 하드디스크에서 읽어와야 하기 때문에 속도가 느려진다. (하드디스크에 접속한다는 것은 I/O가 일어난다는 것이기 때문에..)
그래서 현재 세션을 사용하는 서버들은 DB가 아니라 메모리 공유 서버를 사용한다. 그래서 모든 서버들이 메모리 서버에 접근하는데 여기서 나오는 대표적인 인메모리 데이터베이스가 Redis이다.
세션을 사용하지 않고, JWT 토큰을 사용하는 방법이 더 많이 사용된다. JWT 토큰에 대해서도 정리해보겠다.
'백엔드' 카테고리의 다른 글
[JWT] JWT 인증을 사용하는 이유 (2) | 2023.10.04 |
---|---|
GithubAction을 이용해서 Spring 프로젝트 CI/CD(with Docker) (0) | 2023.09.06 |
[AWS] Elastic BeanStalk 배포와 Trouble Shooting (0) | 2023.05.23 |
[Spring] Spring으로 웹 개발을 진행할 때 알아야할 정보 (0) | 2023.05.23 |
Gradle (0) | 2022.12.27 |