Search
Duplicate

๋ฆฌ์Šค๋„ˆ (Listener)

๋ฆฌ์Šค๋„ˆ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์‹œ์ž ์—ญํ• ์„ ํ•˜๋ฉฐ, ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋‚˜ ์ƒํƒœ ๋ณ€ํ™”์— ์ž๋™์œผ๋กœ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค.

Listener๋ž€?

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์—์„œ ๋ฐœ์ƒํ•˜๋Š” ํŠน์ • ์ด๋ฒคํŠธ ์— ๋Œ€ํ•ด ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
โ€ข
์ด๋ฒคํŠธ (์˜ˆ: ์„ธ์…˜ ์ƒ์„ฑ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ๋“ฑ)
๋ฆฌ์Šค๋„ˆ๋Š” ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ(Tomcat ๋“ฑ)๊ฐ€ ์ž๋™์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

์ฃผ์š” Listener ์ข…๋ฅ˜

Listener ์ธํ„ฐํŽ˜์ด์Šค
๊ฐ์ง€ ๋Œ€์ƒ (์ด๋ฒคํŠธ)
์ฃผ ์‚ฌ์šฉ ๋ชฉ์ 
ServletContextListener
์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘/์ข…๋ฃŒ
์ดˆ๊ธฐ ์„ค์ •, ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ ๋“ฑ
HttpSessionListener
์„ธ์…˜ ์ƒ์„ฑ/์ข…๋ฃŒ
๋กœ๊ทธ์ธ ์ถ”์ , ์„ธ์…˜ ์ˆ˜ ๊ด€๋ฆฌ
ServletRequestListener
์š”์ฒญ ์‹œ์ž‘/์ข…๋ฃŒ
์š”์ฒญ ์‹œ๊ฐ„ ์ธก์ •, ๋กœ๊น… ๋“ฑ
HttpSessionAttributeListener
์„ธ์…˜ ์†์„ฑ ๋ณ€๊ฒฝ
๋กœ๊ทธ์ธ ์ •๋ณด ์ถ”์  ๋“ฑ
ServletContextAttributeListener
์ปจํ…์ŠคํŠธ ์†์„ฑ ๋ณ€๊ฒฝ
์ „์—ญ ์„ค์ • ๋ณ€๊ฒฝ ๊ฐ์‹œ
ServletRequestAttributeListener
์š”์ฒญ ์†์„ฑ ๋ณ€๊ฒฝ
๋””๋ฒ„๊น…, ๋กœ๊น… ๋“ฑ

1. ServletContextListener

์—ญํ• :

โ€ข
์›น ์•ฑ ์‹œ์ž‘/์ข…๋ฃŒ ์‹œ์ ์— ๋™์ž‘

์ฝ”๋“œ ์˜ˆ์‹œ:

@WebListener public class AppStartListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { System.out.println("๐ŸŒ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘๋จ"); } public void contextDestroyed(ServletContextEvent sce) { System.out.println("๐Ÿ›‘ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ข…๋ฃŒ๋จ"); } }
Java
๋ณต์‚ฌ

2. HttpSessionListener

์—ญํ• :

โ€ข
์„ธ์…˜ ์ƒ์„ฑ/์ข…๋ฃŒ ๊ฐ์ง€ (๋กœ๊ทธ์ธ ์ƒํƒœ ๋“ฑ ์ถ”์ )

์ฝ”๋“œ ์˜ˆ์‹œ:

@WebListener public class SessionTracker implements HttpSessionListener { public void sessionCreated(HttpSessionEvent se) { System.out.println("๐ŸŸข ์„ธ์…˜ ์ƒ์„ฑ๋จ: " + se.getSession().getId()); } public void sessionDestroyed(HttpSessionEvent se) { System.out.println("๐Ÿ”ด ์„ธ์…˜ ์ข…๋ฃŒ๋จ: " + se.getSession().getId()); } }
Java
๋ณต์‚ฌ

3. ServletRequestListener

์—ญํ• :

โ€ข
HTTP ์š”์ฒญ์˜ ์‹œ์ž‘/์ข…๋ฃŒ ๊ฐ์ง€

์ฝ”๋“œ ์˜ˆ์‹œ:

@WebListener public class RequestLogger implements ServletRequestListener { public void requestInitialized(ServletRequestEvent sre) { System.out.println("โžก๏ธ ์š”์ฒญ ์‹œ์ž‘๋จ: " + ((HttpServletRequest) sre.getServletRequest()).getRequestURI()); } public void requestDestroyed(ServletRequestEvent sre) { System.out.println("โฌ…๏ธ ์š”์ฒญ ์ข…๋ฃŒ๋จ"); } }
Java
๋ณต์‚ฌ

