쿠키 세션 캐시?
셋이 각각 어떻게 다르고 어떻게 쓰일까?
각종 편의, 오락시설을 갖춘 대규모 찜질방이 있다 가정하자.
이름은 울랄라 스파라 정하고 회원등록 하고 입장한 뒤 내부시설을 마음껏 이용한 뒤 나올 때에 한꺼번에 계산하는 식이다.
이곳에서는 쿠폰북이 아닌 쿠키북이라는 수첩을 들고 다니며 이용하는 시설마다 이것을 보여주게 되어있다. 이 쿠키북은 내가 직접 들고다니며 무언가를 기록할수도, 수정하거나 찢어버릴 수도 있다. 카페를 이용하고 스탬프를 받거나 샵에서 마음에 드는 물건이 있으면 적어두기도 하고 어떠한 이벤트를 한번 안내받으면 이미 한번 안내 받았다고 기록해둬서 여러번 귀찮은 일이 없도록 할 수도 있다. 이 쿠키북의 핵심은 내가 들고다닌다는 것. 그리고 시설을 이용할 때마다 보여준다는 것이다.
쿠키는 사이트를 방문하고 이용할 때에 브라우저에 저장되는 내용들이다. 브라우저는 내 컴퓨터에 있는거니까 내가 갖고 있는 정보인 것이다. 하지만 이 쿠키북에는 한계가 있다. 내가 임의로 고치거나 지울수도 있고 심지어 남이 훔쳐보거나 도둑질하기도 쉽다. 나로서는 민감하거나 중요한 정보를 쿠키북에 적어서 다니기는 불안할 것이다. 스파 측에서는 음식 서비스를 이용한 손님의 결제서를 손님의 쿠키북에다 적어주려 하지는 않을 것이다. 비싼거 사먹은 뒤 그 내역을 찢어내서 버리거나 고쳐서 주려는 손님들이 있을거니까.
즉 내가 들고다니는 쿠키북이 아니라 스파측에서 보관하고 관리해야 하는 정보들이 있다는 것이다. 스파 측에서는 스파를 이용하는 이용자들의 중요 정보들을 총괄하는 곳으로 울랄라 세션이라는 곳이 있다. 내가 스파에 입장하면 울랄라 세션에서 그때 그때 생성되는 바코드를 내 쿠키북에 하나 찍어준다. 내가 스파를 돌아다니며 시설을 이용할 때 이 고객은 회원으로 확인되어 입장해있다, 어디서 얼마짜리 서비스를 이용했다, 귀중품은 어디어디에 보관되어 있다 등등 쿠키북에다 보관하기 곤란한 정보들은 이 울랄라 세션에서 관리해주고 그 정보들이 각각 누구의 것인지는 이 바코드로 구분이 되는 것이다. 세션을 사용하는 사이트에 접속하면 서버에서는 사용자를 구분하기 위한 기한이 짧은 임시 키 하나를 브라우저에 보내서 쿠키에 저장한다.
'동민' 이라는 사용자가 사이트 안의 페이지들을 돌아다닐 때 이 사용자의 중요한 정보들은 이 서버의 메모리나 데이터베이스에 저장된다. 브라우저가 이 사이트의 페이지들에 접속할 때마다 http 요청에 이 키가 담긴 쿠키를 실어서 전송하고 서버는 그 키를 보고 '얘는 동민이구나' 인식해서 '동민'의 정보들을 가공해서 응답으로 보내주는 것이다. 우리가 네이버에 로그인 한 다음 네이버의 여러 페이지들을 이용할 때마다 새로 로그인 할 필요가 없는 건, 쿠키와 세션의 조합으로 컴퓨터에서 네이버에 로그인해있다는 걸 네이버 서버가 인지하고 있기 때문이다. 만약 네이버에 속한 모든 쿠키를 임의로 지우고 새로고침을 눌러보면 로그인이 해제되어 있는 것을 확인할 수 있다.
서버에서는 세션에 나의 로그인 정보를 갖고 있지만 그게 내 것이라는 걸 증명할 SessionId가 나의 쿠키를 보관하는 곳에서 지워졌기 때문이다.
정리하자면,
쿠키는 로그인창의 아이디를 자동완성하거나, 공지 메시지를 하루 안 보기 하거나 쇼핑몰 사이트에서 로그인 안 한 상태로 물건을 장바구니에 담는 등. 사용자의 편의를 위하되, 지워지거나 조작되거나 가로채이더라도 큰 일은 없을 그런 수준의 정보들을 브라우저에 저장하는데에 사용한다.
그리고 사용자나 다른 누군가에 노출되어서는 안되는, 서비스 제공자가 직접 관리해야 할 정보들은 세션으로 서버 안에서 다뤄지는 것.
웹 개발자들을 사이트를 만들 때. 이 정보는 쿠키에 젖아할 지 세션에 저장할 지 적절한 판단을 내릴 수 있어야 하겠다.
쿠키로 노출시켜서는 안될 정보들이 있고 그리고 세션을 남발하면 접속자가 많을 때 서버에 부하가 걸릴 것이다.
문어발 기업인 울랄라 스파가 속한 울랄라그룹은 신발 판매 사업에도 진출해있다. 울랄라 스파 쇼핑섹션에 개점을 했다. 손님이 방문해서 신발을 고르고 운동화 사이즈 하나를 요청했다. 직원이 창고에서 신발을 가져왔고 손님은 한번 신어본 뒤 좀 더 둘러보고 오겠다 하고 간다. 직원이 손님을 보아하니 다시 와서 신발을 사거나 다른 제품과 비교해서 다시 신어보거나 할 것 같다. 그런데 다시 또 창고에 두었다가 다시 가지러 가면 손님도 기다려야하고 자기도 힘들 것이다. 그래서 그 신발을 매장 한 켠에 있는 큰 백에 일단 넣어둔다. 이 백의 이름은 캐시 백이다. 캐시란 개념은 웹 뿐만 아니라 컴퓨터의 메모리 부분이나 안드로이드 등 다양한 곳에서 쓰이는데 거의 공통적인 의미로, 가져오는데 비용이 드는 데이터를 한 번 가져온 뒤에는 임시로 저장해두는 것이다. 웹 캐시는 이미지 등의 정보를 불러올 때 데이터 사용량도 발생하고 시간도 들기 때문에 사용자가 여러 번 방문할 법한 사이트에서는 한번 받아온 데이터를 사용자의 컴퓨터 또는 중간 역할을 하는 서버에 저장해둔다.
HttpServletRequest 를 사용하면 값을 받아올 수 있다.
예를 들어, 아이디, 비밀번호 등의 데이터를 컨트롤러로 보냈을 때, HttpServletRequest 객체 안에 모든 데이터들이 들어가게 된다.
원하는 데이터를 꺼낼 때에는 HttpServletRequest 객체 안의 메소드를 이용하면 된다.
getParameter() 메소드는 반환 타입이 String 타입이다.
String id = httpServletRequest.getParameter("id");
HttpServletRequest객체안의 id 값을 Stirng 타입으로 가져온다.
@Controller
public class HomeController {
@RequestMapping("/board/confirmId")
public String confirmId(HttpServletRequest httpServletRequest, Model model) {
String id = httpServletRequest.getParameter("id");
String pwd = httpServletRequest.getParameter("pwd");
model.addAttribute("id", id);
model.addAttribute("pwd", pwd);
return "board/confirmId";
}
}
id와 pwd를 HttpServletRquest 객체를 통해 받아오고,
그리고 Model 객체를 이용해서 뷰로 값을 넘긴다.
<body>
id : ${id}<br>
pwd : ${pwd}
</body>
뷰에서 그대로 출력해보면
주소 창에 board/confirmId?id=dongmin&pwd=1234
뜨는 것을 확인할 수 있다.
정리하자면
HTTP 기반으로 동작하는 클라이언트가 서버에 정보를 요청할 때 생성되는 "상태정보"를 세션이라고 합니다. 세션은 HttpSession이라는 인터페이스 객체로 표현되며, HttpSession 객체는 HttpServletRequest의 getSession()이나 getSession(true) 메소드를 이용하여 생성할 수 있습니다.
HttpSession 객체가 생성될 때는 요청을 보내온 클라이언트 정보, 요청 시간 정보 등을 조합한 세션 ID가 부여되며, 이 세션 ID는 클라이언트 측에 쿠키 기술로 저장됩니다. HttpSession 객체는 서버에 생성되며, 클라이언트에는 세션 ID가 쿠키 기술로 저장되어 각 클라이언트에 대해 생성되는 HttpSession 객체를 클라이언트마다 개별적으로 유지 및 관리합니다.
클라이언트마다 개별적으로 생성되어 유지되는 HttpSession 객체는 요청을 보내온 클라이언트와 서버간에 일정 시간(최대 시간은 브라우저가 살아 있는 동안) 동안 각 클라이언트의 상태정보를 서버에 저장하여 유지하고자 하는 목적으로 사용되는 객체입니다. 그리고 클라이언트마다 상태정보를 일정 시간 동안 개별적으로 유지하여 사용하는 기술을 '세션 트래킹(session tracking)'이라고 합니다.
세션 트래킹 기능의 구현 순서는 다음과 같습니다.
- 1) 클라이언트를 위한 세션을 준비한다. 이전에 이 클라이언트를 위해 생성된 세션이 이미 존재하면 존재하는 세션을 추출하고, 그렇지 않으면 새로 생성한다. 세션이 새로 생성될 때는 고유한 ID가 하나 부여되며, 이 ID는 클라이언트에 쿠키 기술로 저장된다.
- 2) 유지하고자 하는 정보를 저장할 목적의 객체를 생성하여 세션에 등록한다.
- 3) 클라이언트가 요청을 전달할 때마다 세션에 등록된 정보를 담고 있는 객체를 추출하여 원하는 기능에 사용한다.
- 4) 세션이 더 이상 필요없는 시점에서 세션을 삭제한다.
HttpSession 객체를 사용하고자 할 때는 개발자가 수동으로 생성하는 것이 아니라, 메소드를 이용하여 생성하거나 기존의 HttpSession 객체의 주솟값을 추출하여 사용합니다. HttpSession 객체를 얻으려면 HttpServletRequest 객체의 다음 메소드를 사용합니다.
HttpServletRequest의 getSession()
클라이언트가 가지고 있는 세션 ID와 동일한 세션 객체를 찾아서 주솟값을 반환합니다. 만일 세션이 존재하지 않으면 새로운 HttpSession 객체를 생성하여 반환합니다.
HttpServletRequest의 getSession(boolean create)
클라이언트가 가지고 있는 세션 ID와 동일한 세션 객체를 찾아서 주솟값을 반환합니다. 만일 세션이 존재하지 않으면, 매개변수 create의 값이 true인지 false인지에 따라서 다르게 동작합니다. true이면 getSession() 메소드와 마찬가지로 새로운 HttpSession 객체를 생성하여 반환합니다. 그러나 false이면 새로운 HttpSession 객체를 생성하지 않고 null을 반환합니다.
HttpSession 메소드
HttpServletRequest의 getSession() 또는 getSession(boolean) 메소드를 사용하여 HttpSession 객체를 얻어낸 후 다음과 같은 HttpSessio 객체에서 가지고 있는 메소드를 이용하여 클라이언트 단위로 정보를 유지하는 작업을 합니다. 즉 세션 트래킹 기술을 활용합니다.
상태정보 유지
웹에서 사용하는 HTTP 프로토콜의 통신 방식은 클라이언트와 서버 간의 연결을 클라이언트로부터 요청이 있을 때마다 매번 새롭게 연결하는 방식입니다. 요청이 있을 때마다 연결 작업이 새롭게 이루어지고, 서버가 클라이언트에게 응답을 보내는 즉시 끊어집니다. 이처럼 클라이언트와 서버 간에 연결상태가 유지되지 않는 통신 방식을 '무상태(Stateless)'라고 합니다.
무상태 통신 방식의 특징은 연결이 유지되지 않기 때문에 서비스를 요청한 클라이언트에 대한 정보가 유지되지 않습니다. 동일한 클라이언트의 요청이더라도 요청 단위로 연결이 맺어져서 이전의 작업은 지금의 연결 작업과는 아무런 관계가 없습니다. 그래서 클라이언트가 이전 요청에서의 처리결과를 계속해서 다른 요청에서도 사용하고 싶다면 서버 측이든, 클라이언트 측이든 어딘가에 저장해서 정보를 유지해야 합니다.
이처럼 클라이언트나 서버에 계속된 요청에서 사용할 수 있도록 저장한 정보들을 '상태정보(State Information)'라고 합니다.
다음은 상태정보 유지 기술들을 저장 위치와 저장 기간에 따라 분류한 것입니다.
저장 위치 분류
정보를 저장하는 위치에 따라 상태정보 유지 기술을 분류하면 다음과 같습니다.
클라이언트 측에 저장 기술
웹에서 클라이언트는 웹 브라우저를 의미합니다. 그래서 클라이언트 측에 저장한다는 것은 웹 브라우저에 저장하는 것을 의미합니다. 웹 브라우저가 종료되기 전까지 정보를 유지할 수도 있고, 또는 웹 브라우저가 종료된 이후에도 계속 유지하게 할 수도 있습니다. 이처럼 클라이언트 측에 정보를 유지하는 기술에는 쿠키(Cookie)가 있습니다. 다음은 서블릿에서 쿠키 기능이 있는 객체입니다.
javax.servlet.http.Cookie
서버 측에 저장 기술
서버 측에 저장한다는 것은 서버의 힙 메모리 영역에 만들어진 객체에 상태정보를 저장(등록)하는 것을 의미합니다. 상태정보가 저장된 객체가 힙 메모리 영역에 존재하는 한 등록된 상태정보는 계속해서 사용할 수 있습니다. 다음은 서블릿에서 서버 측에 상태정보를 저장할 수 있는 객체입니다.
javax.servlet.ServletContext
javax.servlet.http.HttpSession
javax.servlet.http.HttpServletRequest
유지 기간 분류
클라이언트나 서버 측에 저장된 정보들은 무한정 유지되는 것이 아니라 기간이 한정되어 있습니다. 정보가 저장되어 유지되는 기간을 기준으로 상태정보 유지 기술을 분류하면 다음과 같습니다.
웹 애플리케이션 단위 유지
웹 애플리케이션 단위로 유지한다는 것은 웹 애플리케이션이 서비스되고 있는 동안 유지하는 것을 의미합니다. 생명주기가 웹 애플리케이션과 같은 객체는 ServletContext입니다. ServletContext 객체는 웹 애플리케이션 서비스가 시작될 때 생성되고 종료될 때 소멸합니다. 그래서 ServletContext 객체에 상태정보를 저장하면 웹 애플리케이션이 서비스되고 있는 동안은 계속해서 사용할 수 있습니다.
javax.servlet.ServletContext
클라이언트 단위 유지
클라이언트 단위로 유지한다는 것은 클라이언트별로 구분해서 상태정보를 유지한다는 의미입니다. 예를 들어, A 클라이언트가 계속해서 사용하고자 하는 상태정보가 있는데, 이 상태정보를 다른 클라이언트는 사용할 수 없어야 할 때 클라이언트 단위로 유지해야 합니다. 대표적인 예가 로그인 작업입니다.
쿠키는 클라이언트 측에 상태정보를 유지하는 기술이어서 당연히 클라이언트 단위로 상태정보가 유지되어 사용되며, 서버 측에서는 클라이언트별로 생성되는 HttpSession 객체를 통해 클라이언트 단위로 상태정보를 유지할 수 있습니다.
javax.servlet.http.Cookie
javax.servlet.http.HttpSession
요청 단위 유지
요청 단위로 유지한다는 것은 클라이언트의 서비스 요청 단위로 유지한다는 것입니다. 웹에서는 클라이언트로부터 요청이 있을 때마다 새로운 연결 작업이 이루어지며, 클라이언트로 응답이 이루어지면 연결은 해제됩니다. 이렇게 하나의 요청에서만 상태정보를 유지하고자 할 때 HttpServletRequest 객체를 통해 할 수 있습니다.
javax.servlet.http.HttpServletRequest
출처 링크
참고링크