๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Programming/JavaScript

[JavaScript] String-boot ์›น ์†Œ์ผ“(WebSocket)์„ ์ด์šฉํ•œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ตฌํ˜„ - Session Storage ํ™œ์šฉํ•˜๊ธฐ

728x90
๋ฐ˜์‘ํ˜•

์†Œ๊ฐœ

์™œ WebSocket์„ ์‚ฌ์šฉํ•˜์˜€๋‚˜?

Spring-boot WebSocket ์‚ฌ์šฉ๋ฒ•(์„ค์ •๋ฒ•)

์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์„ฑํ•ด๋ณด๊ธฐ

๋ฐœ์ƒํ•œ ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

   ใ„ด HTTP session ๊ฐ€์ ธ์˜ค๊ธฐ -> interception ์‚ฌ์šฉ

   ใ„ด DB๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด ๋ฉ”์‹œ์ง€ ์ €์žฅํ•˜๊ธฐ -> Session Storage ์‚ฌ์šฉํ•˜๊ธฐ

 

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

๐Ÿค” ์™œ WebSocket์„ ์‚ฌ์šฉํ•˜์˜€๋‚˜?

์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์›น ์†Œ์ผ“์€ Spring Framework์˜ STOMP๊ฐ€ ์•„๋‹Œ ์ˆœ์ˆ˜ JavaScript๋ฅผ ํ™œ์šฉํ•œ ์˜ˆ์ œ ์ž…๋‹ˆ๋‹ค.

jquery๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

WebSocket์ด ํ•„์š”ํ–ˆ๋˜ ์ด์œ 

 

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

์ผ๋ฐ˜์ ์ธ HTTP ํ†ต์‹  ๋ฐฉ๋ฒ•

์›น ์†Œ์ผ“์€ HandShake(์•…์ˆ˜)๋ผ๋Š” ๊ณผ์ •์œผ๋กœ ํ†ตํ•ด์„œ HTTP์„ WS(WebSocket)ํ”„๋กœํ† ์ฝœ๋กœ ์ „ํ™˜ ํ•ด์ฃผ๋Š”๋ฐ ์ดํ›„ ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋จผ์ € ๋ฉ”์„ธ์ง€๋ฅผ ์ „ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์ค€๋‹ค.

์‚ฌ์ง„์ถœ์ฒ˜: ์œ„ํ‚ค๋ฐฑ๊ณผ
WS์„ ์ด์šฉ

๐Ÿฅธ Spring-boot WebSocket ์‚ฌ์šฉ๋ฒ•(์„ธํŒ… ๋ฐฉ๋ฒ•)

1. WebSocket ์˜์กด์„ฑ์„ ์ถ”๊ฐ€

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-websocket'
    }

gradle.build ํŒŒ์ผ dependencies ์•ˆ์— ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋นŒ๋“œ ๋„๊ตฌ๋กœ๋Š” gradle์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค. Maven์„ ์‚ฌ์šฉํ•˜์‹ ๋‹ค๋ฉด ๊ทธ์— ๋งž๊ฒŒ ์„ค์ • ํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

2. Handler class ์ƒ์„ฑ

WebSocket์„ ํ†ตํ•ด์„œ message๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” WebSocketHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์† ๋ฐ›์€ TextWebSocketHandler๋ฅผ ์ƒ์† ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋” ์ƒ์œ„ ๊ฐ์ฒด๋กœ๋Š” AbstractWebSocketHandler๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์น˜๋Š” core package ํ•˜์œ„์—๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

package com.spacedev.board.handler;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import lombok.extern.log4j.Log4j2;

@Component
@Log4j2
public class ChatHandler extends TextWebSocketHandler {

   // message
   @Override
   protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

   }

   // connection established
   @Override
   public void afterConnectionEstablished(WebSocketSession session) throws Exception {

   }

   // connection closed
   @Override
   public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
   
   }

}

TextWebSocketHandler๋ฅผ ์ƒ์† ๋ฐ›์œผ๋ฉด handleTextMessage, afterConnectionEstablished, afterConnectionClosed ์ถ”์ƒํ™”๋œ 3๊ฐ€์ง€ ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฆ„์—์„œ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ์„ธ ๋ฉ”์†Œ๋“œ์˜ ๊ธฐ๋Šฅ์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

