본문 바로가기
FrameWork & Runtime/Spring

Spring Session & Cookie

by jaeaemin 2022. 3. 9.

 

[1] HTTP 요청과 응답

 

웹 서비스는 HTTP 프로토콜을 기반으로 사용자와 통신한다.

 * HTTP 프로토콜은 클라이언트의 상태정보를 가지지 않는 서버 처리 방식의 stateless 기반 프로토콜 

 * HTTP 프로토콜은은 클라이언트 요청에 대한 응답 후 연결을 끊는 비-연결지향 처리 방식이다.

 

상태 정보 처리 방식 
 Stateful
[ 상태 유지 ]
클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존함을 의미한다. 
즉, 순차적으로 정보들을 기록하면서 다음의 요청에 대해 그 정보들을 토대로 응답한다.
Stateless
[ 무 상태 ]
 클라이언트와 서버 관계에서 서버가 클라이언트 상태를 보존하지 않는 것을 의미함 
 즉, 정보들을 기록하지 않고 새로 생겨나는 요청들에 새롭게 응답한다.

[장점] 서버의 확장성이 높아진다. > 대량의 트래픽 대처 용이
[단점] 클라이언트 요청에 상대적으로 Stateful보다 많은 데이터가 소모된다.

 

 

1. Stateful의 Risk 

만약 A라는 클라이언트가 C라는 서버와 서로 소통하고 있다고 가정하자.

C는 A가 " 주문 항목은 자전거,  가격은 20만원" 이라는 것을 기억하고 있다. 

 

이 때 대량의 트래픽이 발생하고 어떤 조건에 의해서 서버가 C에서 D로 교체되었다고 가정하자.

클라이언트 A는 이제 "배송지 = 울산"을 입력했다. 

하지만 서버 D는 배송지라는 정보만 받았을 뿐, 무엇을 구입하는지 조차 모르고 있다. 

이러한 문제점들을 해결하기 위해서 StateLess가 등장했다. 

 

 

 

2. Solution of Stateless 

Stateless를 통해서 위의 문제점을 해결 할 수 있다. 

즉, 연결을 게속해서 갱신하지만, 갱신할 때마다 소통이 끊어지지 않게 이전 정보를 추가로 제공하는 방법이다.

 

 

< 스토리 보드 예시 > 

Server : 어서오세요! 자전거 가개입니다.

Client : 구매 항목으로 들어와서 자전거를 선택함 

 

Server : 자전거의 색깔을 골라주세요 ! ( 오직 방향만 제시, 저장 X)

Client : 구매 항목으로 자전거 선택 , 색깔은 빨간색 

 

Server : 배송 위치를 선택해주세요 ! ( 저장 X ) 

Clinet: 구매 항목으로 자전거 선택, 색깔은 발간색, 배송지는 울산

 

Server: 결제 방식을 선택해주세요 ! (저장 X)

Client: 구매 항목으로 자전거 선택, 색깔은 발간색, 배송지는 울산, 결제는 카드

 

Server :  결제 완료 되었습니다 [ 이제 요청을 처리 (모든 정보를 받았음으로) ]

 

 

 

Stateless의 문제점 

이러한 Stateless도 문제점을 가지고 있다. 아래의 상황을 생각해보자 

HTTP 프로토콜로 클라이언트와 서버가 통신한다면 , HTTP 프로토콜은 Stateless기반으로 동작할 것이다.

이 때 쇼핑몰같은 웹서비스를 이용한다면, 페이지를 이동할 때마다 게속해서 서버와 연결해야 하는 문제점이 발생한다.

( 사용자의 요청마다 서버와 새로운 연결이 게속 생기기 때문 (login, purchase, remove ... )  )

이러한 문제점을 해결하는 방법으로 세션과 쿠키를 사용할  수 있다. 

 

 

 

 

 


[2] 쿠키와 세션 

  = 웹 통신동안 유하려는 정보를 저장하기 위해 사용하는 기술 

 

 

1. 쿠키란 

클라이언트(브라우저) 로컬에 저장되어 사용되는 키-값 형식의 작은 데이터 파일을 의미한다.

클라이언트의 상태정보와 사용자 인증의 유효 시간을 명시하여 로컬에 저장하고 , 그 시간동안 참조되면서 브라우저가 종료되어도 인증이 유지 된다. 

Response Header에 Set-Cookie 속성을 사용하면 클라이언트 쿠키를 만들 수 있다. 이 때 사용자의 요청과 상관없이 브라우저가 Reqeuest한다면 자동으로 Reqeust Header를 넣어서 서버에 전송한다.

 

 

[1-1] 쿠키 구성 요소 

