[JS] Promise 활용 - 사용자 입력에 의한 동작 진행 / 미진행

Posted by Space_Jin
2025. 11. 6. 18:37 Programming/JavaScript
728x90
반응형

JS를 활용하는 front 소스에서 사용자 입력을 통해서 함수를 더 진행시킬지 중단할지 정해야하는 경우가 많이 생깁니다.

 

모든 Modal 창을 통해서 callback 처리를 각각 함수에서 받아서 처리하면 문제가 생길 일이 없지만, 복잡한 비지니스 로직해서

하나의 함수에서 연속적으로 사용자 입력을 받아할 경우가 생길 수 있습니다.

 

최근 실무에서 위와 같은 문제가 생긴적이 있는데 이를 해결하기 위해서 사용한 간략한 기법을 정리해 봅니다.

 

예시코드

let success = ''	//resolve를 담을 변수
let fail = '' 		//reject를 담을 변수


const returnPromise = () => {
    console.log("returnPromise call")
    
    return new Promise((resolve, reject) => {
        success = resolve
        fail = reject
    })
}


const promiseControllTest = async () => {
    console.log("test start")

    //유저 입력 confirm을 비동기로 호출
    //업무에서는 Modal창을 통해서 사용자 입력을 받는다.
    setTimeout(() => {
        if(confirm("확인을 눌러주세요.")) success()
        else fail()
    }, 0)
    
    console.log("유저 입력까지 returnPromise 대기")
    
    let resultP = await returnPromise()
        .then(() => "success 되었음.")
        .catch(() => "reject 되었음.")

    //resultP 값에 따라서 함수를 더 진행할지 결정할 수 있음
    console.log("resultP = ", resultP)

    console.log("test end")
}

 

위 소스의 promiseControllTest 함수는 await된 returnPromise의 resolve가 사용자 입력인 confirm이 resolve()를 해줄 때까지 pending 되었다가 이후 결과 값 resultP를 통해서 함수를 더 진행시킬지 종료 시킬지(reuturn) 결정할 수 있습니다.

 

실무에서 React 혹은 Vue를 사용할 경우, 새로운 컴포넌트에서 success / fail 변수를 할당하고 Modal 창을 비동기적으로 호출하여 동작을 컨트롤할 수 있습니다.

728x90
반응형

[JS] setTimeout 사용법과 await / sleep 만들기

Posted by Space_Jin
2024. 9. 5. 14:35 Programming/JavaScript
728x90
반응형

 

JavaScript에서 setTimeout은 비동기(async)로 특정 시간 후의 로직을 수행시킬 수 있다.

 

setTimeout 수행 예제
console.log('start');

// async로 3초(3,000ms)뒤에 {}안의 로직 수행
setTimeout(() => {
	console.log('call it after 3s');
}, 3000);

console.log('end')

 

setTimeout 수행 결과
>>> start
>>> end
// ...약 3초 뒤...
>>> call it after 3s

 

 

setTimeout에 await를 사용하기

 

setTimeout await 사용
console.log('start');

// async로 3초(3,000ms)뒤에 {}안의 로직 수행
await setTimeout(() => {
	console.log('call it after 3s');
}, 3000);

console.log('end')
setTimeout await 사용 결과
>>> start
>>> end
// ...약 3초 뒤...
>>> call it after 3s

await를 사용하지 않은 결과와 동일하다.

 

그 이유는 setTimeout은 Promise를 return하지 않기 때문

 

await는 Promise해결될 때까지 기다리는 행위이다.

하지만, setTimeout은 지정된 시간이 지난 후 콜백함 수를 수행하는 비동기 함수 일뿐, Promise를 반환하지 않는다.

>>> start
// ...약 3초 뒤...
>>> call it after 3s
>>> end

 

위와 같은 결과를 위해서 await를 사용하려고 했다면, 아래와 같이 해결할 수 있다.

 

setTimeout을 활용한 sleep 예제
// ms 밀리세컨즈 이후 Promise를 반환
const sleep = ms => {
	return new Promise(resolve => {
    	setTimeout(resolve, ms)
        })
}

