MapleStory Finger Point

๐Ÿ”˜ ํ”„๋กœ์ ํŠธ

[Project] WebSocket ์›น ์†Œ์ผ“ ๊ตฌํ˜„ (์‹ค์‹œ๊ฐ„ ์œ„์น˜ ์ •๋ณด)

HYEJU01 2025. 2. 12. 02:43

๋ชฉ์ฐจ

 

     

     

    WebSocket ์„ ์จ๋ณด์ž

     

    ํ”„๋กœ์ ํŠธ์—์„œ ์‹ค์‹œ๊ฐ„ ์œ„์น˜์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

     


    โœ… ์›น์†Œ์ผ“์— ์ ‘์†ํ•˜๋ฉด ์ ‘์†ํ•œ ์œ ์ € ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

    โœ… ์‚ฌ์šฉ์ž ์œ„์น˜๊ฐ€ ๋ณ€๊ฒฝ๋ ๋•Œ๋งˆ๋‹ค ์†Œ์ผ“์œผ๋กœ ์œ„์น˜์ •๋ณด๋ฅผ ๋ณด๋‚ด๋ฉด, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ์œ„์น˜์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    โœ… ์ด๋•Œ, ์†Œ์ผ“์œผ๋กœ userId ๋ฅผ ๋ณด๋‚ด๋ฉด ์ž๋™์œผ๋กœ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๋ฐ›์•„์˜จ ์œ„์น˜(์œ„๋„,๊ฒฝ๋„)๋„ ํ•จ๊ป˜ ํฌํ•จํ•ด์„œ ๋‹ค๋ฅธ ์†Œ์ผ“ ์œ ์ €๋“ค์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.

     

     

     

    ์‹ค์‹œ๊ฐ„ ์œ„์น˜์ •๋ณด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ณ„์†ํ•ด์„œ ์œ„์น˜๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•œ๋ฐ...

    ์ด๊ฑธ HTTP ๋กœ ๊ตฌํ˜„ ํ•˜๊ธฐ์—๋Š” ๋งค์šฐ ํž˜๋“ค๋‹ค. HTTP ์˜ ํŠน์ง• ๋•Œ๋ฌธ์ธ๋ฐ, ๋‹จ๋ฐฉํ–ฅํ†ต์‹ ์ธ ์  (์š”์ฒญ์„ ํ•ด์•ผ๋งŒ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Œ)

    ์š”์ฒญ์„ ํ• ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กญ๊ฒŒ ์—ฐ๊ฒฐํ•ด์•ผํ•˜๋Š” ๋“ฑ ๋งŽ์€ ๋‹จ์ ์ด ์žˆ๋‹ค. ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ’€๋ง์ด๋ผ๋Š” ๊ฐœ๋…์ด ๋‚˜์˜ค๊ธด ํ•˜๋Š”๋ฐ ์ด๊ฑด ์ฃผ๊ธฐ์ ์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋„ˆ๋ฌด ์‹ฌํ•˜๊ณ , ์‹ค์‹œ๊ฐ„ ์„ฑ๋„ ๋‚ฎ๋‹ค.

    ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” WebSocket ์„ ์“ด๋‹ค. ์›น์†Œ์ผ“์€ ํ•œ๋ฒˆ ์—ฐ๊ฒฐํ•˜๋ฉด ๊ณ„์†ํ•ด์„œ ์—ฐ๊ฒฐ์ด ์œ ์ง€๋˜๋ฉฐ, ์–‘๋ฐฉํ–ฅ ํ†ต์‹ (์ „์ด์ค‘ ํ†ต์‹ )์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋˜ํ•œ ์š”์ฒญ์ด ์—†๋”๋ผ๋„ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ณ  ์˜ค๋ฒ„ํ—ค๋“œ๋„ ์ ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์‹œ๊ฐ„์ด ํ•„์š”ํ•œ ์‹œ์Šคํ…œ์—์„œ๋Š” ์›น์†Œ์ผ“์„ ์“ฐ๊ฒŒ๋œ๋‹ค ! ๐Ÿ˜€

     

     

     

    WebSocket ์›น ์†Œ์ผ“ ๊ฐœ๋…

    HTTPํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ(Request) → ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต(Response)์‘๋‹ต ํ›„ ์—ฐ๊ฒฐ์ด ๋‹ซํž˜ (Stateless)์ƒˆ๋กœ์šด ์š”์ฒญ๋งˆ๋‹ค ๋‹ค์‹œ ์—ฐ๊ฒฐ ํ•„์š”์ฃผ๋กœ ๋‹จ๋ฐฉํ–ฅ ํ†ต์‹  (ํด๋ผ์ด์–ธํŠธ → ์„œ๋ฒ„)๋ฐ์ดํ„ฐ๋ฅผ ํ—ค๋”์— ํฌํ•จ์‹œ์ผœ์„œ ์ „๋‹ฌํ•จ ํด

    hyejux.tistory.com

     


     

     

     

    build gradle ์ถ”๊ฐ€ 

     

     

     

     


     

    config ์„ค์ • ๊ตฌํ˜„

     

     

    ์›น์†Œ์ผ“์„ ์“ฐ๊ธฐ ์œ„ํ•ด์„œ๋Š” Config (์›น ์†Œ์ผ“ ์„ค์ •ํŒŒ์ผ) ๊ณผ Handler(์†Œ์ผ“ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ) ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์ค˜์•ผํ•œ๋‹ค.

     

     

     

    `config.java`

     

    ์›น ์†Œ์ผ“ ํ™œ์„ฑํ™”, ์—”๋“œํฌ์ธํŠธ ์„ค์ •

     

    `WebSocketConfigurer` ๊ตฌํ˜„

    `@EnableWebSocket ` ์›น ์†Œ์ผ“ ํ™œ์„ฑํ™” ์–ด๋…ธํ…Œ์ด์…˜

    package com.sanchat.api.config;
    
    import lombok.RequiredArgsConstructor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.WebSocketHandler;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    
    @Configuration // ์Šคํ”„๋ง์„ค์ •ํŒŒ์ผ
    @EnableWebSocket // ์†Œ์ผ“ ์‚ฌ์šฉ
    @RequiredArgsConstructor
    public class MapWebSocketConfig implements WebSocketConfigurer {
    
        private final MapWebSocketHandler mapWebSocketHandler;
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(mapWebSocketHandler, "/tracking") // ์š”์ฒญ ํ—ˆ์šฉ ๊ฒฝ๋กœ
                    .setAllowedOrigins("*"); // ์„œ๋ฒ„๊ฐ€ ๋‹ฌ๋ผ๋„ ํ—ˆ์šฉ Cors
        }
    }

     

     


     

    Handler ํ•ธ๋“ค๋Ÿฌ ๊ตฌํ˜„

     

     

    `Handler.java`

     

    ๋”๋ณด๊ธฐ
    package com.sanchat.api.config;
    
    import ch.qos.logback.core.net.SyslogOutputStream;
    import ch.qos.logback.core.net.server.Client;
    import com.fasterxml.jackson.databind.util.JSONPObject;
    import com.sanchat.api.dto.DogDTO;
    import com.sanchat.api.dto.UserDTO;
    import com.sanchat.api.dto.UserMDTO;
    import com.sanchat.api.service.UserService;
    import lombok.Builder;
    import org.apache.catalina.User;
    import org.apache.tomcat.util.json.JSONParser;
    import org.json.JSONException;
    import org.json.JSONObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.socket.*;
    import org.springframework.web.socket.handler.TextWebSocketHandler;
    
    import java.io.IOException;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    
    
    @Component // bean ์œผ๋กœ ๋“ฑ๋ก
    public class MapWebSocketHandler extends TextWebSocketHandler {
    
        @Autowired
        UserService userService;
    
        /**
        * ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” MAP (์ ‘์†ํ•œ ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ)
        * userID , UserMDTO ์ €์žฅ
        */
        Map<String, UserMDTO> userList = new HashMap<>();
    
    
        /**
        * ํ˜„์žฌ ์ ‘์†ํ•œ ํด๋ผ์ด์–ธํŠธ (WebSocket ์„ธ์…˜) ๋ชฉ๋ก ์ €์žฅ
        */
        private static final ConcurrentHashMap<String, WebSocketSession> CLIENTS =
                    new ConcurrentHashMap<String, WebSocketSession>();
    
    
        /**
        * ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ์— ์„ฑ๊ณต ์‹œ ํ˜ธ์ถœ
        */
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            CLIENTS.put(session.getId(), session);
    
            // ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ์‚ฌ์šฉ์ž ๋ชฉ๋ก์„ JSON์œผ๋กœ ๋ณ€ํ™˜
            JSONObject response = new JSONObject();
            response.put("type", "USER_LIST"); // ๋ฉ”์‹œ์ง€ ํƒ€์ž…์„ USER_LIST๋กœ ์„ค์ •
    
            List<JSONObject> userArray = new ArrayList<>();
    
            for (UserMDTO user : userList.values()) {
                    System.out.println(user.getUserId() + session.getId());
                    JSONObject userJson = new JSONObject();
                    userJson.put("userId", user.getUserId());
                    userJson.put("userName", user.getUserName());
                    userJson.put("photo", user.getPhoto());
                    userJson.put("userIntro", user.getUserIntro());
                    userJson.put("latitude", user.getLatitude());
                    userJson.put("longitude", user.getLongitude());
                    userJson.put("dogList", user.getDogList());
                    userArray.add(userJson);
            }
    
    
            response.put("users", userArray);
    
            // ์ƒˆ๋กœ ์ ‘์†ํ•œ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ์‚ฌ์šฉ์ž ๋ชฉ๋ก ์ „์†ก
            session.sendMessage(new TextMessage(response.toString()));
    
        }
    
        /**
         * ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ผ ๋•Œ ํ˜ธ์ถœ
         * (์‚ฌ์šฉ์ž ์œ„์น˜ ์ €์žฅ, ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ์— ๋ฉ”์„ธ์ง€ ์ „๋‹ฌ)
         */
        @Override
        public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
    
    
            String id = session.getId();  //๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ธ ์›น์†Œ์ผ“ ์„ธ์…˜ ์•„์ด๋””
    
            // ๋ฐ›์€ ๋ฉ”์‹œ์ง€๋ฅผ JSON ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
            JSONObject jsonObject = new JSONObject(String.valueOf(message.getPayload()));
    
            // ํ•„์š”ํ•œ ์ •๋ณด ์ถ”์ถœ
            String userId = jsonObject.getString("userId");
            String latitude = jsonObject.getString("latitude");
            String longitude = jsonObject.getString("longitude");
            String type = jsonObject.getString("type"); // LOCATION, CLOSE , USER_LIST..
    
            UserDTO userDTO = userService.getUser(userId); // ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒํ•ด์˜ค๊ธฐ
    
            // ์‚ฌ์šฉ์ž ์œ„์น˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” UserDTO ๊ฐ์ฒด ์ƒ์„ฑ
            UserMDTO userMDTO = new UserMDTO();
            userMDTO.setUserId(userId);
            userMDTO.setPhoto(userDTO.getPhoto().getPhotoUrl());
            userMDTO.setUserName(userDTO.getUserName());
            userMDTO.setUserIntro(userDTO.getUserIntro());
    
            List<String> dogList = new ArrayList<>();
            for(DogDTO dDto : userDTO.getDogList()){
                dogList.add(dDto.getDogName());
            }
            userMDTO.setDogList(dogList);
    
            // ์œ„๋„, ๊ฒฝ๋„
            userMDTO.setLatitude(Double.parseDouble(latitude));
            userMDTO.setLongitude(Double.parseDouble(longitude));
    
            // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ userList(Map) ์— ์ €์žฅ
            userList.put(session.getId(), userMDTO);
    
            System.out.println(id +" :: " + userId + " ๋‹˜์˜ ์œ„์น˜ ์ •๋ณด | " +latitude + " | " +longitude + type );
    
    
            // ๋ฉ”์„ธ์ง€ type = "CLOSE" ๋ฉด ์—ฐ๊ฒฐ ์ข…๋ฃŒ, ์„ธ์…˜ ์ œ๊ฑฐ
            switch(type) {
                case "CLOSE" :
    
    
                    CLIENTS.remove(session.getId());
                    userList.remove(session.getId());
    
    
                    break;
                default:
                    break;
            }
    
    
            // ํ˜„์ œ ์ ‘์† ์ค‘์ธ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ (์ž์‹ ์€ ์ œ์™ธ)
            CLIENTS.entrySet().forEach(arg -> {
                if(!arg.getKey().equals(id)) {  // ์ž์‹ ์ด ์•„๋‹ˆ๋ฉด ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
                    try {
                        // ์œ„์น˜ ์ •๋ณด๋„ ํฌํ•จํ•˜์—ฌ ์ „๋‹ฌ
                        JSONObject response = new JSONObject();
                        response.put("type", "LOCATION"); // ๋ฉ”์‹œ์ง€ ํƒ€์ž…์€ LOCATION
                        response.put("userId", userMDTO.getUserId());
                        response.put("userName", userMDTO.getUserName());
                        response.put("latitude", userMDTO.getLatitude());
                        response.put("longitude", userMDTO.getLongitude());
                        response.put("photo", userMDTO.getPhoto());
                        response.put("dogList", userMDTO.getDogList());
    
                        // ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „์†ก
                        arg.getValue().sendMessage(new TextMessage(response.toString()));
    
                    } catch (IOException | JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        /**
         * WebSocket ์ „์†ก ์ค‘ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ํ˜ธ์ถœ๋จ
         */
        @Override
        public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    
        }
    
        /**
         * ํด๋ผ์ด์–ธํŠธ์™€์˜ ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋  ๋•Œ ํ˜ธ์ถœ๋จ
         * - ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ๋ฅผ CLIENTS ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ
         */
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
            CLIENTS.remove(session.getId());
            userList.remove(session.getId());
        }
    
        /**
         * ๋ถ€๋ถ„ ๋ฉ”์‹œ์ง€๋ฅผ ์ง€์›ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ (ํ˜„์žฌ๋Š” false)
         */
        @Override
        public boolean supportsPartialMessages() {
            return false;
        }
    
    
    }



     

     

     

     

     `TextWebSocketHandler` : ํ…์ŠคํŠธ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์›น์†Œ์ผ“ ํ•ธ๋“ค๋Ÿฌ 

     

    • `afterConnectionEstablished()` : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น์†Œ์ผ“์— ์—ฐ๊ฒฐ๋  ๋•Œ ์‹คํ–‰
    • `handleTextMessage()` : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‹คํ–‰
    • `afterConnectionClosed()` : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒํ•  ๋•Œ ์‹คํ–‰

     

    ์œ„ ์„ธ๊ฐœ์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

     

     

        /**
        * ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” MAP (์ ‘์†ํ•œ ์‚ฌ์šฉ์ž ๋ฆฌ์ŠคํŠธ)
        * userID , UserMDTO ์ €์žฅ
        */
        Map<String, UserMDTO> userList = new HashMap<>();

     

    Map ์„ ์ด์šฉํ•ด์„œ ์ ‘์†ํ•œ ์œ ์ €๋“ค์˜ ์ตœ์‹  ์œ„์น˜๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.  key ๋Š” sesstionId 

     

     

       /**
        * ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ์— ์„ฑ๊ณต ์‹œ ํ˜ธ์ถœ
        */
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            CLIENTS.put(session.getId(), session); // ํด๋ผ์ด์–ธํŠธ ์„ธ์…˜์„ ์ €์žฅ
    
            // ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ์‚ฌ์šฉ์ž ๋ชฉ๋ก์„ JSON์œผ๋กœ ๋ณ€ํ™˜
            JSONObject response = new JSONObject();
            response.put("type", "USER_LIST"); // ๋ฉ”์‹œ์ง€ ํƒ€์ž…์„ USER_LIST๋กœ ์„ค์ •
    
            List<JSONObject> userArray = new ArrayList<>();
    
            for (UserMDTO user : userList.values()) {
                    System.out.println(user.getUserId() + session.getId());
                    JSONObject userJson = new JSONObject();
                    userJson.put("userId", user.getUserId());
                    userJson.put("userName", user.getUserName());
                    userJson.put("photo", user.getPhoto());
                    userJson.put("userIntro", user.getUserIntro());
                    userJson.put("latitude", user.getLatitude());
                    userJson.put("longitude", user.getLongitude());
                    userJson.put("dogList", user.getDogList());
                    userArray.add(userJson);
            }
    
    
            response.put("users", userArray);
    
            // ์ƒˆ๋กœ ์ ‘์†ํ•œ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ์‚ฌ์šฉ์ž ๋ชฉ๋ก ์ „์†ก
            session.sendMessage(new TextMessage(response.toString()));
    
        }

     

    ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น ์†Œ์ผ“ ์—ฐ๊ฒฐ์— ์„ฑ๊ณตํ•˜๋ฉด, ์†Œ์ผ“์— ์ ‘์† ํ•ด ์žˆ๋Š” ์œ ์ € ๋ฆฌ์ŠคํŠธ๋ฅผ JSON ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†กํ•œ๋‹ค.

     

     

            String id = session.getId();  //๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ธ ์›น์†Œ์ผ“ ์„ธ์…˜ ์•„์ด๋””
    
            // ๋ฐ›์€ ๋ฉ”์‹œ์ง€๋ฅผ JSON ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
            JSONObject jsonObject = new JSONObject(String.valueOf(message.getPayload()));
    
            // ํ•„์š”ํ•œ ์ •๋ณด ์ถ”์ถœ
            String userId = jsonObject.getString("userId");
            String latitude = jsonObject.getString("latitude");
            String longitude = jsonObject.getString("longitude");
            String type = jsonObject.getString("type"); // LOCATION, CLOSE , USER_LIST..
    
            UserDTO userDTO = userService.getUser(userId); // ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒํ•ด์˜ค๊ธฐ
    
            // ์‚ฌ์šฉ์ž ์œ„์น˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” UserDTO ๊ฐ์ฒด ์ƒ์„ฑ
            UserMDTO userMDTO = new UserMDTO();
            userMDTO.setUserId(userId);
            userMDTO.setPhoto(userDTO.getPhoto().getPhotoUrl());
            userMDTO.setUserName(userDTO.getUserName());
            userMDTO.setUserIntro(userDTO.getUserIntro());
    
            List<String> dogList = new ArrayList<>();
            for(DogDTO dDto : userDTO.getDogList()){
                dogList.add(dDto.getDogName());
            }
            userMDTO.setDogList(dogList);
    
            // ์œ„๋„, ๊ฒฝ๋„
            userMDTO.setLatitude(Double.parseDouble(latitude));
            userMDTO.setLongitude(Double.parseDouble(longitude));

     

    ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ผ๋•Œ๋งˆ๋‹ค ์‹คํ–‰ ์ฝ”๋“œ์ด๋‹ค.

    ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ (์‚ฌ์šฉ์ž์ •๋ณด+์œ„์น˜(์œ„๋„,๊ฒฝ๋„)) ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ ๋‹ค.

     

    		// ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ userList(Map) ์— ์ €์žฅ
            userList.put(session.getId(), userMDTO);
       
    		// ํ˜„์ œ ์ ‘์† ์ค‘์ธ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ (์ž์‹ ์€ ์ œ์™ธ)
            CLIENTS.entrySet().forEach(arg -> {
                if(!arg.getKey().equals(id)) {  // ์ž์‹ ์ด ์•„๋‹ˆ๋ฉด ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
                    try {
                        // ์œ„์น˜ ์ •๋ณด๋„ ํฌํ•จํ•˜์—ฌ ์ „๋‹ฌ
                        JSONObject response = new JSONObject();
                        response.put("type", "LOCATION"); // ๋ฉ”์‹œ์ง€ ํƒ€์ž…์€ LOCATION
                        response.put("userId", userMDTO.getUserId());
                        response.put("userName", userMDTO.getUserName());
                        response.put("latitude", userMDTO.getLatitude());
                        response.put("longitude", userMDTO.getLongitude());
                        response.put("photo", userMDTO.getPhoto());
                        response.put("dogList", userMDTO.getDogList());
    
                        // ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „์†ก
                        arg.getValue().sendMessage(new TextMessage(response.toString()));
    
                    } catch (IOException | JSONException e) {
                        e.printStackTrace();
                    }
                }
            });

     

     

    ->  userList ์—๋„ ์ถ”๊ฐ€ํ•˜๊ณ 

    ->  JSON ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋‚˜๋ฅผ ์ œ์™ธํ•œ ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ๋“ค์—๊ฒŒ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ธ๋‹ค.

     

         // ๋ฉ”์„ธ์ง€ type = "CLOSE" ๋ฉด ์—ฐ๊ฒฐ ์ข…๋ฃŒ, ์„ธ์…˜ ์ œ๊ฑฐ
            switch(type) {
                case "CLOSE" :
                    CLIENTS.remove(session.getId());
                    userList.remove(session.getId());
                    break;
                default:
                    break;
            }

     

     /**
         * ํด๋ผ์ด์–ธํŠธ์™€์˜ ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋  ๋•Œ ํ˜ธ์ถœ๋จ
         * - ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ๋ฅผ CLIENTS ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ
         */
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
            CLIENTS.remove(session.getId());
            userList.remove(session.getId());
        }

     

     

    -  ๋ฉ”์„ธ์ง€ ํƒ€์ž…์ด CLOSE ์ผ๋•Œ์—๋Š” ์„ธ์…˜์„ ์ œ๊ฑฐํ•ด์„œ ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒ์‹œํ‚ค๊ณ 

    - `afterConnectionClosed` ์—๋„ ์„ธ์…˜ ์ œ๊ฑฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ค€๋‹ค  => ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋œ ํ›„ ํ˜ธ์ถœ๋จ 

     

     


     

     

    ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ

     

     

     

    ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ํฌ๋กฌ ํ™•์žฅํ”„๋กœ๊ทธ๋žจ์ธ `Browser WebSocket Client` ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

     

     

     

     

    ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์„ค์ •ํ•ด๋‘” endpoint ์ฃผ์†Œ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์›น์†Œ์ผ“์— ์—ฐ๊ฒฐ๋œ๋‹ค

     

     

     

     

     

    โœ… ํ…Œ์ŠคํŠธ 1) ์†Œ์ผ“์— ์ ‘์†ํ•œ ์œ ์ € ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ 

     

     

    1) arin84 ๊ฐ€ ์ ‘์†ํ•˜๋ฉด -> ํ˜„์žฌ ์†Œ์ผ“์— ์žˆ๋Š” ์œ ์ € ๋ฆฌ์ŠคํŠธ (arin84 ๊ฐ€ ์ฒ˜์Œ์ด๋ฏ€๋กœ ์•„๋ฌด๋„ ์—†์Œ)

    2) ์ดํ›„ ์œ„์น˜์ •๋ณด๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ธ๋‹ค. 

     

     

    3) doyoon90 ์ด ์†Œ์ผ“์— ์ ‘์†ํ•˜๋ฉด ๋ฏธ๋ฆฌ ์ ‘์†ํ•ด ์žˆ๋˜ arin84์˜ ์ •๋ณด๊ฐ€ ๋œฌ๋‹ค. 

    4) ์ดํ›„ ์œ„์น˜์ •๋ณด๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ธ๋‹ค.

     

     


    โœ… ํ…Œ์ŠคํŠธ 2 ) ์†Œ์ผ“์— ์ ‘์†ํ•œ ์‚ฌ๋žŒ์—๊ฒŒ ์ž์‹ ์˜ ์ •๋ณด ์ „๋‹ฌ (๋ฉ”์„ธ์ง€ ์ „๋‹ฌ)

     

     

    5) arin84 ๋Š” doyoon90 ์ด ์ ‘์†ํ•ด์„œ ๋ณด๋‚ธ ์œ„์น˜์ •๋ณด๋ฅผ ๋ฐ›๊ฒŒ ๋œ๋‹ค.

     

     

     

    โœ… ํ…Œ์ŠคํŠธ 3 ) ์†Œ์ผ“ ์ข…๋ฃŒ ํ…Œ์ŠคํŠธ 

     

     

    6) doyoon90 ์ด ์ ‘์†์„ ์ข…๋ฃŒํ•˜๊ณ  ์ƒˆ๋กœ์šด yeye91 ์ด ์ ‘์†ํ•ด๋ณด์ž. (์ด๋Ÿฐ๊ฒฝ์šฐ ๋ฆฌ์ŠคํŠธ์—๋Š” arin84๋งŒ ์กด์žฌํ•ด์•ผํ•จ)

     

     

    yeye91

     

    7) arin84 ๋งŒ ์†Œ์ผ“์— ์กด์žฌํ•˜๊ฒŒ๋œ๋‹ค. 

     

     

    8) ์ฆ‰ ์ข…๋ฃŒ๋˜์–ด์„œ yeye91 ์ด ๋ณด๋‚ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค. arin84 ๋งŒ ๊ณ„์†ํ•ด์„œ ๋ฐ›์Œ