/java-chat

๐Ÿ“ข ์ž๋ฐ” ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ (Socket + Multi Thread + Swing)

Primary LanguageJava

์ž๋ฐ” ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ

Java Swing ํ™˜๊ฒฝ์˜ ํ…์ŠคํŠธ ์ฑ„ํŒ… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ, Socket ํ†ต์‹ ๊ณผ Multi Thread ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ๊ตฌํ˜„ํ•œ ํ”„๋กœ๊ทธ๋žจ

๋ชฉ์ฐจ

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๋ฐ ์‚ฌ์šฉ ๊ธฐ์ˆ 

  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ
    • macOS Monterey 12.4
    • IntelliJ IDEA
    • Java 11
  • ์‚ฌ์šฉ ๊ธฐ์ˆ 
    • Java Network Socket
    • AWT, Swing

์‹คํ–‰ํ™”๋ฉด๊ณผ ๊ธฐ๋Šฅ์„ค๋ช…

  • ๋กœ๊ทธ์ธ ํ™”๋ฉด

    • ์‚ฌ์šฉ์ž ์•„์ด๋””์™€ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๋Š” ํ™”๋ฉด
    • ์‚ฌ์šฉ์ž ์•„์ด๋””: ํ”„๋กœ๊ทธ๋žจ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ์ดํ„ฐ
    • ์ด๋ฆ„: ์‚ฌ์šฉ์ž ๋ชฉ๋ก๊ณผ ์ฑ„ํŒ…์„ ์ž…๋ ฅํ•œ ์‚ฌ๋žŒ์„ ํ‘œ์‹œํ•˜๋Š” ๋ฐ์ดํ„ฐ


  • ๋กœ๋น„ ํ™”๋ฉด

    • ๋กœ๋น„ ์ฑ„ํŒ… (๋ชจ๋“  ์‚ฌ์šฉ์ž ์ฑ„ํŒ… ๊ฐ€๋Šฅ)
    • ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ์— ์ ‘์†ํ•œ ๋ชจ๋“  ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ ์ถœ๋ ฅ
    • ์ฑ„ํŒ…๋ฐฉ ๋ชฉ๋ก ์ถœ๋ ฅ


  • ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ ํ™”๋ฉด

    • ์ฑ„ํŒ…๋ฐฉ ์ด๋ฆ„ ์ž…๋ ฅ

    • ํ™•์ธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ž…๋ ฅํ•œ ๋ฌธ์ž์—ด์„ ๋ฐ”ํƒ•์œผ๋กœ ์ƒˆ๋กœ์šด ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ

      • ์ƒˆ๋กœ์šด ์ฑ„ํŒ… ํ™”๋ฉด ์ถœ๋ ฅ


      • ์ƒ์„ฑ๋œ ์ฑ„ํŒ…๋ฐฉ ๋ชฉ๋ก๋“ค์€ ๋กœ๋น„์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ



      • ์ฑ„ํŒ…๋ฐฉ ๋ชฉ๋ก์—์„œ ์ฑ„ํŒ…๋ฐฉ ์ด๋ฆ„ ํด๋ฆญ ํ•˜๋ฉด, ํ•ด๋‹น ์ฑ„ํŒ… ํ™”๋ฉด ์ถœ๋ ฅ



  • ์ฑ„ํŒ…๋ฐฉ ํ™”๋ฉด

    • ํ•ด๋‹น ์ฑ„ํŒ…๋ฐฉ์— ์ ‘์†ํ•œ ์‚ฌ์šฉ์ž ๋ชฉ๋ก ์ถœ๋ ฅ



    • ๋‚˜๊ฐ€๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ ํ•˜๋ฉด ์ฑ„ํŒ…์ฐฝ์— ํ‡ด์žฅ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ๋˜๊ณ , ์‚ฌ์šฉ์ž ๋ชฉ๋ก ๊ฐฑ์‹ 



    • ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ์ฑ„ํŒ…๋ฐฉ์—์„œ ๋‚˜๊ฐ„ ๊ฒฝ์šฐ, ์ฑ„ํŒ…๋ฐฉ ์ด๋ฆ„์„ ๋กœ๋น„์˜ ์ฑ„ํŒ… ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ

      • ์ฑ„ํŒ…๋ฐฉ ์ด๋ฆ„1 ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ



    • ์ด๋ฏธ ์—ด๋ ค์žˆ๋Š” ์ฑ„ํŒ…๋ฐฉ์„ ๋‹ค์‹œ ๋“ค์–ด๊ฐ€๋ ค ํ•  ๊ฒฝ์šฐ ์˜ค๋ฅ˜ ํŒ์—… ์ถœ๋ ฅ



