[Spring] 세션과 쿠키

olsohee·2023년 6월 5일
0

Spring

목록 보기
8/12

1. 세션과 쿠키

클라이언트와 서버는 stateless인 HTTP 통신을 주고 받지만, 로그인과 같이 접속했던 정보를 저장한 상태를 유지해야 하는 경우가 있다.

쿠키

서버에서 쿠키를 생성해 클라이언트에게 전달하면, 클라이언트 측에서 쿠키를 저장해두고, 그 이후로 서버로 요청을 보낼 때마다 쿠키를 함께 담아 보낸다.

따라서 서버에 메모리 부담을 줄일 수 있다.

그러나 쿠키 내부에 있는 보안 정보들이 그대로 노출될 수 있어서 보안 상의 문제가 있다. 그리고 쿠키 값은 외부에서 임의로 변경할 수 있다. 만약 쿠키 값으로 memberId를 사용한 경우, 쿠키 값이 1일 때 외부에서 쿠키 값을 2로 변경하면 memberId가 2인 사용자의 정보가 그대로 노출될 수 있다.

그리고 쿠키가 클 경우 네트워크 부하가 커질 수 있다.

세션

앞서 언급한 쿠키의 보안 상 문제를 해결하기 위해서는 쿠키에 중요한 값을 노출하지 않고, 사용자 별로 예측 불가능한 임의의 토큰(랜덤 값)을 노출해야 한다. 이 토큰은 서버에서 관리하며, 외부에 보여지는 토큰과 서버에서만 확인할 수 있는 사용자 id를 서버 측에서 매핑해서 인식해야 한다.

세션은 인증된 사용자의 정보를 임의의 토큰과 매핑하여 서버에 저장하고, 클라이언트에게 임의의 토큰(SESSION ID)을 응답 헤더에 넣어 전송한다.

하지만 서버에 데이터 저장량이 많아지므로 서버 메모리에 부담이 갈 수 있다.

쿠키와 세션 정리

가장 큰 차이점은 사용자의 정보가 저장되는 위치이다. 쿠키는 서버의 자원을 사용하지 않지만, 네트워크에 부담이 생길 수 있다. 반면 세션은 서버의 자원을 사용하여 서버 메모리에 부담이 갈 수 있지만, 네트워크에 부담이 가지 않는다. 보안 면에서는 세션이 더 우수하지만, 세션은 서버에서 처리하기 때문에 요청 속도는 쿠키가 더 빠르다.


2. HttpSession

HttpSession은 서블릿이 세션을 위해 제공하는 기능이다. 서블릿을 통해 HttpSession을 생성하면 JSESSIONID라는 이름과 랜덤 값으로 이루어진 쿠키가 생성된다.

@PostMapping("/login")
public String login(@Validated @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request) {
	//아이디, 패스워드가 비어있을 경우 오류(@Validated)
	if(bindingResult.hasErrors()) {
		return "memberView/loginForm";
	}

	Member loginMember = loginService.login(form.getLoginId(), form.getPassword());

	//아이디 혹은 패스워트가 틀린 경우 오류
	if(loginMember == null) {
		bindingResult.reject("loginFail", "아이디 또는 비밀번호가 틀립니다");
		return "memberView/loginForm";
	}

	//로그인 성공 처리
	HttpSession session = request.getSession(); //세션 생성
	session.setAttribute(LOGIN_MEMBER, loginMember); //세션에 로그인 회원 보관

	return "redirect:/main";
}

@PostMapping("/logout")
public String logout(HttpServletRequest request) {
	HttpSession session = request.getSession(false);
	if(session != null) {
		session.invalidate();
	}
	return "redirect:/main";
}
  • 세션을 생성하려면 request.getSession()을 사용하면 된다. 이때 create 옵션으로 true를 지정하면, 세션이 있으면 기존 세션을 반환하고 없으면 새로운 세션을 생성해서 반환한다. 반면 create 옵션을 false로 지정하면, 세션이 있으면 기존 세션을 반환하고 없으면 새로운 세션을 생성하지 않으며 null을 반환한다.

  • session.setAttribute(LOGIN_MEMBER, loginMember)을 통해 세션에 데이터(회원 정보)를 보관한다.

  • session.invalidate()를 통해 세션을 제거한다.


3. @SessionAttribute

스프링은 세션을 더 편리하게 사용할 수 있도록 @SessionAttribute를 지원한다. 이를 통해 세션을 찾고, 세션에 들어있는 데이터를 찾는 과정을 간소화할 수 있다. 참고로 이 기능은 새로운 세션을 생성하지 않는다.

@Controller
@RequiredArgsConstructor
public class HomeController {
    @GetMapping("/")
    public String home() {
        return "redirect:/main";
    }

    @GetMapping("/main")
    public String main(@SessionAttribute(name = LOGIN_MEMBER, required = false) Member member, Model model) {

        if(member == null) {
            return "main";
        }

        //세션이 유지되면 loginMain으로
        model.addAttribute("member", member);
        return "loginMain";
    }
}

4. 세션 타임아웃 설정

스프링 부트의 application.properties에 다음과 같이 설정해두면 된다. 참고로 기본 설정은 1800초(30분)이다.

server.servlet.session.timeout=60

만약 특정 세션에 대해서만 별도의 시간 설정을 하고자 한다면, 다음과 같이 특정 세선 단위로 시간 설정을 하면 된다.

session.setMaxInactiveInterval(1800);
profile
공부한 것들을 기록합니다.

0개의 댓글