๋ฆฌ์Šค๋„ˆ ๋“ฑ๋ก ๋ฐฉ๋ฒ•

1.
์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ (@WebListener) โ†’ ์ตœ์‹  ๋ฐฉ์‹
2.
web.xml์— ๋“ฑ๋ก โ†’ ์ „ํ†ต ๋ฐฉ์‹
<!-- web.xml ๋ฐฉ์‹ ์˜ˆ์‹œ --> <listener> <listener-class>com.example.MyListener</listener-class> </listener>
XML
๋ณต์‚ฌ

์‚ฌ์šฉ ์˜ˆ

์‹œ๋‚˜๋ฆฌ์˜ค
ํ™œ์šฉํ•  ๋ฆฌ์Šค๋„ˆ
์›น ์•ฑ ์‹œ์ž‘ ์‹œ DB ์—ฐ๊ฒฐ ํ’€ ์ƒ์„ฑ
ServletContextListener
์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ์ˆ˜ ์นด์šดํŒ…
HttpSessionListener
์š”์ฒญ ๋กœ๊ทธ ๊ธฐ๋ก
ServletRequestListener
๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์ •๋ณด ์ถ”์ 
HttpSessionAttributeListener
์ „์—ญ ์„ค์ • ๋ณ€๊ฒฝ ๊ฐ์‹œ
ServletContextAttributeListener

์ •๋ฆฌ

๋ฆฌ์Šค๋„ˆ ์ข…๋ฅ˜
๊ฐ์ง€ ์‹œ์ 
ServletContextListener
์›น ์•ฑ ์‹œ์ž‘/์ข…๋ฃŒ
HttpSessionListener
์„ธ์…˜ ์ƒ์„ฑ/์ข…๋ฃŒ
ServletRequestListener
์š”์ฒญ ์‹œ์ž‘/์ข…๋ฃŒ
์†์„ฑ ๊ด€๋ จ ๋ฆฌ์Šค๋„ˆ๋“ค
์†์„ฑ ์ถ”๊ฐ€/๋ณ€๊ฒฝ/์‚ญ์ œ ์‹œ์ 

์‹ค์‹œ๊ฐ„ ์ ‘์†์ž ์ˆ˜

์„ธ์…˜ ๋ฆฌ์Šค๋„ˆ๋กœ ์‹ค์‹œ๊ฐ„ ์ ‘์†์ž ์ˆ˜ ๊ตฌํ˜„

์„ธ์…˜์ด ์ƒ์„ฑ๋˜๊ณ  ์ข…๋ฃŒ๋  ๋•Œ๋งˆ๋‹ค ์ ‘์†์ž ์ˆ˜๋ฅผ ์นด์šดํŒ…ํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SessionCountListener ๊ตฌํ˜„

@WebListener public class SessionCountListener implements HttpSessionListener { private static int activeSessions = 0; public void sessionCreated(HttpSessionEvent se) { activeSessions++; ServletContext context = se.getSession().getServletContext(); context.setAttribute("activeSessions", activeSessions); System.out.println("๐ŸŸข ์„ธ์…˜ ์ƒ์„ฑ | ํ˜„์žฌ ์ ‘์†์ž ์ˆ˜: " + activeSessions); } public void sessionDestroyed(HttpSessionEvent se) { activeSessions--; ServletContext context = se.getSession().getServletContext(); context.setAttribute("activeSessions", activeSessions); System.out.println("๐Ÿ”ด ์„ธ์…˜ ์ข…๋ฃŒ | ํ˜„์žฌ ์ ‘์†์ž ์ˆ˜: " + activeSessions); } public static int getActiveSessions() { return activeSessions; } }
Java
๋ณต์‚ฌ

Servlet์—์„œ ์ ‘์†์ž ์ˆ˜ ์กฐํšŒ

@WebServlet("/visitor-count") public class VisitorCountServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ServletContext์—์„œ ์ ‘์†์ž ์ˆ˜ ๊ฐ€์ ธ์˜ค๊ธฐ int count = (int) getServletContext().getAttribute("activeSessions"); response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<h1>ํ˜„์žฌ ์ ‘์†์ž ์ˆ˜: " + count + "๋ช…</h1>"); } }
Java
๋ณต์‚ฌ

JSP์—์„œ ์ ‘์†์ž ์ˆ˜ ํ‘œ์‹œ