이름 쿠키를 구별하는데 사용되는 구분자
쿠키의 이름에 매핑되어 사용되는 값
유효시간 쿠키의 유지시간
도메인 쿠키를 전송할 도메인
경로 쿠키를 전송할 요청 경로

 

[1-2] 쿠키 동작 방식

  1. 클라이언트에서 reqeuset 요청 
  2. 서버에서 쿠키를 생성하고 HTTP 헤더에 쿠키를 포함시켜서 응답
  3. 브라우저 종료시, 쿠키 유효시간동안 쿠키를 클라이언트에 보관
  4. 같은 요청을 할 경우 HTTP 헤더에 쿠키를 포함시켜서 응답
  5. 서버에서 쿠키를 읽고 , 업데이트가 필요한 경우 업데이트하여 HTTP 헤더에 새로운 쿠키 포함시켜서 응답

 

[1-3] 쿠키의 예시

  • 방문 사이트의 아이디와 비밀번호를 저장하는 경우
  • 쇼핑몰의 장바구니 기능
  • 지금부터 N시간까지 이 창을 보지 않습니다 등 

 

[1-4] 쿠키 특징

 

  • 클라이언트에 총 300개의 쿠키를 저장할 수 있다.
  • 하나의 도메인 당 20개의 쿠키를 가질 수 있다
  • 하나의 쿠키는 4KB(=4096byte)까지 저장 가능하다.

 

 

 

 

 

 

2. 세션이란

쿠키를 기반으로하여 사용자 정보파일을 클라이언트가 아닌 서버에서 관리하는 가슐

서버에서는 클라이언트를 구분하기 위해 세션 ID로 구분하고, 서버에 접속하는 동안 인증상태를 유지함 

(접속 시간에 제한을 두고, 일정 시간 이상 응답이 없으면 인증상태를 해지하는 것도 가능함)

사용자의 정보를 서버에서 관리하기 때문에 보안성능은 뛰어나나, 사용자가 많아지면 서버 자원을 많이 소비하게 된다. (성능 저하)

클라이언트에서 Request를 요청하면, 서버 엔진에서 세션 ID를 부여함 ( 클라이언트 식별자 ) 

 

 

[2-1] 세션 동작 방식 

  1. 클라이언트가 서버에 접속하고, 세션 ID를 발급 받는다. 클라이언트는 세션ID 기반으로 쿠키를 사용해 정보를 저장한다.
  2. 클라이언트는 서버에 request할 때, 쿠키의 세션ID를 포함시켜서 전송한다.
  3. 서버에서 세션ID를 기반으로 검색하여 클라이언트 정보를 가져와 사용한다.
  4. 세션 ID로 찾은 클라이언트 정보를 기반으로 request를 처리하고 클라이언트에게 response한다.

 

[2-2] 세션의 예시

  • 서버에 데이터를 저장하므로, 큰 양이 아닌 중요한 정보에 해당 ( 로그인 등 보안상 중요 정책 ) 

 

 

 

 

3. 쿠키와 세션의 차이

 

세션은 쿠키를 사용하여 HTTP 요청과 응답을 처리한다. 

이 때 가장 큰 차이는 사용자의 정보가 저장되는 위치인데, 쿠키의 경우에는 클라이언트에 정보를 저장하고 세션은 서버에 정보를 저장한다

보안적인 측면에서는 당연히 서버에 정보를 저장하는 세션의 경우에 보안적으로 뛰어나다.

( 쿠키는 스니핑 당할 우려가 있지만, 세션은 SessionId를 이용해 서버에서 처리하기 때문에 비교적 보안 측면에서 우수하다 ) 

요청속도는 쿠키가 세션보다 뛰어난데 이 이유는, 세션의 경우 서버에서 정보들을 처리해야 하기 때문이다.

 

 

https://hahahoho5915.tistory.com/

 

 

 


[3] Spring에서 세션 & 쿠키 

 

[1] Spring에서의 Cookie 구현

 

public class Mall {

    private String gender;
    private boolean cookieDel;

    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public boolean isCookieDel() {
        return cookieDel;
    }
    public void setCookieDel(boolean cookieDel) {
        this.cookieDel = cookieDel;
    }

}


// 컨트롤러 단 // 
@RequestMapping("/main")
public String mallMain(Mall mall, HttpServletResponse response){

        Cookie genderCookie = new Cookie("gender", mall.getGender());

        if(mall.isCookieDel()) {
        genderCookie.setMaxAge(0);
        mall.setGender(null);
        } else {
        genderCookie.setMaxAge(60*60*24*30);
        }
        response.addCookie(genderCookie);

        return "/mall/main";
}

main 페이지를 요청하는 /main이 클라이언트에서 요청된다면, mallMain 메서드가 실행되면서 쿠키를 생성하고, 전달한다.