// sleep을 활용
const delay = async () =>{
    console.log('start');
    await sleep(3000);
    console.log('end');
}

// delay 호출
delay()

 

setTimeout을 활용한 sleep 예제 결과

 

>>> start
// ...약 3초 뒤...
>>> call it after 3s
>>> end
728x90
반응형

[JS] 보안 키패드 입력 error 예외처리(ft. isNaN)

Posted by Space_Jin
2024. 8. 19. 15:00 Programming/JavaScript
728x90
반응형

회사에서 운영하고 있는 앱의 보안 키패드를 사용하는 서비스에서 잘못된 입력 값으로 인한 오류의 트러블 슈팅을 진행했습니다.

 

서버에서 input 값 검증을 통해서 업무 오류를 뱉어내 잘못된 정보가 업데이트 되지는 않았었지만, 화면 소스(front end)에서 예외처리 미흡으로 잘못된 input 값을 서버(back end) 측으로 보내고 있음을 확인했습니다.

 

😮 문제 상황

보안 키패드의 사용하는 이벤트의 value를 처리하는 부분에서 numberic의 검증이 되지 않아서 숫자형 값만 들어와야하는 부분에 실제 string이 들어오는 경우가 발생하였습니다.

 

🛠️ 조치방법

키패드 이벤트를 통해서 들어오는 value 값을 화면에서 isNaN를 사용해 한번 더 예외처리 하였습니다.

 

기존 로직의 경우, value가 string으로 들어오는데 해당 값이 '1'...'9'(1~9) 로 들어온다는 상정하고 개발되어 있었기에 숫자형의 value가 들어온다면, 이를 예외처리하기 위해서 JS Number class의 isNaN 메서드를 사용하여 예외처리 하였습니다.

 

if (Number.isNaN(v) === false) {
	// 숫자형 v 가 들어왔음으로 처리
}

 

isNaN는 숫자형 데이터(numberic)가 아닐 경우(NaN), true를 return 합니다.

여기서 숫자형은 실제 Number 타입의 데이터와 숫자형식의 char('0' ~ '9')를 모두 포함 합니다.

 

▶ isNaN 예제

let n1 = '1'
let n2 = Number(n1) // 1

let r1 = Number.isNaN(n1)
let r2 = Number.isNaN(n2)

console.log('n1', n1)
console.log('n2', n2)

console.log('r1', r1)
console.log('r2', r2)

 

▶ 결과

> "n1" "1"
> "n2" 1
> "r1" false
> "r2" false

 

 

isNaN는  static으로 해당 메서드만 바로 사용해도 되지만, 명확하기 Number.isNaN() 로 사용하는 것이 권장 됩니다.

 

 

728x90
반응형

[JS] Object 변수 데이터 추가, 문자열(String)을 이용한 동적 접근 방법

Posted by Space_Jin
2022. 8. 17. 23:00 Programming/JavaScript
728x90
반응형

🥸 JavaScript Object 객체 문자열을 이용해 동적으로 데이터 추가, 삭제하기

 

자바스크립트의 Object 객체는 key, value 형태도 데이터를 저장합니다.

🤔 프로퍼티 접근법으로 데이터 추가, 대체 하기

var object = {};

object.arr = [];	// obect에 arr가 없다면 빈 배열([])을 추가, 존재한다면 대체
console.log(object);    // { arr: [] }

object.arr.push('first');	// object 안의 arr에 문자열 'first' 추가
console.log(object.arr);    // [ 'first' ]

object.arr = [];	// 기존에 있는 arr를 빈 배열로 대체
console.log(object.arr);    // []

위 코드와 같이 '.'을 사용해서 property에 바로 접근할 수 있습니다.

 

object.key = value 형태로 데이터를 추가할 수 있습니다. 만약, 이미 key가 존재한다면 새로운 value로 대체 됩니다.

🤔 문자열 변수로 동적 접근 하기

var object = {};

object.arr = [];