handleTextMessage: websocket์„ ํ†ตํ•ด์„œ ๋ฐ›์€ ๋ฉ”์„ธ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ

afterConnectionEstablished: websocket์— session์ด ์ ‘์†ํ–ˆ์„ ๋•Œ, ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ

afterConnectionClosed: websocket์— session์ด ์ ‘์†์„ ํ•ด์ œ ํ–ˆ์„ ๋•Œ, ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ

 

3. WebSocketConfigurer ์ƒ์„ฑ

package com.spacedev.board;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import com.spacedev.board.handler.ChatHandler;

import lombok.RequiredArgsConstructor;


@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
   
   @Autowired
   private final ChatHandler chatHandler;
   
   @Override
   public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
      registry.addHandler(chatHandler, "/ws/chat").setAllowedOrigins("*")
      .addInterceptors(new HttpSessionHandshakeInterceptor());   // interceptor for adding httpsession into websocket session
   }
   
}

WebSecketConfigurer ๋ฅผ ์ƒ์† ๋ฐ›์€ ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•  hanlder ํด๋ž˜์Šค์™€ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

.setAllowedOrigins("*")๋Š” wsํ”„๋กœํ† ์ฝœ /ws/chat ํ•˜์œ„์˜ ๋ชจ๋“  uri์—์„œ chatHandler๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

 

.addInterceptors(new HttpSessionHandshakeInterceptor()) ๋Š” ํ•ธ๋“œ ์‰์ดํฌ๋ฅผ ํ•  ๋•Œ, http์˜ session์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ธ๋ฐ ์—†์–ด๋„ ์ƒ๊ด€์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” ์•„๋ž˜์—์„œ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋กœ์จ, spring boot์—์„œ websocket์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ์ ์ธ ์„ค์ •์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿง ์ˆœ์ˆ˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์„ฑํ•ด๋ณด๊ธฐ

<script>
	// websocket ์ƒ์„ฑ
    const websocket = new WebSocket("ws://localhost:8080/ws/chat");
    websocket.onmessage = onMessage;	// ์†Œ์ผ“์ด ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์„ ๋•Œ
    websocket.onopen = onOpen;		// ์†Œ์ผ“์ด ์ƒ์„ฑ๋ ๋•Œ(ํด๋ผ์ด์–ธํŠธ ์ ‘์†)
    websocket.onclose = onClose;	// ์†Œ์ผ“์ด ๋‹ซํž๋•Œ(ํด๋ผ์ด์–ธํŠธ ์ ‘์†ํ•ด์ œ)

    //on exit chat room
    function onClose(evt) {
    console.log("close event : " + evt);
    }

    //on entering chat room
    function onOpen(evt) {
    console.log("open event : " + evt);
    }

    // on message controller
    function onMessage(msg) {
    var data = JSON.parse(msg.data); // msg๋ฅผ ๋ฐ›์œผ๋ฉด data ํ•„๋“œ ์•ˆ์— Json String์œผ๋กœ ์ •๋ณด๊ฐ€ ์žˆ์Œ
    // ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ Json data์—์„œ ์ถ”์ถœ
     var senderId = data.senderId;
     var message = data.message;
     var time = data.time;
     var newOne = data.newOne;
     var outOne = data.outOne;
    }
    
    // send a message
    function send(){
    var message = document.getElementById("msg").value;
    
    // don't send when content is empty
    // ์ฑ„ํŒ… ์ž…๋ ฅ ์นธ์ด ๋น„์–ด์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ๋งŒ ์ •๋ณด๋ฅผ Jsonํ˜•ํƒœ๋กœ ์ „์†ก
    if(message != "") {			
	let msg = {
   	'receiverId' : receiverId,
    	'message' : message
      	}

    	if(message != null) {
    	websocket.send(JSON.stringify(msg));	// websocket handler๋กœ ์ „์†ก(์„œ๋ฒ„๋กœ ์ „์†ก)
    	}
    	document.getElementById("msg").value = '';
 	}
}

</script>

