๋ชฉ์ฐจ
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๋ง ์กด์ฌํด์ผํจ)

7) arin84 ๋ง ์์ผ์ ์กด์ฌํ๊ฒ๋๋ค.

8) ์ฆ ์ข ๋ฃ๋์ด์ yeye91 ์ด ๋ณด๋ด๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์๊ฒ ๋๋ค. arin84 ๋ง ๊ณ์ํด์ ๋ฐ์