주요글: 도커 시작하기
반응형
접속 중인 사용자 리스트의 실질적인 구현 방법을 알아본다.

접속 중인 사용자 리스트 구현

접속 중인 사용자 리스트를 구현하기 위해서는 간단한 클래스를 하나 따로 만드는 것이 편하다. 이 클래스의 이름을 LoginUserList 클래스라고 붙인다. 이제 몇가지 가정을 생각해 본다. 접속 중인 사용자 리스트를 구현할 필요가 있는 것은 몇가지 용도가 있기 때문이다. 예를 들면 어떤 특정 사용자가 접속 중인지도 알 수 있고, 현재 접속 중인 사용자가 몇 명이지도 알 수 있으며 각각의 사용자에 대한 로그인/아웃 기록도 남길 수 있다.

이제 접속 중인 사용자 리스트를 어떻게 관리할 것인가를 생각해 본다. Vector 클래스를 사용해 리스트를 유지할 수도 있다. 하지만 사용자들은 아이디라는 고유의 항목을 가지고 있다는 특징과 이 아이디를 통해 쉽게 원하는 항목을 찾을 수 있다는 점을 생각하면 Hashtable 클래스가 더 적합할 수도 있다. 여기서는 Hashtable 클래스를 이용하기로 한다. 해쉬테이블의 키 값은 사용자의 아이디를 이용한다.

LoginUserList 클래스

간단한 접속 중인 사용자 리스트를 구현하기 위한 LoginUserList 클래스는 다음과 같다.

   public class LoginUserList {
      
      private Hashtable users = null;
   
      public LoginUserList() {
         users = new Hashtable();
      }
   
      public boolean isLoginUser(String id) {
         return users.get(id) != null;
      }   
   
      public Iterator iterator() {
         return users.values().iterator();
      }
   
      public void addLoginUser(LoginBean login) {
         users.put(login.getId(), login);
      }
      
      public void removeLoginUser (LoginBean login) {
         users.remove(login.getId());
      }
   }

LoginUserList 클래스는 간단히 Hashtable 클래스를 이용해 접속 중인 사용자의 리스트를 유지하게 된다. 새로 사용자가 접속할 경우 addLoginUser() 메소드를 통해 LoginUserList 객체에 알려주고 사용자가 로그아웃할 경우 removeLoginUser() 메소드를 통해 LoginUserList 객체에 알려주면 된다.

isLoginUser() 메소드는 접속 중인 사용자인가 알려주는 메소드이며, iterator() 메소드는 접속 중인 사용자의 리스트를 담고 있는 Hashtable 객체의 뷰(view)를 제공해 준다. collection의 view를 모르는 사람은 iterator 대신에 같은 기능의 enumeration 을 사용해도 좋다. 자바 2에서는 enumeration 보다는 iterator 을 추천한다. 그 이유는 여기서 다루기엔 범위가 초과하므로 생략한다.

MemberManager 클래스의 수정

LoginUserList 클래스는 어느 클래스의 어느 메소드에 연결해야 할까? 이미 우리는 그 답을 알고 있다. 바로 MemberManager 클래스이다. MemberManager 클래스는 사용자 로그인/아웃 및 사용자 관련 메소드들의 총 관리를 맡고 있다. 바로 여기가 LoginUserList 클래스가 위치할 곳이다.

MemberManager 클래스에 다름과 같은 필드를 추가한다.

   private LoginUserList users = null;

그리고 생성자에 다음과 같은 코드를 추가한다.

   users = new LoginUserList();

MemberManager 클래스가 싱글톤 패턴으로 단 하나의 객체만 생성되므로 LoginUserList 클래스도 단 한 개의 객체만이 생성되어 사용된다. 이제 실제로 사용자가 로그인하거나 로그아웃할 때 LoginUserList 클래스의 addLoginUser() 메소드와 removeLoginUser() 메소드를 통해 알려주도록 연결하는 코드를 추가하기만 하면 된다. 그 위치는 Part I, II 에서부터 상세히 다루어 온 MemberManager 클래스의 loginPerformed() 메소드와 logoutPerformed() 메소드이다. 이제 두 메소드는 다음과 같은 코드를 추가하게 된다.

   public void loginPerformed(LoginBeanBindingEvent event) {
      users.addLoginUser(event.getLoginBean());
   }

   public void logoutPerformed(LoginBeanBindingEvent event) {
      users.removeLoginUser(event.getLoginBean());
   }