์œ„ ์Šคํฌ๋ฆฝํŠธ๋Š” ์˜ˆ์‹œ์šฉ ์Šคํฌ๋ฆฝํŠธ ์ž…๋‹ˆ๋‹ค.

ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด์žˆ๋Š” view์— ํŒŒ์ผ์˜ url์— ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘์†ํ•  ๋•Œ ์›น ์†Œ์ผ“์ด ์ƒ์„ฑ์ด๋œ๋‹ค.

const websocket = new WebSocket("ws://localhost:8080/ws/chat");

http ํ”„๋กœํ† ์ฝœ์„ ws๋กœ ๋ฐ”๊พธ๊ณ  config์—์„œ ์„ค์ •ํ•œ url๋กœ ์ ‘์†ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.(8080 ํ•˜์œ„ ์ฃผ์†Œ ex: ws/chat  -> ๋ณธ์ธ์ด ์„ค์ •ํ•œ ์ฃผ์†Œ)

 

WebSocket์œผ๋กœ ์ฑ„ํŒ…๋ฐฉ์„ ๊ตฌํ˜„ํ• ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” 4๊ฐœ์˜€๋‹ค.

 

1. ์ ‘์†(Session connection): onopen

2. ์—ฐ๊ฒฐํ•ด์ œ(Session disconnection): onclose

3. ๋ฉ”์„ธ์ง€๋ฅผ ์ˆ˜์‹ (get): onmessage

4. ๋ฉ”์„ธ์ง€๋ฅผ ์†ก์‹ (send): send

 

์ฃผ๋กœ ๋ณผ ๊ฒƒ์€ ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์„ ๋•Œ์™€ ์ „์†กํ•  ๋•Œ์ด๋‹ค.

 

์ฑ„ํŒ…์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณด๋‚ธ์‹œ๊ฐ„, ๋ฐ›๋Š”์‚ฌ๋žŒ, ๋ณด๋‚ธ์‚ฌ๋žŒ, ๋ฉ”์„ธ์ง€ ๋‚ด์šฉ ๋“ฑ ๋‹ค์–‘ํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ๋ฐ ์›น ์†Œ์ผ“์˜ ๊ฒฝ์šฐ String ํƒ€์ž…์˜ message๋งŒ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋‹จ์—์„œ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

๊ทธ๋ ‡๊ธฐ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ Json ํ˜•์‹์œผ๋กœ ์„œ๋ฒ„์™€ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

 

๐Ÿ˜ฑ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๊ตฌํ˜„ ์ค‘ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ ๋ฐ”๋กœ HTTP session์„ ๊ฐ€์ ธ์˜ค๊ธฐ์ด๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด์„œ ์›น ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•˜๋ฉด ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ๋“ค์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ฐ์ž ๊ณ ์œ ์˜ ๊ฐ’์ด session์„ ์ƒ์„ฑํ•ด์„œ ์œ ์ €์—๊ฒŒ ์ „์†กํ•˜๋Š”๋ฐ ์ด session์€ HTTP์ƒ์˜ session์ด๋‹ค.

 

์™œ ๋ฌธ์ œ๊ฐ€ ๋ ๊นŒ?

Session ์†์— ๋“ค์–ด์žˆ๋Š” seesion id๋ฅผ ๊ฐ€๊ณตํ•ด์„œ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ WS์ด HTTP๋Š” ์„œ๋กœ ๋‹ค๋ฅธ session์„ ์ƒ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฆ‰, ์›น ํŽ˜์ด์ง€์˜ ํ™ˆ session id๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ attribute์— ์ €์žฅํ•ด๋†“์€ ๊ฒƒ์„ WS์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์—ˆ๋‹ค๋Š” ๊ฒƒ.

 

โ–ถ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•: HTTP session ๊ฐ€์ ธ์˜ค๊ธฐ -> interception ์‚ฌ์šฉ

๋‚ด๊ฐ€ ํ•„์š”ํ•œ๊ฑด ๋งŽ์ธ ํ›Œ๋ฅญํ•œ ๋ถ„๋“ค๊ป˜์„œ ๋‹ค ๋งŒ๋“ค์–ด ๋†“์œผ์‹  ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์ด์˜€๊ธฐ์— ์ด๋ฒˆ์—๋„ ํ•ด๋‹ต์„ ์ฐพ์•˜๋‹ค.

