웹에서 “로그인 상태”를 만든다는 건 결국 서버가 사용자를 기억하는 기준을 하나 정하는 것이다.
이 구현에서는 그 기준을 세션(session) 으로 잡는다.
핵심은 단순하다.
- 로그인 성공하면 sessionScope.user에 사용자 객체를 저장한다
- 로그아웃하면 세션을 무효화(invalidate)한다
- 화면(JSP)은 sessionScope.user 존재 여부로 메뉴를 분기한다
아래는 그 요구사항을 코드 변경 흐름으로 정확히 정리한 내용이다.
로그인 성공 시 세션에 사용자 저장 (로그인 상태의 기준 만들기)
왜 세션에 저장하나?
HTTP는 기본적으로 무상태(stateless) 이다.
즉, 요청이 끝나면 서버는 “누가 방금 요청했는지”를 기억하지 않는다.
그래서 로그인 후에도 다음 요청에서 로그인 상태를 유지하려면 서버 쪽에 “기억 장치”가 필요하고, 그게 세션이다.
이 구현에서 세션에 user가 존재하는 것 = 로그인 상태다.
LoginServlet 핵심 변경 코드
User user = DataBase.findByUser(userId);
if (user == null || !user.getPassword().equals(password)) {
resp.sendRedirect("/user/login_failed.jsp");
return;
}
// 로그인 성공 -> 세션에 로그인 정보 저장
HttpSession session = req.getSession();
session.setAttribute("user", user);
resp.sendRedirect("/");
흐름
- DataBase.findByUser(userId)로 사용자 조회
- 사용자 없거나 비밀번호 틀리면 로그인 실패 페이지로 redirect
- 성공이면 req.getSession()으로 세션을 얻는다
- 없으면 새로 만든다
- 있으면 기존 것을 가져온다
- session.setAttribute("user", user)로 “로그인한 사용자”를 세션에 저장
- 홈(/)으로 redirect
중요 포인트
- 로그인 성공 후 redirect를 사용한다
로그인은 “상태 변경(세션 저장)”이 발생하는 작업이고, 새로고침 중복 처리 등도 고려하면 redirect 흐름이 자연스럽다. - 이후 JSP/서블릿 어디서든 session.getAttribute("user")로 로그인 여부를 판단할 수 있다.
로그아웃 서블릿 추가: 세션 무효화로 로그인 상태 해제
로그아웃의 본질
로그아웃은 “사용자 정보를 지운다”가 아니라 더 정확히 말하면,
서버가 가지고 있던 “이 브라우저의 로그인 상태(세션)”를 제거하는 것
이 구현에서는 세션 전체를 무효화하는 방식으로 처리한다.
LogoutServlet 추가 코드
@WebServlet("/user/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
HttpSession session = req.getSession(false);
if (session != null) {
session.invalidate();
}
resp.sendRedirect("/");
}
}
흐름
- req.getSession(false)가 핵심이다.
- false = “세션 없으면 새로 만들지 마라”
- 로그아웃 요청 자체 때문에 새 세션이 생기면 이상하니까 이게 맞다.
- 세션이 존재하면 invalidate()로 완전 무효화한다.
- 세션에 담긴 user 포함 모든 attribute가 사라진다.
- 처리 후 홈으로 redirect
메뉴 분기: 로그인 상태에 따라 다른 메뉴 노출
로그인 상태를 “세션에 user가 있냐 없냐”로 잡았으니,
화면에서도 그 기준으로 분기하면 된다.
subnav.jsp 핵심 변경 코드
<c:if test="${empty sessionScope.user}">
<li><a href="/user/login.jsp" role="button">로그인</a></li>
<li><a href="/user/form.jsp" role="button">회원가입</a></li>
</c:if>
<c:if test="${not empty sessionScope.user}">
<li><a href="/user/logout" role="button">로그아웃</a></li>
<li><a href="/user/updateForm?userId=${sessionScope.user.userId}" role="button">개인정보수정</a></li>
</c:if>
중요
(1) sessionScope.user
JSP EL에서 sessionScope는 세션 영역을 의미한다.
즉, 아래와 같은 의미다.
- 자바로 치면: `session.getAttribute("user")`
(2) `${empty ...}` / `${not empty ...}`
- empty는 null이거나 비어있으면 true다.
- 즉, 세션에 user가 없으면 “로그인/회원가입”
- 세션에 user가 있으면 “로그아웃/개인정보수정”
로그인 페이지 이동 경로 정리 (.html → .jsp)
변경 이유
이 프로젝트에서는 화면이 JSP 기반으로 구성된다.
즉, “로그인 화면”도 JSP여야 자연스럽다.
그래서 아래처럼 정리한다.
- 기존: `login.html`
- 변경: `login.jsp`
`LoginServlet`에서도 로그인 실패/성공 후 이동 경로가 이 규칙에 맞게 정리돼야 한다.
링크 경로 통일: 화면은 .jsp, 기능은 서블릿 URL
이 단계에서 전체 링크 규칙을 통일한다.
화면(View) → .jsp
- login.jsp
- form.jsp
- 기타 화면들
기능(Action) → 서블릿 매핑 URL
- `/user/logout`
- `/user/updateForm?userId=...` (updateForm 서블릿이 처리)
이렇게 분리하면 구조가 명확해진다.
- JSP는 “보여주기”
- 서블릿은 “처리하기(세션/DB/로직)”
요약
이 변경들이 요구사항을 어떻게 만족시키는지 한 줄씩 매핑하면 다음과 같다.
- 로그인 성공 시 세션에 user 저장
→ sessionScope.user 존재 여부로 로그인 상태 판단 가능 - 로그아웃 클릭 시 세션 제거
→ invalidate()로 로그인 상태 완전 해제 - 메뉴는 세션 존재 여부로 분기
→ 로그인/회원가입 ↔ 로그아웃/개인정보수정 자동 전환 - 링크/경로 통일
→ 화면은 .jsp, 기능은 /user/logout 같은 서블릿 엔드포인트로 정리
출처 : 《자바 웹 프로그래밍 Next Step》, 박재성, 로드북
'Book > 자바 웹 프로그래밍 Next Step' 카테고리의 다른 글
| 6장_ : 쿠키와 세션 (0) | 2026.02.07 |
|---|---|
| 6장_ 요구사항4 : 회원 목록 및 개인정보 수정 보안 강화 (0) | 2026.02.07 |
| 6장_ 요구사항1: 개인정보 수정 (0) | 2026.02.06 |
| 6장_ : ListUser 화면 구현 (0) | 2026.02.06 |
| 6장_ : ListUSerServlet 구현 (0) | 2026.02.06 |
