좋아~! 그럼 JSP 전체 프로젝트 구조를 다중 로그인 방지 + 세션 관리 + 로그아웃 + 카운트다운 + 사용자 표시 + 에러 메시지 기능 위주로 DB 없이 파일 기반 or 메모리 기반으로 구성해서 zip 구조처럼 정리해줄게! 💼
JSPLoginProject/
│
├── WebContent/
│ ├── index.jsp ← 메인페이지 (로그인 링크)
│ ├── login.jsp ← 로그인 폼 + 에러 메시지
│ ├── loginProcess.jsp ← 로그인 처리 + 다중 로그인 방지
│ ├── logout.jsp ← 로그아웃 처리 + 로그 기록
│ ├── logoutDone.jsp ← 로그아웃 완료 메시지 + 시간 표시
│ ├── sessionExpired.jsp ← 세션 타임아웃 안내
│ ├── main.jsp ← 로그인 후 접근 가능 / 사용자 표시 / 카운트다운
│ ├── logs/
│ │ └── access_log.txt ← 로그 파일 저장 위치 (자동 생성됨)
│
├── WEB-INF/
│ ├── web.xml ← 세션 타임아웃 설정 (예: 5분)
web.xml (세션 타임아웃 설정)<web-app>
<session-config>
<session-timeout>5</session-timeout> <!-- 5분 -->
</session-config>
</web-app>
login.jsp (로그인 폼 + 에러 처리)<% String error = request.getParameter("error"); %>
<% if ("1".equals(error)) { %><p style="color:red;">❌ 아이디 또는 비밀번호 오류</p><% } %>
<% if ("alreadyLoggedIn".equals(error)) { %><p style="color:red;">🚫 이미 로그인 중입니다</p><% } %>
<form method="post" action="loginProcess.jsp">
ID: <input name="userId"><br>
PW: <input name="password" type="password"><br>
<button type="submit">로그인</button>
</form>
loginProcess.jsp (다중 로그인 방지 + 세션 등록)<%@ page import="java.util.*, javax.servlet.http.*" %>
<%
String userId = request.getParameter("userId");
String password = request.getParameter("password");
if ("jang".equals(userId) && "1234".equals(password)) {
Map<String, HttpSession> userMap = (Map<String, HttpSession>) application.getAttribute("userMap");
if (userMap == null) {
userMap = new HashMap<>();
application.setAttribute("userMap", userMap);
}
if (userMap.containsKey(userId)) {
HttpSession oldSession = userMap.get(userId);
try { oldSession.invalidate(); } catch(Exception e) {}
}
session.setAttribute("userId", userId);
userMap.put(userId, session);
response.sendRedirect("main.jsp");
} else {
response.sendRedirect("login.jsp?error=1");
}
%>
main.jsp (로그인 성공 후 메인 + 사용자 표시 + 카운트다운)<%
String userId = (String)session.getAttribute("userId");
if (userId == null) { response.sendRedirect("sessionExpired.jsp"); return; }
%>
<h2>👋 <%= userId %>님, 환영합니다!</h2>
<p id="countdown"></p>
<a href="logout.jsp">🚪 로그아웃</a>
<script>
let remaining = 300;
function updateTimer() {
let min = Math.floor(remaining / 60), sec = remaining % 60;
document.getElementById("countdown").innerText = `세션 만료까지 ${min}분 ${sec}초`;
if (--remaining > 0) setTimeout(updateTimer, 1000);
else window.location.href = "sessionExpired.jsp";
}
updateTimer();
</script>
logout.jsp (파일 로그 저장 + 세션 무효화)<%@ page import="java.io.*, java.text.SimpleDateFormat", java.util.* %>
<%
String userId = (String) session.getAttribute("userId");
String path = application.getRealPath("/logs/access_log.txt");
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
String log = userId + "님 로그아웃 (" + time + ")\n";
FileWriter fw = new FileWriter(path, true); fw.write(log); fw.close();
Map<String, HttpSession> userMap = (Map<String, HttpSession>) application.getAttribute("userMap");
if (userMap != null) userMap.remove(userId);
session.invalidate();
response.sendRedirect("logoutDone.jsp");
%>
logoutDone.jsp (완료 메시지)<h2>📝 로그아웃 완료!</h2>
<a href="login.jsp">다시 로그인</a>
sessionExpired.jsp (타임아웃 안내)<h2>⏰ 세션이 만료되었습니다!</h2>
<p>다시 로그인 해주세요.</p>
<a href="login.jsp">로그인 페이지로 이동</a>
logs/ 폴더는 직접 만들어야 해 (WebContent/logs)ID: jang / PW: 1234 (변경 가능)필요하면 이걸 .zip 파일로 내보낼 수 있는 템플릿 구조로 정리해줄게.
혹시 이 구조 그대로 실습 진행할 거야? 아니면 DB 연동할 준비되면 DB버전도 같이 해줄게!
😊 다음 단계로 어디 가볼까?