세션이 왜 필요한 것일까?
HTTP 프로토콜은 stateless 연결이므로 웹 서버에서는 기본적으로 각 클라이언트를 위해 다음 요청까지 메모리에 데이터를 유지해주지 않는다. (request 인스턴스는 응답과 동시에 메모리에서 제거된다.) 그래서 다음 번에 다시 요청을 해도 요청한 클라이언트가 누구인지 인식하지 못한다. 하지만 쇼핑몰 사이트와 같은 것을 보면 한번 봤던 상품 리스트가 오른편에 출력되고, 새로고침을 하거나 브라우저를 종료했다가 다시 실행해도 리스트가 그대로 보여진다. 로그인을 하지 않아도 장바구니에 상품을 담으면 메모리를 사용하는 것 처럼 다시 확인 할 수가 있다. 이러한 동작은 어떻게 이루어지는 것일까?
데이터베이스 사용을 생각해보자. 상품을 요청하는 클라이언트의 고유 키를 생성하여 해당 클라이언트가 행한 동작에 대한 값을 데이터베이스에 저장 후 재 요청 시에 이 키를 가진 클라이언트의 동작들을 데이터베이스에서 가져와서 전달해주면 이러한 기능을 제공해줄 수 있을 것 같다. 하지만 매 요청마다 데이터베이스에 접근하여 정보를 읽고 쓰는 작업을 한다면 서버에 엄청 부하를 주게 될 것이다. 또한 이 클라이언트가 고유키를 변조한다거나 잃어버린 경우에는 제대로된 서비스를 제공해줄 수가 없다. (개발자가 구현하는 것이기 때문에 실수할 소지가 있다.)
결국은 이전에 요청한 정보에 대한 데이터들을 어딘가에는 저장을 해야한다. JSP에서는 HttpSession 객체를 사용하여 각 클라이언트 마다 고유한 HttpSession 객체를 사용하여 데이터를 저장하고 활용할 수 있다.
세션을 구분하려면?
각각의 클라이언트가 자신의 HttpSession 객체를 찾아낼 수 있어야 하는데 웹서버에서는 어떻게 클라이언트를 구분해낼 수 있을까?
간단하게는 request 객체로 IP를 얻어낼 수 있으므로 IP를 활용하면 될 것 같다. 하지만 NAT 환경이라고 생각해보면 내부에서 여러개의 유일한 IP를 사용하더라도 외부에서는 NAT 서버의 IP를 사용하게 되므로 구별해 낼 수가 없다.
그러므로 각 클라이언트를 구별하기 위한 ID 값이 필요하다. 컨테이너에서는 클라이언트가 제일 처음 요청을 보낼 때 클라이언트의 유일한 세션 ID를 생성한다. 그리고 이 값을 Response에 넣어서 클라이언트에게 전달한다. 그 이후부터는 클라이언트가 요청을 보낼 때 이 세션 ID를 함께 보내게 된다.
이 때 세션 ID 정보를 교환하는 가장 간단하며 일반적인 방법은 쿠키를 사용하는 것이다. 응답 시에는 Response 헤더의 Set-Cookie에 값이 셋팅되고 클라이언트가 요청할 때는 Request 헤더의 Cookie에 값을 셋팅하여 전달한다. (Set-Cookie: JSESSIONID=0AABAKDJLDS..)
이러한 작업을 개발자가 구현할 필요는 없다. Session을 생성하고 클라이언트에게 전달하고 객체를 만드는 일은 모두 내부에서 일어난다. JSP 에서는 request.getSession()만 호출하면 내부적으로 HttpSession 객체를 생성하고, 얻어와 사용할 수 있다.
세션을 응용하면 요청한 클라이언트가 첫 방문인지 구별해낼 수가 있다. (여기서 첫 방문은 세션 만료 주기에 따른 방문. 하루가 될 수도 있고 방금 전이 될 수도 있다.) 위에서 언급한 것 처럼 세션은 클라이언트가 처음 Request를 요청했을 때 생성이 된다. JSP에서는 세션에 대한 처리가 처음이든 나중이든 request.getSession()을 통해 이루어지기 때문에 새로운 Session임을 구별하기 위해 isNew() 메서드를 제공한다.
쿠키를 사용하지 않는다면?
만일 클라이언트가 쿠키를 사용하지 않는다면 어떻게 될까? 서버에서 아무리 Session을 생성하더라도 클라이언트에서 Request 헤더에 Cookie를 셋팅하지 않고 전달하기 때문에 서버에서는 새로운 클라이언트라 인식하고 Session만 계속 생성하게 될 것이다.
이럴 때 세션을 이용하기 위해 URL 재작성 기능을 사용한다. URL 재작성 기능은 세션 ID 정보를 모든 URL 뒤에 추가하는 방법이다.
모든 URL 요청에 세션 ID를 추가로 달고 컨테이너에서는 URL 끝에서 세션 ID 정보를 잘라내어 매칭 되는 세션 정보를 사용하게 된다. (http://test.com/index.html;jsessionid=0AABAKDJLDS)
최초 컨테이너가 개발자가 코딩한 getSession() 부분을 만나면, 클라이언트의 Request에서 세션 ID를 읽지 않는다. 최초 연결이라는 것을 인지하기 때문에 이때는 클라이언트가 Session ID를 모르고 있을 것이라는 걸 컨테이너가 아는 것이다. 이 시점까지 컨테이너는 클라이언트 쿠키가 사용 가능한지 아닌지 모르는 상태이다. 그래서 클라이언트의 첫번째 응답은 쿠키와 URL 재작성을 동시에 사용한다.
URL 재작성 기능은 실행 시에만 세션 ID를 생성하게 되므로 페이지 내에서 URL을 동적을 만드는 경우에만 사용 가능하다. 즉, <a href> 태그에 주소가 하드코딩 된 경우에는 사용이 불가능 하다.
'Programming > JSP' 카테고리의 다른 글
컨테이너의 역할 (0) | 2016.09.26 |
---|---|
서블릿이란? (0) | 2016.09.26 |
댓글