var key = 'arr';
object['arr'].push('first');
object[key].push('second');
console.log(object.arr);    // [ 'first', 'second' ]

객체의 대괄호([]) 안에 key의 문자열을 직접 입력하면 데이터에 접근할 수 있습니다.

 

변수에 문자열을 담아서 위 방법으로 접근하면 동적으로 데이터에 접근하여 값을 추가, 제거, 수정 할 수 있습니다.

🤗 종합 코드 보기

// Object 접근 테스트
var object = {};

object.arr = [];
console.log(object);    // { arr: [] }

object.arr.push('first');
console.log(object.arr);    // [ 'first' ]

var key = 'arr';
object[key].push('second');
console.log(object.arr);    // [ 'first', 'second' ]
728x90
반응형

[JS] 자바스크립트의 상속과 prototype

Posted by Space_Jin
2022. 8. 4. 20:00 Programming/JavaScript
728x90
반응형

이번에 회사에서 배치받은 팀은 모바일 서비스 팀이었다.

 

네이티브 앱 아래에  웹 뷰를 제공하는데 당분간은 프론트 부분을 다루게 될 것 같다.

 

JS는 DOM 조작 외에는 다뤄볼 기회가 없었기에 이번에 prototype에 대한 개념도 처음 알게 되었다.

JS는 prototype 기반 언어라고 불린다는데 기본도 몰랐던 거시였다... 한 동안 JS를 열심히 공부해야할 것 같다.

 

prototype은 JS에서 객체의 상속을 다루는 간단하면서, 중요한 개념이었다. 사실 JS도 이런 기능을 제공한다는 것에 놀라기도 했다.

또 역시 JS답게 굉장히 심플했다.

🧐 자바스크립트 객체 생성

function MyObject(인자) {
	this.property1 = ...
	this.property2 = 인자
}
class MyObject {
	constructor(인자) {
    		this.property1 = ...
    		this.property2 = 인자
      }
}

자바스크립트에서 객체를 생성하는 방법은 크게 위 두 가지 방식인데 아래 방식의 class를 만드는 것은 SE6 이후에 나온 문법이라고 한다.

그래서인지 대체로 function을 사용하는 위 방법으로 작성된 코드들이 대부분인 듯하다.

🤔 자바스크립트 prototype을 이용한 상속

자바스크립트에서 객체를 생성하면 자동적으로 prototype이라는 property가 생성된다.

이 property안에 새로운 객체를 생성하면 그것이 '부모' 객체가 되면서 상속이 일어난다고 할 수 있다.

function Papa(){
	this.age = 50
}

function Son() {
	this.name = 'son'
}

var sam = new Son()
sam.prototype = new Papa()	// Son의 다형성 객체인 sam은 Papa객체를 부모 객체로 상속 받는다.

console.log(sam.name)	// >>> son
console.log(sam.age)	// >>> 50

실제로 sam이라는 객체는 Son 객체이기 때문에 age라는 속성은 없지만, prototype이라는 속성 안에 Papa를 생성하여 상속받았기에 Papa가 가지고 있는 age라는 속성을 가지게 된다.

sam.protytpe.tall = 180
console.log(sam.tall) // >>> 180

위 처럼 꼭 객체를 생성해야하는 것이 아닌 prototype 안에 property를 추가할 수 도 있다.

확실히 문법이 자유롭다.

🥸 자바스크립트 prototype chain

위 코드에서 보듯이 sam.age의 동작은 아래처럼 이뤄진다.

sam 객체에서 age 속성을 찾음 -> 없음 -> prototype에서 찾음 -> prototype안에 Papa 객체에서 찾음 -> 출력

만약, prototype 객체의 Papa 객체에도 없었다면, Papa 객체 안의 prototype에서 찾기를 반복한다. -> 언제까지? 최상위 객체까지

 

이렇게 prototype을 연쇄적으로 찾는다 하여 이를 prototype chain이라고 부른다고 한다.

 

자바를 공부했었다면, 자바스크립트의 prototype을 어렵지 않게 이해할 수 있을 것이라고 생각한다.

 