이 때 gederCookie의 인자로 오는 Mall 객체 인자는 클라이언트에서 보내는 커맨드 객체이고, 이 객체에 cookieDel 변수가 담긴다.

cookieDel 변수는 쿠키를 삭제할 것인지 정하는 변수로 true인 경우 쿠키를 삭제하는 메소드가 실행된다.

그렇지 않은 경우는 setMaxAge 메서드를 통해서 쿠키 유효기간을 연장한다.

마지막으로 사용자에게 보낼 쿠키 데이터를 HttpServletResponse 객체의 addCookie 메서드를 통해 쿠키 정보를 저장한다.

이 후 서버에서는 받은 쿠키 정보를 이용해서 사용자 정보를 관리한다.

 

 

 

 

[2] Spring에서 Session 구현 : HttpServletReqeust 

스프링 MVC에서 세션은 HttpServiceReqeust 또는 HttpSession을 사용해서 구현하는 것이 가능하다.

 

아래 코드의 동작 방식은 다음과 같다.

  1. 사용자 정보 변경 요청으로 " xxx/modify " 요청이 들어온다.
  2. HttpServletRequest 객체의 request 변수가 인자로 들어오면 modify 메서드가 실행된다.
  3. modify 메서드 내부에서 request.getSession()을 통해 세션 값들을 얻어온다.
  4. 그 후 session.setAttribute( )를 통해 멤버 변수들을 초기화한다.
  5. 마지막으로 ModelAndView 객체를 초기화&값 할당한 뒤 리턴한다.
@RequestMapping(value = "/modify", method = RequestMethod.POST)
public ModelAndView modify(Member member, HttpServletRequest request) {

        HttpSession session = request.getSession();

        Member mem = service.memberModify(member);
        session.setAttribute("member", mem);

        ModelAndView mav = new ModelAndView();
        mav.addObject("memAft", mem);
        mav.setViewName("/member/modifyOk");

        return mav;
}

 

 

사용자의 세션을 끊는 방식으로는 삭제하는 url에 대해서 request 객체의 세션을 얻은 뒤,

그 세션을 invalidate 메서드로 비활성화 시켜주면 세션 연결이 사라지게 된다. 

따라서 이 후의 url에 연결하면 새로운 사용자 정보로 판단되고, 다시 정보를 등록해야 한다.

@RequestMapping(value = "/remove", method = RequestMethod.POST)
public String memRemove(Member member, HttpServletRequest request) {

        service.memberRemove(member);

        HttpSession session = request.getSession();
        session.invalidate();

        return "/member/removeOk";
}

 

 

 

[4] 웹 캐시란 ? 

캐시는 여러 이미지나 css, java script 파일 등을 브라우저나 서버의 앞 단에 저장해놓고 사용하는 것을 의미한다.

한번 캐시에 저장된 경우 브라우저에서 참조하기 때문에, 서버에서 변경점이 생겨도 사용자에게 표시되지 않을 수 있다.

캐시 파일들을 업데이트 시켜주기 위해 캐시 파일을 지워주거나, 서버에서 클라이언트 응답시, header에 캐시 만료 조건을 명시할 수 있다.

 

정리하면 Client가 요청하는 html, image, css 등 파일에 대해 첫 요청 시 파일을 내려받아 특정 위치에 복사본을 저장한다.

이후 동일한 URL의 Resource요청 시, 다시 내려받지 않고 내부에 저장한 파일을 사용하여 서비스 속도를 향상시킨다.

서버를 통해 내려받는 양이 감소하니 응답 시간도 줄어들고 트래픽이 감소하게 된다.

 

 

웹 캐시의 종류

브라우저 캐시 - 브라우저 또는 HTTP 요청을 하는 Client Application에 의해 내부 디스크에 캐시함.
- 개인에게 한정된 캐시로 resource를 공유하지 않는다.
(ex) 이전 페이지 

프록시 캐시  - client, server가 아닌 네트워크 상에서 동작함 
 - 큰회사의 IPS의 방화벽에 설치되고, 대기시간-트래픽-접근정책-사용률 등을 기록하고 수행함
(ex) 

게이트웨이 캐시  - 서버 앞 단에 설치되어 요청에 대한 캐시 + 효율적인 분배로 가용성, 신뢰성 등 향상
(ex) 

반응형

'FrameWork & Runtime > Spring' 카테고리의 다른 글

MyBatis  (0) 2022.03.07
Spring Bean & Dependency Injection(DI)  (0) 2022.03.01
Spring의 Request & Response  (0) 2022.03.01
Spring 서비스 계층  (0) 2022.02.28
<코드 프레소 웹 개발 트랙> Spring Boot 웹 개발 초급 [1]  (0) 2022.02.22