단지 이 두 메소드에 각각 한 줄씩의 코드를 추가하는 것으로 간단히 접속 중인 사용자 리스트를 관리하고 유지할 수 있게 된다. 그러면 서블릿이나 JSP 페이지에서 접속 중인 사용자 리스트를 보고 싶으면 어떻게 이 클래스들을 이용해야 할까. 아직 코드가 완성된 것이 아니다.

서블릿/JSP 페이지에서 LoginUserList 클래스로의 접근

이 부분에 대해서 생각해 볼 필요가 있다. 모든 서블릿 또는 JSP 페이지는 사용자 정보를 얻기 위해서 MemberManager 클래스를 통해서 접근해야만 한다. LoginUserList 클래스도 MemberManager 클래스에 의해 유지되고 관리된다. 따라서 LoginUserList 클래스가 가지고 있는 정보도 MemberManager 클래스를 통해서 얻어야 한다.

그렇다면, MemberManager 클래스로부터 LoginUserList 클래스의 정보를 얻기 위하여 MemberManager 클래스에는 필요한 메소드가 추가되어야 한다. 두가지 방법을 생각할 수 있다.

직접적인 접근

하나는 getLoginUserList() 메소드를 MemberManager 클래스에 추가하여 직접 LoginUserList 객체의 레퍼런스를 받아서 서블릿이나 JSP 페이지에서 이용하는 방법이다.

   public LoginUserList getLoginUserList() {
      return users;
   }

그러나, 이 방법은 캡슐화에 너무 부실하게 된다. 물론 코딩 상에는 문제가 없다. 이 방법보다는 두번째 방법을 추천한다.

간접적인 접근

두번째 방법은 MemberManager 클래스가 LoginUserList 클래스의 랩퍼 클래스 역할을 하는 것이다. 복잡한 것 같지만 오히려 이 방법이 단순하다. LoginUserList 클래스의 메소드 들 중에 서블릿 또는 JSP 페이지에서 필요한 메소드들을 안전한 형태로 MemberManager 클래스에서 중계해 주면 된다.

MemberManager 클래스에 다음과 같은 메소드를 추가한다.

   public Iterator getLoginUserIterator() {
      return users.iterator();
   }

   public boolean isLoginUser(String id) {
      return users.isLoginUser(id);
   }

이제 서블릿 또는 JSP 페이지에서는 손쉽게 다음 코드를 이용하여 접속 중인 사용자 리스트를 볼 수 있다. JSP 페이지라면 다음과 같은 코드가 될 것이다.

   <h2>접속 중인 사용자 리스트<hr></h2>
   <%
      for (Iterator it = MemberManager.getInstance().getLoginUserIterator(); it.hasNext(); ) {
   %>
      <%= it.next().toString() %><br>
   <%
      }
   %>
   <hr>

이와 같은 코드를 작성하면 된다. 나중에 보완한다면 exception 처리를 보완해서 페이지에 오류가 발생하지 않도록 하는 것뿐이다. 이로서 접속 중인 사용자 리스트를 구현하고 필요한 경우 확장할 수 있는 완전한 형태를 제시해보았다.

결론

접속 중인 사용자 리스트를 구현하고 필요한 경우 확장할 수 있는 완전한 형태를 제시해보았다. 이번 파트에 다중 접속을 막는 방법까지 제시하려고 했으나 내용이 길어지고 복잡해지는 것을 피하기 위해 Part IV를 추가하고 다음 파트에서 다루기로 한다.



본 글의 저작권은 이동훈에 있으며 저작권자의 허락없이 온라인/오프라인으로 본 글을 유보/복사하는 것을 금합니다.

+ Recent posts