Project/실시간 채팅 서비스 개발

Socket.io를 이용한 실시간 채팅 구현 - 2. 기능 구현

둉이 2021. 5. 3. 15:57
 

Socket.io를 이용한 실시간 채팅 구현 - 1. 환경설정

회사 업무를 하면서 실시간 채팅 기능을 구현할 기회가 생겼다. 이사님이 솔루션 사서 개발하라고 하셨지만 예전부터 소켓 통신 관련하여 공부도 해보고 싶었던 참이고, 회삿돈이 아깝기도 해

guiyomi.tistory.com

 

앞 파트에서 환경 설정을 포함한 기본 셋팅을 마쳤다.

 

오늘은 채팅 기능을 구현하기 위한 과정을 적어보려고 한다.

 

실시간 메시지 기능 구현

가장 핵심적인 기능이자 가장 쉬운 기능이다. 이건 그냥 구글링해도 나온다!

채팅 리스트가 업데이트 될 때마다 리스트를 가져와서 유저가 접속한 채팅방의 메시지만 화면에 보여준다.

 

1. Web Js 코드(일부)

socket.on('chatList', (data) => {
	chatList = data;
	let msg = chatList[chatList.length - 1];
	if (msg.room == currentRoomNo) addChat(msg.sendId, msg.chatContent);
});

 

2. Node.js 코드

    socket.on('message', (data) => {
        chatList.push(data)
        io.emit('chatList', chatList)
    })

 

3. 완성작

활동중 기능 구현

사용자가 채팅 페이지로 접근하면 채팅방 목록 내 사용자 이름 옆에 활동중이라는 표시가 뜨게 한다.

이것도 마치... 페이스북 메신저처럼?

사용자가 채팅 페이지에 접속할 경우 enter, 해당 페이지에서 나갈 경우에는 leave로 처리한다.

(원래는 window.onbeforeunload을 이용하여 구현하려고 했지만 저걸 쓰려면 무조건 '이 페이지에서 나가시겠습니까?' 경고창이 뜨나 보다. 아무튼 사용 불가)

 

1. Web Js 코드(일부)

// 페이지 공통 헤더에 삽입
var socket = io("https://chat.dongjakin.com/");
socket.emit("leave", '${userId}');
// 채팅 페이지에만 삽입
socket.emit('enter', $("#userId").val());

 

2. Node.js 코드

    socket.on('enter', (uid) => {
        onUser.push(uid)
        onUser = [...new Set(onUser)]
        io.emit('onUser', onUser)
        io.emit('onTypingUser', onTypingUser)
    })
  
    socket.on('leave', (uid) => {
        onUser.indexOf(uid) != -1 && onUser.splice(onUser.indexOf(uid), 1)
        onTypingUser.indexOf(uid) != -1 && onTypingUser.splice(onTypingUser.indexOf(uid), 1)
        io.emit('onUser', onUser)
    })

 

3. 완성작

다른 아이디로 왔다갔다 하면서 찍었음

 

타이핑 기능 구현

 

페이스북 메신저처럼 각 사용자들의 타이핑 여부를 알려주는 기능이다.

사용자들이 메시지 창에 타이핑을 할 때마다 해당 메시지의 길이를 검사하여 0이면 notyping, 1 이상이면 typing으로 처리한다.

 

1. Web Js 코드(일부)

socket.on('onTypingUser', (data) => {
	onTypingUser = data;
	
	if (data.indexOf($("#userId").val()) > -1) {
		$("#ask-typing").show();
	}
	else {
		$("#ask-typing").hide();
	}
	switch(list[currentRoomIdx].me) {
		case 'me':
			if (data.indexOf($("#menteeId").val()) > -1) {
				$("#answer-typing").show();
			}
			else $("#answer-typing").hide();
			break;
		case 'you':
			if (data.indexOf($("#mentoId").val()) > -1) {
				$("#answer-typing").show();
			}
			else $("#answer-typing").hide();
			break;
	} 
	scrollDown();
});

 

2. Node.js 코드

    socket.on('typing', (uid) => {
        onTypingUser.push(uid)
        onTypingUser = [...new Set(onTypingUser)]
        io.emit('onTypingUser', onTypingUser)
    })
  
    socket.on('notyping', (uid) => {
        onTypingUser.indexOf(uid) != -1 && onTypingUser.splice(onTypingUser.indexOf(uid), 1)
        io.emit('onTypingUser', onTypingUser)
    })

 

3. 완성작

디자이너님이 만들어 주신 귀여운 ... 이미지

 

마무리

구글님의 가호로 어렵지 않게 기능을 만들 수 있었다.

다음에는 로컬에서 구현한 소스를 CentOS 7 기반 서버에 포팅하는 시간을 가져보자!
항상 서버에 올리면 기능이 먹통이 돼 왔기에... 정말 기대된다!