๊ตฌํ˜„ ๋ฐฉ์‹

  • ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋Š” Socket ์œผ๋กœ ํ†ต์‹ 

  • ํด๋ผ์ด์–ธํŠธ

    • Swing ์„ ์ด์šฉํ•ด ํ™”๋ฉด์„ ๊ตฌ์„ฑ
    • Thread ๋ฅผ ์ด์šฉํ•ด ์ž์‹ ์˜ Socket InputSream ์„ ์ง€์†์ ์œผ๋กœ ์ฝ์–ด์™€์„œ ์„œ๋ฒ„์—์„œ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ 
  • ์„œ๋ฒ„

    • ๊ฐ ํด๋ผ์ด์–ธํŠธ์— ๋Œ€ํ•œ Socket ์„ Multi Thread ํ™˜๊ฒฝ์œผ๋กœ ๊ด€๋ฆฌ
    • Multi Thread ๋ฅผ ์ด์šฉํ•ด ๋ชจ๋“  ์‚ฌ์šฉ์ž๋“ค์˜ Socket InputSream ์„ ์ง€์†์ ์œผ๋กœ ํ™•์ธ
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์„œ๋ฒ„์— ์ €์žฅ๋œ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ์‘๋‹ต์„ ์ „์†ก
  • ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” ๋ฌธ์ž์—ด ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›์œผ๋ฉฐ, ์ฃผ๊ณ  ๋ฐ›๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ํ˜•์‹์— ๋”ฐ๋ผ ๋ชจ๋‘ ๋ฌธ์ž์—ด๋กœ ์น˜ํ™˜

    • ์–‘์ชฝ์—์„œ ๋™์ผํ•œ Request Response DTO ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ์˜ ๊ฒฝ์šฐ Request DTO โž” String ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์„œ ์†ก์‹ ํ•˜๊ณ ,

      ์„œ๋ฒ„๋Š” ์ด๋ฅผ ๋ฐ›์•„ ํŒŒ์‹ฑํ•˜์—ฌ String โž” Request DTO ๋ฅผ ์ƒ์„ฑํ•ด ์‚ฌ์šฉ

      ์„œ๋ฒ„๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ๊ฒฝ์šฐ Response DTO ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ „๋‹ฌํ•  ๋‚ด์šฉ์œผ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ 

      Response DTO โž” String ์œผ๋กœ ๋ณ€๊ฒฝํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†ก

      ํด๋ผ์ด์–ธํŠธ๋Š” ์ด๋ฅผ ๋ฐ›์•„ ํŒŒ์‹ฑํ•˜์—ฌ String โž” Response DTO ๋ฅผ ์ƒ์„ฑํ•ด ์‚ฌ์šฉ

    • Request DTO : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ๋ณด๋‚ด๋Š” ๋ฉ”์‹œ์ง€ (๊ฐ์ฒด ๋‚ด์šฉ์„ ๋ฌธ์ž์—ด๋กœ ์ƒ์„ฑ)

    • Response DTO: ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๋‚ด๋Š” ๋ฉ”์‹œ์ง€ (๊ฐ์ฒด ๋‚ด์šฉ์„ ๋ฌธ์ž์—ด๋กœ ์ƒ์„ฑ)

      • ํ๋ฆ„๋„



      • ํŒŒ์‹ฑ ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”

        DtoType:data ํ˜•์‹์˜ ๋ฌธ์ž์—ด๋กœ ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹ 

        Request ์˜ ์ „์†ก ์ฃผ์ฒด๋Š” Client, Response ์˜ ์ „์†ก ์ฃผ์ฒด๋Š” Server



      • DtoType ์— ๋”ฐ๋ผ ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹ ๋ถ€์—์„œ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ

          class enum DtoType {
            	INIT, // ๋กœ๊ทธ์ธ ํ›„ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์ „์†ก ๊ด€๋ จ ๋ฉ”์‹œ์ง€ (์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ, ์ฑ„ํŒ…๋ฐฉ ๋ฆฌ์ŠคํŠธ)
          
              LOGIN, // ๋กœ๊ทธ์ธ ๋ฉ”์‹œ์ง€ (์‚ฌ์šฉ์ž ์ƒ์„ฑ, ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€)
              CREATE_CHAT, // ์ƒˆ๋กœ์šด ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ ๋ฉ”์‹œ์ง€
              ENTER_CHAT, EXIT_CHAT, // ์ฑ„ํŒ…๋ฐฉ ์ž…์žฅ, ํ‡ด์žฅ ๋ฉ”์‹œ์ง€
              MESSAGE, // ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€
          
              USER_LIST, CHAT_ROOM_LIST, // ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ, ์ฑ„ํŒ…๋ฐฉ ๋ฆฌ์ŠคํŠธ ๋ฉ”์‹œ์ง€
          }
        class DTO {
          	DtoType type;
        
            public DTO(DtoType type) {
                this.type = type;
            }
        
            public DtoType getType() {
                return type;
            }
        
            @Override
            public String toString() {
                return type + ":";
            }
        }
      • ์˜ˆ์‹œ ์ฝ”๋“œ

          /* Client Request */
          
          // Client Application
          public class LoginRequest extends DTO {
          
              String id;
          
              String name;
          
              public LoginRequest(String id, String name) {
                  super(DtoType.LOGIN);
          
                  this.id = id;
                  this.name = name;
              }
          
            	// ๋ฐ์ดํ„ฐ ๋ณด๋‚ผ ๋•Œ ๊ฐ์ฒด ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊ฟ”์„œ ์ „์†ก
              @Override
              public String toString() {
                  return super.toString() + id + "," + name;
              }
          }
          
          // Server Application
          public class LoginRequest {
          
              String id;
          
              String name;
          
            	// ์ŠคํŠธ๋ง ๋ฉ”์‹œ์ง€๋กœ ์ˆ˜์‹ ํ•œ ๋‚ด์šฉ์„ ๊ฐ์ฒด๋กœ ํŒŒ์‹ฑํ•ด์„œ ์‚ฌ์šฉ
              public LoginRequest(String message) {
                  String[] value = message.split(",");
                  id = value[0];
                  name = value[1];
              }
          
              public String getId() {
                  return id;
              }
          
              public String getName() {
                  return name;
              }
          }		
        /* Server Response */
        
        // Server Application
        public class ChatRoomListResponse extends DTO {
        
            List<ChatRoom> chatRooms;
        
            public ChatRoomListResponse(List<ChatRoom> chatRooms) {
                super(DtoType.CHAT_ROOM_LIST);
        
                this.chatRooms = chatRooms;
            }
        
          	// Object to String
            @Override
            public String toString() {
                String str = super.toString();
        
                for (ChatRoom chatRoom : chatRooms) {
                    str += chatRoom.getName() + ",";
                }
                return (chatRooms.size() > 0) ? str.substring(0, str.length() - 1) : str + "empty";
            }
        }
        
        // Client Application
        public class ChatRoomListResponse {
        
            List<ChatRoom> chatRooms = new ArrayList<>();
        
          	// String to Object
            public ChatRoomListResponse(String message) {
                if (!message.equals("empty")) {
                    String[] names = message.split(",");
                    for(String name : names) {
                        chatRooms.add(new ChatRoom(name));
                    }
                }
            }
        
            public List<ChatRoom> getChatRooms() {
                return chatRooms;
            }
        }