이상 끄읕

728x90
반응형

[JavaScript] String-boot 웹 소켓(WebSocket)을 이용한 실시간 채팅 구현 - Session Storage 활용하기

Posted by Space_Jin
2021. 12. 29. 20:30 Programming/JavaScript
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
반응형

[JavaScript] 바닐라 자바스크립트 disabled, display 속성 추가, 해제(변경)

Posted by Space_Jin
2021. 12. 29. 20:26 Programming/JavaScript
728x90
반응형

간혹 자바스크립트에서 disabled 속성과 display 속성을 변경할 때 헷갈리는 경우가 있다.

 

필요할 때 찾아보기 위해서 글을 씁니다.

JavaSctript로 disabled 속성 활성화 or 해제 하기

function disabledFalse() {
    document.querySelector('#name').disabled = false;
    document.querySelector('#email').disabled = false;
    document.querySelector('#phone').disabled = false;
    document.querySelector('#message').disabled = false;
}

위 처럼 내가 원하는 선택자를 선택해준 후 .disabled 속성을 변경해주면 된다.

 

선택자의 경우 <input> 태그나 <button> 태그 등을 말한다.

 

'#선택자의 id 값' => ex) <input id = "name">MyId</input>

 

class로 선택해주고 싶으면 #id 대신 .class이름으로 선택해주면 된다.

ex)

<button class="disBtn"> 태그를 자바스크립트로 선택하려고하면 document.querySelector('.disBtn')

 

false => 활성화 해제: 선택이나 수정 불가능

true -> 활성화: 선택이나 수정 가능

JavaSctript로 display 속성 활성화 or 해제 하기

display 비활성화(안 보이게 하기)

function hideUpdateBtn() {
    document.querySelector('#updateBtn').style.display = 'none';
}

disabled와 마찬가지로 선택자를 선택 후 .style.display = 'none' 으로 바꿔주면 비활성화 된다.

 

disabled와는 조금 다르게 style 속성을 변경해주는 것이다.

 

display 활성화(보이게 하기)

function showUpdateBtn() {
    document.querySelector('#updateBtn').style.display = 'block';
    document.querySelector('#updateBtn').style.display = 'inline';
}

활성화의 경우 block 혹은 inline으로 변경해주면 된다.

 

728x90
반응형

자바 스크립트 기초 / 글자수 계산기

Posted by Space_Jin
2020. 12. 8. 22:00 Programming/JavaScript
728x90
반응형

글자수 계산기 만들기 with 자바스크립트

필요지식

1. getElementById를 이용해

     ㄴ DOM(Document Object Model)id 가져오기

 

2. onkeydown 이벤트


HTML 코드

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>글자수 계산기</title>

    <style> //스타일 지정
        h1 {
            margin-top: 30px; // 상단 공간과의 거리
}
     #count {
            float: right;
        }
    </style>

</head>
<body class='container'>

    <h1>자기소개</h1> // 제목 입력
    <textarea class="form-control" rows="3" onkeydown = 'counter();' id="wordarea">입력하세요</textarea>
	<span id="count">(0/200)</span>
 
</body>
</html>

자바스크립트 코드

<script>
// counter라는 함수 정의
function counter() {
	// content 변수 지정
    // getElementById(id입력)
    // -> 특정 id를 가진 DOM(textarea, span 과 같은 특정 객체를 의미함)을 가져옴  
    // .value를 붙이면 그 안의 내용을 가져옴
    var content = document.getElementById('wordarea').value;

	//count 라는 id를 가진 객체 내용 (0/200) 을 가져온 후 현재 글자수 넣어주기
	document.getElementById('count').innerHTML = '(' + content.length + ' / 200)';

	// 글자수 200초과 시 200자리까지만 표시
	if (content.length > 200){ 
		document.getElementById('wordcount').value = content.substring(0, 200);
	}
}

counter() //counter 함수 실행
</script>

글자 입력시 변화
200글자 초과 시

 

728x90
반응형