server.servlet.session.tracking-modes=cookie
쿠키(idCookie)를 서버 응답 객체(HttpServletResponse) 에 addCookie를 이용해 담아준다. 그럼 실제로 웹 브라우저에서는 Set-Cookie 프로퍼티에 쿠키정보가 담겨져 반환	@PostMapping("/login")
	public String login(@ModelAttribute LoginForm form, Model model, 
			RedirectAttributes redirectAttributes, HttpServletResponse response) {
		
		Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
		if(loginMember == null) {
			// 로그인 실패
			model.addAttribute("msg", "로그인 실패");
			return "login/loginForm";
		}
		
		// 로그인 성공
        //쿠키에 시간 정보를 주지 않으면 세션 쿠키가 된다. (브라우저 종료시 모두 종료)
		Cookie idCookie = new Cookie("memberId",String.valueOf(loginMember.getId()) );
		response.addCookie(idCookie);
		
		redirectAttributes.addFlashAttribute("msg","로그인성공");
		return "redirect:/";
		
	}
key가 memberId인 쿠키값을 찾아 memberId 변수에 할당해준다. required가 false이기에 쿠키정보가 없는 비회원도 접근 가능하다. 	private final MemberRepository memberRepository;
    
	@GetMapping
	public String homeV2(@CookieValue(name = "memberId", required = false)Long memberId,
			Model model) {
		
		// 로그인한 사용자가 아니라면 home으로 보낸다.
		if(memberId == null) {
			return "home";
		}
		
		// db조회
		Member loginMember = memberRepository.findById(memberId);
		// 사용자가 없으면 null 처리 필요
		if(loginMember == null) {
			return "home";
		}
		
		// loginHome : 로그인에 성공한 사람만이 볼 수 있는 화면
		model.addAttribute("member",loginMember);
		return "loginHome";
	}
<h4 class="mb-3" th:text="|로그인 : ${member.name}|">로그인 사용자 이름</h4>
		<hr class="my-4">
		<div class="row">
			<div class="col">
				<button class="w-100 btn btn-secondary btn-lg" type="button"
					th:onclick="|location.href='@{/items}'|">상품 관리</button>
			</div>
			<div class="col">
				<form method="post" th:action="@{/logout}">
					<button class="w-100 btn btn-dark btn-lg"
						onclick="location.href='items.html'" type="submit">
						로그아웃
					</button>
				</form>
			</div>
		</div>
@PostMapping("/logout")
	public String logout(HttpServletResponse response) {
		Cookie cookie = new Cookie("memberId", null);
		// 쿠키 시간설정
		cookie.setMaxAge(0);
		response.addCookie(cookie);
		return "redirect:/";
	}	
key/value로 저장한 뒤 브라우저에서는 key값만 가지고 있도록 하는 것이다.  이 개념을 그림으로 표현하면 다음과 같다. key값을 한꺼번에 class에 정의해 놓는 역할만 하는 class
HttpSession session = request.getSession(true);를 하게되면
사용자 kim이 접속해도session_kim(kim에 대한 세션) 이 생성되고,
사용자 jang이 접속해도session_jang(jang에 대한 세션) 이 생성되어서
session.getAttribute(SessionConst.LOGIN_MEMBER);을 하게 되면
사용자 kim은session_kim.getAttribute(SessionConst.LOGIN_MEMBER);
사용자 jangsession_jang.getAttribute(SessionConst.LOGIN_MEMBER);
을 수행하는거라서 충돌이 발생하지 않는다
- 사용자 kim이 로그인 요청
 - 서버는 Session을 생성하고 생성한 SessionId를 쿠키에 담아서 클라이언트에게 전송
 - 클라이언트 요청시 쿠키에 담긴 SessionId를 서버에 전송
 - 서버는 Session 저장소에서 SessionId에 맞는 Session을 찾음
 - 찾은 Session에서 해당 키값(SessionConst.LOGIN_MEMBER)에 맞는 객체(Member) 반환
 
public class SessionConst {
	public static final String LOGIN_MEMBER = "loginMember";
}
request.getSession(true);
request.getSession(false);
인수를 전달하지 않을 경우 기본 값으로 true이다. 
session.invalidate();
@PostMapping("/login")
	public String loginV2(@ModelAttribute LoginForm form, Model model, 
			RedirectAttributes redirectAttributes, HttpServletRequest request) {
		
		Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
		if(loginMember == null) {
			// 로그인 실패
			model.addAttribute("msg", "로그인 실패");
			return "login/loginForm";
		}
		
		// 로그인 성공
        // session변수에 요청온거에서 getSession 획득
		HttpSession session = request.getSession();
		// 세션에 로그인 회원 정보 보관
		session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
		redirectAttributes.addFlashAttribute("msg","로그인성공");
		return "redirect:/";
		
	}
    
    @PostMapping("/logout")
	public String logoutV2(HttpServletRequest request) {
		// 세션을 삭제
		HttpSession session = request.getSession(false);
		if(session != null) {
			session.invalidate();
		}
		return "redirect:/";
	}
@CookieValue와 비슷하다. 클라이언트로부터 전달받은 내용의 세션중에서 key가 일치하는게 있는지 찾는다. required가 false이니 만약 못찾으면 null이 할당될 것이다// @GetMapping
	public String homeV3(HttpServletRequest request ,Model model) {
		HttpSession session = request.getSession(false);
		
		// 로그인한 사용자가 아니라면 home으로 보낸다.
		if(session == null) {
			return "home";
		}
		Member loginMember = (Member)session.getAttribute(SessionConst.LOGIN_MEMBER);
		
		// 사용자가 없으면 null 처리 필요
		if(loginMember == null) {
			return "home";
		}
		
		// loginHome : 로그인에 성공한 사람만이 볼 수 있는 화면
		model.addAttribute("member",loginMember);
		return "loginHome";
	}
    
// session attribute 사용
@GetMapping
	public String homeV4(
			// session attribute를 뒤져서 member에 값을 넣어준다.
			@SessionAttribute(name=SessionConst.LOGIN_MEMBER,required = false)Member loginMember
			,Model model) {
		
		// 사용자가 없으면 null 처리 필요
		if(loginMember == null) {
			return "home";
		}
		
		// loginHome : 로그인에 성공한 사람만이 볼 수 있는 화면
		model.addAttribute("member",loginMember);
		return "loginHome";
	}
- 쿠키를 가지고 로그인 상태를 관리하는것은 코드도 복잡해지고 보안상 취약하다.
 
- 중요한 정보는 클라이언트에 노출시켜선 안되고 서버에서 관리해야 한다.
 
- 중요 정보는 서버에서 관리하며 정보에 접근할 추리불가능하고 중복이 되지않는 키를 이용해 서버와 클라이언트를 연결하도록 하며 이를 세션이라 한다.