<%@ page language="java" contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <title>์‹ค์‹œ๊ฐ„ ์ ‘์†์ž</title> </head> <body> <h2>๐ŸŒ ํ˜„์žฌ ์ ‘์†์ž ์ˆ˜</h2> <p>์ ‘์† ์ค‘์ธ ์‚ฌ์šฉ์ž: <strong>${applicationScope.activeSessions}</strong>๋ช…</p> </body> </html>
XML
๋ณต์‚ฌ

๋™์ž‘ ์›๋ฆฌ

โ€ข
์„ธ์…˜ ์ƒ์„ฑ ์‹œ: sessionCreated()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด activeSessions ์ฆ๊ฐ€
โ€ข
์„ธ์…˜ ์ข…๋ฃŒ ์‹œ: sessionDestroyed()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด activeSessions ๊ฐ์†Œ
โ€ข
ServletContext์— ์ €์žฅ: ์ „์—ญ ๋ฒ”์œ„์—์„œ ์ ‘์†์ž ์ˆ˜ ๊ณต์œ 
โ€ข
JSP/Servlet์—์„œ ์กฐํšŒ: ${applicationScope.activeSessions} ๋˜๋Š” getAttribute()๋กœ ์ ‘๊ทผ

๋™์‹œ ์ ‘์† ์ œํ•œ

๋™์‹œ ์ ‘์† ์ œํ•œ ๊ตฌํ˜„ (์ตœ๋Œ€ 3๊ฐœ ์„ธ์…˜)

๋™์ผํ•œ ์‚ฌ์šฉ์ž ID๊ฐ€ 3๊ฐœ ์ด์ƒ์˜ ์„ธ์…˜์œผ๋กœ ์ ‘์†ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

SessionLimitListener ๊ตฌํ˜„

