Contents
Servlet으로 Session 사용하기
   Apr 13, 2023     5 min read

서블릿 HTTP 세션1

⚓️서론

서블릿은 세션 기능을위해 HttpSession 을 제공한다.

앞에서 세션을 직접 만들어서 사용했지만, 여기서는 HttpSession을 사용하면 고생을 덜어준다.

직접 구현한 것보다 더 좋다.


HttpSession

서블릿에서 제공하는 HttpSession 는 앞서 해왔던 SessionManager 와 비슷한 방식으로 동작한다.

➡️SessionManager

  • 세션 생성 : UUID값 생성 → SessionStore에 put → 쿠키 생성
  • 세션 조회
  • 세션 만료
@Component
public class SessionManager {
    public static final String SESSION_COOKIE_NAME = "mySessionId";

    private Map<String, Object> sessionStore = new ConcurrentHashMap<>();

    /**
     * 세션 생성
     */
    public void createSession(Object value, HttpServletResponse response) {

        //세션 id를 생성하고, 값을 세션에 저장
        String sessionId = UUID.randomUUID().toString(); // UUID 만들기
        sessionStore.put(sessionId, value);

        //쿠키 생성
        Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId); // Cookie(String name, String value)
        response.addCookie(mySessionCookie); // response에 쿠키를 넣어준다.
    }

    /**
     * 세션 조회
     */
    public Object getSession(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
        if (sessionCookie == null) {
            return null;
        }
        return sessionStore.get(sessionCookie.getValue());
    }

    /**
     * 세션 만료
     */
    public void expire(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
        if (sessionCookie != null) {
            sessionStore.remove(sessionCookie.getValue());
        }
    }

    public Cookie findCookie(HttpServletRequest request, String cookieName) {
        if (request.getCookies() == null) {
            return null;
        }

        return Arrays.stream(request.getCookies()) // 배열을 스트림으로 바꿔준다.
                .filter(cookie -> cookie.getName().equals(cookieName)) //  Loop를 돌리면서 쿠키가 같은지 확인
                .findAny()
                .orElse(null);
    }
}

➡️위와 같은 방식 말고 서블릿에서 제공하는 방법으로 하게된다면?

  • SessionManager가 아닌 HttpSession 으로 세션 기능 구현

서블릿으로 세션을 생서성 쿠키가 생성되는데 쿠키의 이름은 JSESSIONID 이고, 값은 추정 불가능한 랜덤 값이다.

Cookie : JESSIONID = 추정불가한 랜덤값

  • SessionConst : HttpSession에 데이터를 보관하고 조회할 때 , 같은 이름이 중복 되어 사용되므로 상수를 하나 정의했다.
public interface SessionConst {

    String LOGIN_MEMBER = "loginMember";
}
  • loginController
    • request.getSession(true)
      • 세션이 있으면 기존 세션을 반환한다.
      • 세션이 없으면 새로운 세션을 생성해서 반환한다.
    • request.getSession(false)
      • 세션이 있으면 기존 세션을 반환한다.
      • 세션이 없으면 새로운 세션을 생성하지 않는다. → null 을 반환한다.
    • session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
      • 세션에 데이터를 보관하는 방법은 request.setAttribute(...)와 비슷하다. 하나의 세션에 여러 값을 저장할 수 있음.
/**
  * 로그인 세션 HttpSession으로 처리하기
  * @param form
  * @param bindingResult
  * @param request
  * @return
*/
@PostMapping("/login")
public String loginV3(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request) {
    if (bindingResult.hasErrors()) {
        return "login/loginForm";
    }

    Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
    log.info("login? {}", loginMember);

    if (loginMember == null) {
        bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
        return "login/loginForm";
    }

    //로그인 성공 처리

    //세션이 있으면 있는 세션 변환, 없으면 신규 세션 생성
    HttpSession session = request.getSession(); // 세션을 생성하려면 -> true (defalut)

    //세션에 로그인 회원 정보 보관
    session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
    return "redirect:/";
}
  • logout - 로그아웃
    • invalidate 는 세션과 그 안에 데이터를 지워준다.
/**
 * 로그인 처리 - 세션으로 로그아웃 처리 (세션 만료)
 *
 * @param request
 * @return
 */
@PostMapping("/logout")
public String logoutV2(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if(session != null){
        session.invalidate();
    }
    return "redirect:/";
}
  • HomeController
    • request.getSession(false); 세션을 생성할 의도가 없기 떄문에 false
@GetMapping("/")
public String homeLoginV3(HttpServletRequest request, Model model) {

    //세션이 없으면 home
    HttpSession session = request.getSession(false); //false 세션 안만들기 때문에
    if (session == null) {
        return "home";
    }

    Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);

    //세션에 회원 데이터가 없으면 home화면으로 이동
    if (loginMember == null) {
        return "home";
    }

    //세션이 유지되면 로그인으로 이동
    model.addAttribute("member", loginMember);
    return "loginHome";
}
  • 결과 - JSESSIONID

Untitled


📎참고