์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

  • ํด๋ž˜์Šค ๋ฉค๋ฒ„

    class Application {
      
      public static List<Sockets> sockets; // ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ๋ฆฌ์ŠคํŠธ
    
      ChatService chatService; // ์ฑ„ํŒ… ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ธ์Šคํ„ด์Šค (ServerThread ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ)
    
      ChatDao chatDao; // ์ฑ„ํŒ… ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ์ธ์Šคํ„ด์Šค (ChatService ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ)
      
    }
    
    โž” Application ์ธ์Šคํ„ด์Šค๋Š” main ํ•จ์ˆ˜ ์‹คํ–‰ ์‹œ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋“ค์„ ์ƒ์„ฑํ•ด์ฃผ๋Š” ์—ญํ• 
      
    โž” Application ์—์„œ ํด๋ผ์ด์–ธํŠธ๋“ค์˜ Socket ์—ฐ๊ฒฐ์„ ๋Œ€๊ธฐํ•˜๋ฉฐ ํ†ต์‹ ์„ ์œ„ํ•œ ์†Œ์ผ“์„ ์ƒ์„ฑํ•˜๋ฏ€๋กœ Socket List ๋„ ํ•จ๊ป˜ ๊ด€๋ฆฌ
      
    
    
    class ServerThread {
      
      Socket socket; // ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“
    
    	ChatService chatService;
      
    }
    โž” ๊ฐ ํด๋ผ์ด์–ธํŠธ๋งˆ๋‹ค ServerThread ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋ฅผ ๋™์ž‘์‹œ์ผœ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ 
    
      
    class User {
      
      String id; // ์•„์ด๋””
    
      String name; // ์ด๋ฆ„
    
      Socket socket; // ์ž์‹ ์˜ ์†Œ์ผ“ (ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“)
      
    }
    โž” ์‚ฌ์šฉ์ž ํด๋ž˜์Šค๋Š” ์ž์‹ ์˜ ์†Œ์ผ“ ์ •๋ณด๋ฅผ ์ €์žฅ
    
    โž” ์‚ฌ์šฉ์ž ์ธ์Šคํ„ด์Šค๋ฅผ ์ฑ„ํŒ…๋ฐฉ ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€/์‚ญ์ œํ•˜๋ฉฐ ๋ฉ”์‹œ์ง€ ์†ก์‹  ๊ด€๋ฆฌ
    
      
    class ChatRoom {
      
      String name; // ์ฑ„ํŒ…๋ช…
    
    	List<User> users; // ์ฑ„ํŒ…๋ฐฉ ๋‚ด์˜ ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ
      
    }
    โž” ์ฑ„ํŒ…๋ฐฉ ์ž…์žฅ/ํ‡ด์žฅ์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ์— User ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฝ์ž… ๋˜๋Š” ์‚ญ์ œ
      
    โž” ๊ฐ ์ฑ„ํŒ…๋ฐฉ์— ๊ด€๋ฆฌ๋˜๊ณ ์žˆ๋Š” ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์„œ๋ฒ„์—์„œ ๋ฉ”์‹œ์ง€ ์†ก์‹ 
    
    โž” User ์ธ์Šคํ„ด์Šค ์•ˆ์— Socket ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๊ฐœ๋ณ„์ ์ธ ์ฑ„ํŒ…๋ฐฉ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅ
      
      
      
    class ChatService {
      
      ChatDao chatDao;
      
    }
    โž” DAO ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด, ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ฒ˜๋ฆฌ
      
    
    class ChatDao {
      
      List<User> users; // ์ ‘์† ์ค‘์ธ ๋ชจ๋“  ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ
    
      List<ChatRoom> chatRooms;
    
      ChatRoom lobby; // ๋กœ๋น„ ์ฑ„ํŒ…๋ฐฉ ์ •๋ณด (๋กœ๋น„๋ฅผ ๊ณ„์† ๊ฑฐ์ณ ๋‹ค๋‹ˆ๋‹ˆ ๋กœ๋น„ ์ •๋ณด ์ €์žฅ)
    
      String LOBBY_CHAT_NAME = "Lobby";
      
    }
    โž” ChatService ์ธ์Šคํ„ด์Šค์—์„œ ์š”์ฒญํ•˜๋Š” ์ฑ„ํŒ… ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณต
      
    โž” ๋‹ค๋ฅธ ์ฑ„ํŒ…๋ฐฉ์— ๋“ค์–ด๊ฐ€ ์žˆ์–ด๋„ ๋กœ๋น„ ์ฑ„ํŒ…๋ฐฉ์€ ๊ณ„์† ๊ฐฑ์‹ ํ•˜๊ธฐ ์œ„ํ•ด lobby ๋กœ ๋”ฐ๋กœ ๊ด€๋ฆฌ
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์กฐ

    • ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ


  • ์ธ์Šคํ„ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

    • ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์—ฐ๊ฒฐ



    • ์‚ฌ์šฉ์ž ์ •๋ณด ์ƒ์„ฑ (์•„์ด๋””, ์ด๋ฆ„ ์ž…๋ ฅ ํ›„)



    • ์ƒˆ๋กœ์šด ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ



โ€‹

โ€‹

ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

  • ํด๋ž˜์Šค ๋ฉค๋ฒ„

    class Application {
      
        public static Socket socket;
    
        public static MessageSender sender;
    
        public static MessageReceiver receiver;
    
        public static LobbyFrame lobbyFrame;
    
        public static User me;
    
        public static List<User> users = new ArrayList<>(); // ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ๋ชจ๋“  ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ
    
        public static List<ChatRoom> chatRooms = new ArrayList<>(); 
    
      	// ์ฑ„ํŒ…๋ฐฉ ํ”„๋ ˆ์ž„ ๊ด€๋ฆฌ, ๋ฉ”์‹œ์ง€ ์™”์„ ๋•Œ ์–ด๋–ค ์ฑ„ํŒ…๋ฐฉ ๋ ˆ์ด๋ธ”์„ ๊ฐฑ์‹ ํ•ด์•ผ ํ•˜๋Š”์ง€ ํ™•์ธ
      	// [key] ์ฑ„ํŒ…๋ฐฉ ์ด๋ฆ„
        public static Map<String, ChatPanel> chatPanelMap = new HashMap<>();
    
        public static Map<String, ChatRoomUserListPanel> chatRoomUserListPanelMap = new HashMap<>();
    
        public static final String LOBBY_CHAT_NAME = "Lobby"; // ๋กœ๋น„ ์ฑ„ํŒ…๋ฐฉ ์ด๋ฆ„
    
    }
    โž” ์„œ๋ฒ„์™€ ์†Œ์ผ“ ์—ฐ๊ฒฐ ํ›„ ์†Œ์ผ“ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ
      
    โž” ์ฃผ๊ธฐ์ ์œผ๋กœ ์†Œ์ผ“ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ๊ธฐ ์œ„ํ•œ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ
    
      
      
    class MessageReader {
      
      Socket socket;
      
    }
    
    class MessageSender {
      
      Socekt socket;
      
    }
  • ํ™”๋ฉด ํ”„๋ ˆ์ž„