@WebListener public class SessionLimitListener implements HttpSessionListener, HttpSessionAttributeListener { // ์‚ฌ์šฉ์ž๋ณ„ ์„ธ์…˜ ๋ชฉ๋ก ์ €์žฅ (userId โ†’ List<HttpSession>) private static Map<String, List<HttpSession>> userSessions = new ConcurrentHashMap<>(); private static final int MAX_SESSIONS = 3; @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("๐ŸŸข ์„ธ์…˜ ์ƒ์„ฑ: " + se.getSession().getId()); } @Override public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); String userId = (String) session.getAttribute("userId"); if (userId != null) { List<HttpSession> sessions = userSessions.get(userId); if (sessions != null) { sessions.remove(session); if (sessions.isEmpty()) { userSessions.remove(userId); } System.out.println("๐Ÿ”ด ์„ธ์…˜ ์ข…๋ฃŒ: " + userId + " | ๋‚จ์€ ์„ธ์…˜: " + sessions.size()); } } } @Override public void attributeAdded(HttpSessionBindingEvent event) { if ("userId".equals(event.getName())) { String userId = (String) event.getValue(); HttpSession newSession = event.getSession(); // ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜ ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ List<HttpSession> sessions = userSessions.computeIfAbsent(userId, k -> new ArrayList<>()); // ์ด๋ฏธ 3๊ฐœ ์ด์ƒ์ด๋ฉด ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์„ธ์…˜ ๊ฐ•์ œ ์ข…๋ฃŒ if (sessions.size() >= MAX_SESSIONS) { HttpSession oldestSession = sessions.get(0); oldestSession.invalidate(); System.out.println("โš ๏ธ ์ตœ๋Œ€ ์ ‘์† ์ดˆ๊ณผ | ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์„ธ์…˜ ์ข…๋ฃŒ: " + oldestSession.getId()); } // ์ƒˆ ์„ธ์…˜ ์ถ”๊ฐ€ sessions.add(newSession); System.out.println("โœ… ์‚ฌ์šฉ์ž '" + userId + "' ๋กœ๊ทธ์ธ | ํ˜„์žฌ ์„ธ์…˜ ์ˆ˜: " + sessions.size()); } } @Override public void attributeRemoved(HttpSessionBindingEvent event) { // ๋กœ๊ทธ์•„์›ƒ ์‹œ ์ฒ˜๋ฆฌ } @Override public void attributeReplaced(HttpSessionBindingEvent event) { // ์†์„ฑ ๋ณ€๊ฒฝ ์‹œ ์ฒ˜๋ฆฌ } }
Java
๋ณต์‚ฌ

๋กœ๊ทธ์ธ Servlet์—์„œ userId ์„ค์ •

@WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userId = request.getParameter("userId"); String password = request.getParameter("password"); // ๋กœ๊ทธ์ธ ๊ฒ€์ฆ (๊ฐ„๋‹จ ์˜ˆ์‹œ) if (userId != null &amp;&amp; !userId.isEmpty()) { // ์„ธ์…˜์— userId ์ €์žฅ โ†’ ๋ฆฌ์Šค๋„ˆ๊ฐ€ ์ž๋™์œผ๋กœ ๊ฐ์ง€ request.getSession().setAttribute("userId", userId); response.sendRedirect("main.jsp"); } else { response.sendRedirect("login.jsp?error=1"); } } }
Java
๋ณต์‚ฌ

๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ (login.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>๋กœ๊ทธ์ธ</title> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f0f0f0; } .login-container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); width: 300px; } h2 { text-align: center; color: #333; } input[type="text"], input[type="password"] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; } button { width: 100%; padding: 10px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background-color: #45a049; } .error { color: red; text-align: center; margin-top: 10px; } </style> </head> <body> <div class="login-container"> <h2>๐Ÿ” ๋กœ๊ทธ์ธ</h2> <form action="login" method="post"> <input type="text" name="userId" placeholder="์•„์ด๋””" required> <input type="password" name="password" placeholder="๋น„๋ฐ€๋ฒˆํ˜ธ" required> <button type="submit">๋กœ๊ทธ์ธ</button> </form> <% if (request.getParameter("error") != null) { %> <p class="error">โš ๏ธ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.</p> <% } %> <% if (request.getParameter("limit") != null) { %> <p class="error">โš ๏ธ ์ตœ๋Œ€ ์ ‘์† ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•˜์—ฌ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์„ธ์…˜์ด ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.</p> <% } %> </div> </body> </html>
XML
๋ณต์‚ฌ

IP ๊ธฐ๋ฐ˜ ์ œํ•œ (์„ ํƒ ์‚ฌํ•ญ)

PC๋‚˜ IP ๊ธฐ๋ฐ˜์œผ๋กœ ์ œํ•œํ•˜๋ ค๋ฉด userId ๋Œ€์‹  IP ์ฃผ์†Œ๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
@Override public void sessionCreated(HttpSessionEvent se) { HttpSession session = se.getSession(); // IP ์ฃผ์†Œ ๊ฐ€์ ธ์˜ค๊ธฐ ServletRequest request = ...; // ์‹ค์ œ๋กœ๋Š” Filter์—์„œ ์ฒ˜๋ฆฌ ํ•„์š” String ipAddress = request.getRemoteAddr(); session.setAttribute("ipAddress", ipAddress); }
Java
๋ณต์‚ฌ

๋™์ž‘ ํ๋ฆ„

1.
๋กœ๊ทธ์ธ ์‹œ: userId๊ฐ€ ์„ธ์…˜์— ์ €์žฅ๋จ โ†’ attributeAdded() ํ˜ธ์ถœ
2.
์„ธ์…˜ ์ˆ˜ ํ™•์ธ: ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜์ด 3๊ฐœ ์ด์ƒ์ด๋ฉด ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์„ธ์…˜ ๊ฐ•์ œ ์ข…๋ฃŒ
3.
์ƒˆ ์„ธ์…˜ ์ถ”๊ฐ€: ํ˜„์žฌ ์„ธ์…˜์„ ์‚ฌ์šฉ์ž๋ณ„ ์„ธ์…˜ ๋ชฉ๋ก์— ์ถ”๊ฐ€
4.
๋กœ๊ทธ์•„์›ƒ/์„ธ์…˜ ๋งŒ๋ฃŒ: sessionDestroyed()์—์„œ ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ

์ฃผ์˜์‚ฌํ•ญ

โ€ข
ConcurrentHashMap ์‚ฌ์šฉ: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌ
โ€ข
๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์„ธ์…˜ ์ข…๋ฃŒ: sessions.get(0)์ด ๊ฐ€์žฅ ๋จผ์ € ์ถ”๊ฐ€๋œ ์„ธ์…˜
โ€ข
IP ๊ธฐ๋ฐ˜ ์ œํ•œ ์‹œ: ๋™์  IP ํ™˜๊ฒฝ์—์„œ๋Š” ์ œํ•œ์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Œ
โ€ข
PC ์‹๋ณ„: ์™„์ „ํ•œ PC ์‹๋ณ„์€ ์–ด๋ ค์šฐ๋ฏ€๋กœ IP + User-Agent ์กฐํ•ฉ ์‚ฌ์šฉ ๊ถŒ์žฅ