@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
	
	@Autowired
	private final ChatHandler chatHandler;
	
	@Override
	public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		registry.addHandler(chatHandler, "/ws/chat").setAllowedOrigins("*")
		.addInterceptors(new HttpSessionHandshakeInterceptor());	// interceptor for adding httpsession into websocket session
	}
	
}

Java์—์„œ ์›น ์†Œ์ผ“์„ ์„ค์ •ํ• ๋•Œ WebSocketConfigurer ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์† ๋ฐ›๊ณ  resigerWebsocketHandlers ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์† ๋ฐ›์•„์•ผํ•œ๋‹ค.

 

์œ„ ๋ฉ”์†Œ๋“œ์˜ ์ธ์ž registry์— .addInterceptors(new HttpSessionHandshakeInterceptor()๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด HTTP๋ฅผ WS์œผ๋กœ ๋ณ€๊ฒฝํ• ๋•Œ interceptor๊ฐ€ ์ž‘์šฉํ•ด HTTP session์˜ attrubutes๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

@Component
public class ChatHandler extends TextWebSocketHandler {

	@Override
	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

		String senderId = (String) session.getAttributes().get("sessionId");
}

handler ๋‚ด์˜ WebSocketSession์—์„œ httpSession์—์„œ ์„ค์ •ํ•œ attribute๋ฅผ "getAttrubutes().get(์ €์žฅํ•œ ์• ํŠธ๋ฆฌ๋ทฐํŠธ์ด๋ฆ„)์„ ํ†ตํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

โ–ถ DB๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด ๋ฉ”์‹œ์ง€ ์ €์žฅํ•˜๊ธฐ -> Session Storage ์‚ฌ์šฉํ•˜๊ธฐ

<script>
	// save chat history
    function setChatHistory(name){
    var value =[];
    document.querySelectorAll('.message-li').forEach(item => {
    
    var time = item.querySelector('.message-data > .message-data-time').textContent;
    var message = item.querySelector('.message').textContent;
    var senderId;
    var type = item.querySelector('.message').classList[1];
    if(type == 'my-message'){
    senderId = myId;
    } else {
    senderId = name;
    }
    
    data = {
    	"time":time,
        "message":message,
        "senderId":senderId
        }
        value.push(data);
   
   })
        	 
	sessionStorage.setItem(name, JSON.stringify(value));
     };
         
	// insert pre chat history
	function getChatHistory(name){
	var data = JSON.parse(sessionStorage.getItem(name));
        	 
	if(data != null) {
		data.forEach(item => {
		var time = item.time;
		var message = item.message;
		var senderId = item.senderId;

		insertMessage(senderId, time, message);
		})
	}
};
</script>

์ƒ๋Œ€๋ฐฉ์˜ id๋ฅผ session stroage์˜ key๋กœ ์ƒ๋Œ€๋ฐฉ๊ณผ์˜ ๋Œ€ํ™” ๋‚ด์šฉ์€ Json String์œผ๋กœ ๋งŒ๋“ค์–ด value๋กœ ๋„ฃ์–ด์คฌ๋‹ค.

 

sessionStorage๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ?

๋‚ด๊ฐ€ ํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ์‹ค์‹œ๊ฐ„ ๋ผ์ด๋ธŒ ์ฑ„ํŒ…์ด์ง€๋งŒ, 1:1 ์ฑ„ํŒ…์ด์˜€๊ธฐ์— ์ฑ„ํŒ… ์ƒ๋Œ€๋ฅผ ๋ฐ”๊พธ๋Š” ๊ณผ์ •์ด ์žˆ๊ธฐ์— ์ฑ„ํŒ… ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์ €์žฅํ•  ๊ณต๊ฐ„์ด ํ•„์š”ํ–ˆ๋‹ค.

 

sessionStorage๋Š” localStorage๋‚˜ DB ์ €์žฅ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ session์ด ๋งŒ๋ฃŒ๋˜๋ฉด ์‚ฌ๋ผ์ง€๋Š” ์ •๋ณด์ด๋‹ค. ํ•ด๋‹น ์›น ํŽ˜์ด์ง€๋Š” ์ต๋ช…์œผ๋กœ ์ฑ„ํŒ…์— ์ฐธ์—ฌํ•˜๋Š” ๊ฒƒ์ด๊ณ  ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ์— ์„ธ์…˜์ด ์ข…๋ฃŒ์‹œ ์‚ฌ๋ผ์ง€๋Š” ํœ˜๋ฐœ์„ฑ ์ €์žฅ ๊ณต๊ฐ„์ด ํ•„์š”ํ–ˆ๊ธฐ์— ์‚ฌ์šฉํ•˜๊ธฐ ์ ์ ˆํ•ด ์‚ฌ์šฉํ•˜์˜€๋‹ค.

โ–ถ sessionStorage ์‚ฌ์šฉ๋ฒ•

<script>
if(sessionStorage.getItem(senderId) != null) {
	container = JSON.parse(sessionStorage.getItem(senderId));
	console.log('stagine message container >>> ', container);
	container.push(data);
 } else {
 	container.push(data);
 }
 sessionStorage.setItem(senderId, JSON.stringify(container));
 </script>

sessionStorage๋Š” key(String), value(String)๋กœ ์ด๋ค„์ง‘๋‹ˆ๋‹ค.

 

setItem(key, value) ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  getItem(key)๋ฅผ ํ†ตํ•ด์„œ ์ €์žฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์œ„์˜ ์˜ˆ์‹œ ๋‚ด์šฉ

๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์•˜์„ ๋•Œ, senderId(๋ณด๋‚ด๋Š” ์‚ฌ๋žŒ)์˜ key๋ฅผ ๊ฐ€์ง„ sessionStorage๊ฐ€ null์ด ์•„๋‹ ๋•Œ

-> ์ด๋ฏธ senderId์™€ ๋ฉ”์„ธ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›์€์ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ

=> ๋ฉ”์„ธ์ง€๋ฅผ ์ €์žฅํ•ด ๋†“์€ container ๋ฐฐ์—ด ๋’ค์— ์ถ”๊ฐ€ ํ•ด์ค€๋‹ค. 

 

sessionStorage์— senderId์™€ ์ผ์น˜ํ•˜๋Š” key๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ

-> ๋ฉ”์„ธ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›์€์ ์ด ์—†๋‹ค.

=> ๋น„์–ด์žˆ๋Š” container์— ์ถ”๊ฐ€ ํ•ด์ค€๋‹ค.

 

์œ„ ์ฝ”๋“œ์˜ ๋ฌธ์ œ์ 

host์˜ ๊ฒฝ์šฐ ๋Œ€ํ™”์ƒ๋Œ€๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ๋งˆ๋‹ค sessionStorage์— ๊ธฐ์กด์˜ ๋Œ€ํ™” ๋‚ด์šฉ์„ ๋ชจ๋‘ ์ €์žฅํ•˜๊ณ  ๋‹ค์‹œ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์™€์•ผ ํ•œ๋‹ค.

๋Œ€ํ™” ๋‚ด์šฉ๊ณผ ๋Œ€ํ™” ์ƒ๋Œ€๊ฐ€ ๋งค์šฐ ๋งŽ์•„ ์ง„๋‹ค๋ฉด host(master)์˜ ๋ธŒ๋ผ์šฐ์ €์— ๋ถ€ํ•˜๊ฐ€๊ฑธ๋ฆด ํ™•๋ฅ ์ด ๋†’๋‹ค.

 

ํ•ด๊ฒฐ์ฑ…?

1. host์™€ ๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” session ์ œํ•œํ•˜๊ธฐ

2. ์ €์žฅํ•  ๋ฉ”์„ธ์ง€์˜ ๊ฐœ์ˆ˜๋ฅผ ์ œํ•œํ•˜๊ธฐ -> ํ™•์žฅ: ์ €์žฅํ•  ๋Œ€ํ™” ๋‚ด์šฉ์˜ ์–‘์„ host๊ฐ€ ์ง์ ‘ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ ์ œ๊ณต

 

2๋ฒˆ ๋ฐฉ์•ˆ์ด ์กฐ๊ธˆ ๋” ์œ ์šฉํ•  ์ˆœ ์žˆ์ง€๋งŒ, ๊ทผ๋ณธ์ ์ธ ํ•ด๊ฒฐ์ฑ…์ด๋ผ๊ณ  ๋ณด๊ธฐ๋Š” ์–ด๋ ค์šธ ๊ฒƒ ๊ฐ™๋‹ค.

๋” ์ข‹์€ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ์˜๊ฒฌ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ˜ถ‍๐ŸŒซ๏ธ์•„๋ฌดํŠผ ๊ฒฐ๊ณผ...

guest

์ฑ„ํŒ…๋ฐฉ์€ guest๋กœ ์ ‘์†ํ•˜๋ƒ master๋กœ ์ ‘์†ํ•˜๋ƒ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€ ์ ‘์†ํ•˜๊ฒŒ๋˜๋ฉด ์ ‘์† ๋ฉ”์„ธ์ง€๋ฅผ ๋‚จ๊ธฐ๊ฒŒ๋˜๋Š”๋ฐ ๋งˆ์Šคํ„ฐ์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ๊ฒŒ์ŠคํŠธ๋“ค์—๊ฒŒ ์ ‘์† ๋ฉ”์„ธ์ง€๋ฅผ ๋‚ ๋ฆฌ๊ฒŒํ•ฉ๋‹ˆ๋‹ค.

์ขŒ: guest ์šฐ: master(host)

 

๋งˆ์Šคํ„ฐ์˜ ๊ฒฝ์šฐ ๊ฒŒ์ŠคํŠธ๊ฐ€ ๋งŽ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ฒŒ์ŠคํŠธ๋ฅผ ์„ ํƒ์ ์œผ๋กœ ๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๋Œ€ํ™” ์ค‘์ด ์•„๋‹Œ ๊ฒŒ์ŠคํŠธ๊ฐ€ ๋งˆ์Šคํ„ฐ์—๊ฒŒ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ธ๋‹ค๋ฉด ๋ณด๋‚ธ ๋งŒํผ ์นด์šดํŒ…๋˜๊ณ  ๋งˆ์Šคํ„ฐ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๊ฒŒ ํ•ด๋†จ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„  seesionStorage์— ์ƒ๋Œ€์˜ ๋ฉ”์„ธ์ง€๋ฅผ ์ €์žฅ์‹œ์ผœ ๋†“์Šต๋‹ˆ๋‹ค.

ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ๋™๊ทธ๋ž€ ํ‘œ์‹œ๋Š” canvas๋ฅผ ์ด์šฉํ•ด์„œ ๊ทธ๋ ธ์Šต๋‹ˆ๋‹ค.

๊ฒŒ์ŠคํŠธ๋ฅผ ์„ ํƒํ•˜๋Š” ์ˆœ๊ฐ„ ํ•ด๋‹น ๊ฒŒ์ŠคํŠธ์˜ ์•„์ด๋””์™€ ๋™์ผํ•œ sessionStorage์—์„œ ๋ฉ”์„ธ์ง€๋ฅผ ๊ฐ€์ ธ์™€ ํ˜•์‹์— ๋งž๊ฒŒ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์˜ ๊ธฐ๋Šฅ์„ ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ดค์Šต๋‹ˆ๋‹ค. 

 

JS์™€ Java ์ „์ฒด์ฝ”๋“œ๋ฅผ ์ ๋Š”๊ฑด ๋„ˆ๋ฌด ๊ธธ์–ด์„œ ํ•„์š”ํ•œ ํ‹€๋งŒ ์ž‘์„ฑํ–ˆ์œผ๋‹ˆ ๋‚ด์šฉ์ด ํ•„์š”ํ•˜์‹  ๋ถ€๋ถ„์€ ๊นƒํ—™์—์„œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

 

chatHandler.java, chat.html(<script>)๋ฅผ ์ฐพ์•„์„œ ํ™•์ธ ํ•˜์‹œ๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

 

๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ๋งŽ์„ํ…๋ฐ ์ด์Šˆ๊ฐ€ ๋ ๋งŒํ•œ ๋ถ€๋ถ„์€ ๊นƒํ—™ ์ด์Šˆ์— ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

 

ํ”„๋กœ์ ํŠธ ์ „์ฒด ์†Œ์Šค: https://github.com/wjgin/Spring-boot-drill/tree/master/itsme

728x90
๋ฐ˜์‘ํ˜•