728x90


http통신은 상태라는게 없다. 그리고 연결이라는게 없다.

서버입장에서 항상 클라이언트는 새로온 손님일 뿐이다.

이를 극복하기 위해서 만든 것이 바로 쿠키라는 개념이다.

쿠키는 서버가 클라이언트에 흔적을 남긴다. 그리고 같은 url로 다시 연락이 올 경우 쿠키와 함께 요청한다.

이 방식으로 서버는 계속해서 쿠키에 기록함으로써 현재 클라이언트(유저)가 어떤 녀석인지를 판단할 수 있다.

하지만 이미 여기서 여러분들은 쿠키의 가장 크고 근본적인 문제점을 알 수 있다.


야.. 근데 그걸(쿠키=정보) 유저에게 맞겨도되?

쿠키에 별 시덥잖은 정보들이라면 상관없지만 조금 중요해진다면 어떻게 될까?

쿠키는 위조나 변조가 가능하며 심지어 남이 훔쳐갈수도 있다.

일단 유저가 가지고 다닌다는게 꺼림찍 하다는 것이다.


내놔봐! 내(세션)가 관리한다.

이렇게 해서 등장하는 것이 바로 세션이다.


세션은 쿠키 처럼 사용자의 데이터를 기록해둔다.

바로... 서버에!


여기서 여러분은 1차적으로 궁금증을 가져야하는데 사실 일반적으로 서버에는 데이터를 저장하는게 불가능하다.

왜냐하면 서버입장에서는 여러분이 번째로 접속했는지 두번째로 접속했는지 알 길이 없다는 것이다.

쉽게말하면 여러분이 첫번째로 접속했다고 가정하자. 그래서 서버에 여러분의 데이터를 저장했다고 가정하자.

근데 여러분이 두번째로 접속했다고 생각했을 때 이 두번째로 접속한 여러분이 첫번째와 동일인물인지 어떻게 알지?


클라이언트에 저장하는 쿠키야 첫번째 접속했을 때 발급하고 두번째에서 그 쿠키를 발급하는 놈은 동일인물인지 알 수있다.

놀이동산에서 처음 온사람에게 자유이용권을 주고 두번째로 입장한 사람에게 자유이용권을 가지고 있으면

"아 이놈이 두번째구나"하고 쉽게 알 수 있다.

세션은 도대체 어떻게 알건데? 자유이용권을 놀이공원에서 아무리 가지고 있어봐야 사용자에게 안주면 의미 없다.


즉 이론적으로 불가능하다는 것이다. IP? 30분 간격으로 바뀌는 경우도 허다하다.

맥주소? 웹 정책상 가져오는거 불가능 하다.

그럼 서버에 저장하는건 마치 불가능한 허무맹랑한 소리라는 이야기이다.

데이터를 저장해봤자 주인공을 특정하지 못한다면야 의미가 없으니까.


그럼 누가 누구인지 특정할 수 있는 방법은 없는 거야?

아니. 왜 없어? 여러분은 이미 방법을 알고 있잖아.

쿠키를 자유이용권에 비유해서 설명했잖아.

그렇다. 바로 쿠키를 발급해 주는 것이다.

여러분이 알아야하는건 반드시 쿠키만이 정답은 아니지만 일반적으로 쿠키를 사용한다.


이제 일반적으로 세션이 어떻게 동작하는지 보도록하자.

예시는 tomcat, jsp가 예제이다.


먼저 접속하는 모든 녀석들에게 쿠키(session id)를 부여한다.


접속하는 모든 녀석에게 쿠키를 발급한다. 이는 서버 로직을 안짜도 상관없다. 그냥 첫접속하는 모든 녀석에게 발급한다.

이를 session cookie라고 하는데 이 세션쿠키를 발급해준다.

앞으로 우리는 이 쿠키를 항상 가지고 있어야한다. 이 쿠키는 아까 말한 놀이공원 자유이용권과 같다.

이걸 가지고 있어야 동일인물임을 보장 받는다.


그리고 서버쪽에는 세션이라는게 생성된다.


session = request.getSession();

세션은 항상 request객체 안에 내장되 있다. 이는 다른 언어도 마찬가지이다.

원리는 사용자의 세션쿠키에 있는 session id와 서버의 session 객체가 가지고 있는 session id가 동등하다면 동일인물이라 가정한다.


※아니 근데 쿠키는 클라이언트에서 위조가 가능하다며!!

그럼 세션id는 도난당하면, 즉 자유이용권 빼앗아가면 끝인거 아냐?


뭐 맞는 말이긴 한데 일단 쿠키를 도난하는것보다 패스워드를 도난하는게 난이도가 더 쉽다.

게다가 쿠키는 도난당하더라도 그 한번의 접속에만 유용하다.

패스워드는 뺏기면 앞으로 영원히 털리는 거지만 세션쿠키는 뺏겨도 한번의 접속만 가능할뿐 세션쿠키가 한번이라도 소멸하게 된다면 

어짜피 서버에서 만료되게 되므로 의미가 없어진다.

게다가 무엇보다 쿠키에 중요한데이터가 없다.

털려봤자 시한부의 ID가 전부이다.

만약 인증시스템을 쿠키로 만들게 된다면 쿠키에 아이디나 패스워드가 있다는 이야기이다.

털리면 끝난다. 암호화 하면 되긴하지만... 그래도 불안한건 변함 없다.

하지만 세션기반 인증에서는 털어봤자 ID가 전부이다.

물론 서버를 털면 되긴 하겠지만... 그쯤되면 걍 아이디 패스워드 내줘라. 어짜피 우리의 영역이 아니다.


세션에 데이터를 저장한다.


session.setAttribute("name", "kukaro");

세션은 보통 데이터를 저장할 수 있다. 이 역시 key-value형태이다.

쿠키와 이렇게 보면 비슷한 맥락이 있지만 사용자의 컴퓨터에 저장되고 크기와 길이 제한이 있는 쿠키와는 달리

세션에서는 자체 메모리에 저장되므로(그냥 각 언어에 맞는 데이터라고 생각하면된다. jsp는 자바니까 자바객체이다.)

세션에서는 key는 String이지만 value는 온갖 자바객체르 담을 수 있다.

사실 저기 보이는 kukaro라는 값다. 그냥 String객체를 담은 것이다.


저장한 세션의 값을 꺼내는 방법역시 간단하다.

session.getAttribute("name");

이렇게 하면 각언어의 객체가 반환된다.

위의 경우 jsp이니 자바객체가 반환된다. 우리는 kukaro라는 String객체가 반환될 것이다.


세션은 이제 프로그래밍의 영역이다.


세션으로 데이터가 넘어들어오게되면 웹의 규칙을 벗어난다.

이제부터는 각각 언어에 맞는 규칙으로 사용하면된다.

그리고 반환시 적절하게 수정해서 반환하면 된다.


jsp는 자바의 세계이며 asp.net은 C#의 세계, cppCMS는 cpp, flask는 python, express는 js로 각각 짜면된다.


세션은 언제 죽음을 맞이하는데?


결국 만들어진 세션은 죽음을 맞이한다.

그 타이밍은 딱 두가지 관점으로 볼 수 있다.


1.클라이언트에서의 죽음(쿠키가 소멸됨)

2.서버에서의 죽음(서버내에서 세션을 소멸함)


세션은 클라이언트와 서버의 합작품이다.

즉 클라이언트의 쿠키가 죽게되면 서버의 세션은 더 이상 의미없다고 판단하여 서버역시 내부의 세션데이터를 몽땅 지워버린다.


반대도 마찬가지다.

서버에서 세션(여기서 세션은 각 언에 맞는 데이터덩어리다)은 시간제한을 정하던가 아니면 직접 죽일 수 있다.

죽이는 방법은 jsp에서는 아래와 같다.

session.invalidate();

이 명령어로 특정 세션을 곧바로 골로보낼 수 있다.


일반적으로 session의 생명주기는 뭐 플랫폼마다 다르지만 보통은 30분으로 정해놓는다.

설정을 바꾸지 않으면 30분이 적절하다고 생각하는거 같다.

물론 설정을 바꿔서 시간을 바꿀 수 있다. tomcat에서 바꾸는 방법은 아래와 같다.


<session-config>
<session-timeout>10</session-timeout>
</session-config>

web.xml에서 바꿀 수 있으며 단위는 분이다.

위의 경우 세션시간은 10분이된다.


어쨋든 시간이 만료되면 서버에서의 세션은 죽음을 맞이한다.

서버에서의 세션이 죽게된다면 클라이언트에 존재하는 쿠키는 아무짝에 의미없다.

이 경우 세션을 다시 만들게 된다.


그럼 클라이언트쪽 쿠키를 보도록하자.

이 쿠키는 시간제한을 일반적인 방법으로는 설정할 수 없다.

이 포스팅에 나와있지만 일반적으로 시간제한이 설정되있지 않다면 쿠키는 브라우저가 닫히는 순간 쿠키는 파괴된다.

여기서 세션이 죽는 경우는 다시 다른의미로 두가지로 해석된다.


1.세션은 일반적으로는 브라우저가 종료되는 순간 세션이 죽는다.

2.혹은 시간제한이 다되면 세션은 죽게된다.



세션과 쿠키의 차이점


둘다 데이터를 영속시키려는 점은 동일하다.

하지만 방식과 그걸 구현하는 과정은 여러분도 두 포스팅을 모두 읽어 봤다면 알겠지만

사실 엄청나게 다르고 쓰는 분야도 당연히 엄청나게 달라진다.


둘의 차이점을 비교해보자.


1. 쿠키는 브라우저가 종료되도 유지될 가능성이 있다. 세션은 브라우저가 종료되면 같이 종료된다.

2. 쿠키는 클라이언트에 저장된다. 세션은 서버에 저장된다. 일반적으로 클라이언트 저장은 파일(경량 db)에 저장되며 서버에서는 메모리에 저장되지만 둘다 저장위치를 바꿀순 있다.

3. 쿠키는 클라이언트에 있으므로 위변조가 가능, 세션은 서버쪽이므로 뚫으려면 서버를 뚫어야한다.

4. 속도는 일반적으로 쿠키 처리가 세션 처리보단 빠른편이지만 사실 속도를 이야기하는건 슈퍼똥컴이 아닌이상 의미 없는 수준이다.

5. 쿠키는 클라이언트만 사용하므로 서버에 부담을 주지않는다. 세션은 서버에서 처리하므로 사용자가 많고 담는 객체가 커질수록 부하가 매우 커진다.


보통 쿠키와 세션을 고르는 첫번째 기준은 브라우저가 닫혀도 유지할것이면 쿠키, 아니면 세션이다.

어짜피 중요한 정보인 아이디나 패스워드는 쿠키에 저장하진 않지만 그렇다고 세션에 저장하지도 않는다.

두번째는 보통은 보안성인데 사실 요즘에는 이건 잘 안따진다. 보안이 중요하면 세션에 담는다고 일반적이라고 하지만

요즘에는 사실 세션도 가급적 안쓰려는 추세이다. 그 이유야 간단한데 세션은 사용자가 많으면 서버에 부하가 커진다.

부하뿐만아니라 위에서도 언급했지만 세션은 이제 프로그래밍의 영역이다.

반대로 말하면 션은 프로그래밍코드에 매우 강력하게 종속된다.

서버의 구조를 바꾸거나 이러는데 힘이 든다는 이야기와 동일하다.


여튼 종류에 맞게 사용하면 될 것이다.


사용자가 브라우저를 닫았는지 바로 알 수 있는 방법은 없을까?


서버쪽에서 세션을 쓰면 사용자가 세션이 끊겼는지 바로 알 수 있을것 같지만 일반적으로는 바로 알 수 없다.

그 이유를 알기위해서는 세션이 어떤 상황에서 끊기는지 다시 봐야한다.


1.클라이언트에서의 죽음(쿠키가 소멸됨)

2.서버에서의 죽음(서버내에서 세션을 소멸함)


여기서 서버에서 죽는 경우, 즉 세션이 시간이 만료되는 경우이다.

이 경우에는 정확하게 알 수 있다.


하지만 클라이언트에서의 죽음은 정확하게 예측할 수 없다.

왜냐하면 쿠키가 소멸되는 경우(시간 만료건 브라우저가 종료됬건 클라이언트에서는 사라졌다.

그렇다고 서버의 세션객체가 바로 사라지는건 아니라는 것이다.

서버의 세션객체는 사용자가 직접 삭제하지 않으면 타임아웃까지 유지되게 된다.

그냥 그 세션객체가 의미 없어지는것 뿐이다. 이제 쿠키가 없으니 대조할 세션 id가 없어지는 것이다.

이는 서버로서의 낭비지만 대부분 그냥 저냥 쓰는 편인거 같다.


하지만 페이스북이나 텔레그램등의 앱들을 보면 종료하면 거의 바로 알아내서 사용자에게 알려준다.


window.onunload = function (ev) { 
console.log(ev);
}

일반적으로 onunload를 사용해서 구현하는 곳이 많다.

이 이벤트는 페이지를 옮기거나 브라우저가 꺼질 때 동작한다.

약간의 테크닉을 가미하면 페이지를 옮기는 경우는 제외할 수 있다.

하지만 이는 되게 불안정한 방법이다. 비 정상적인 종료는 감지를 못하기 때문이다.

그래서 롱풀링 및 풀링을 섞어서 쓴다고도 알려져있다.

추후에 이 방법은 중요한 내용이므로 다시 포스팅할 예정이다.



+ Recent posts