개요
모클리는 1인 셀러와 제조 공장을 온라인으로 연결하는 혁신적인 플랫폼으로, 특히 화장품 분야에서 제품을 제작하고자 하는 1인 셀러들이 전문적으로 생산을 담당하는 공장과 간편하게 소통할 수 있는 창구 역할을 합니다.
기획 초기에 1인 셀러와 공장 관계자 간의 소통의 어려움이 부각되었습니다. 특히, 1인 셀러 시장이 급증하면서 문의 전화가 증가하고, 기업 대상으로 업무를 진행해왔던 관계로 고객 서비스 프로세스가 부족하다는 공장 관계자들의 의견이 나왔습니다. 이에 따라, 일정상의 이유로 제외되었던 채팅 기능을 빠른 시간 안에 구현하기로 결정하였습니다.
이런 상황에서 저희는 Long Polling 기술을 사용해 채팅 기능을 구현했는데요, 채팅을 구현 방식 총 3가지와 Long Polling 을 선택한 이유, 그리고 저희 프로젝트에 어떻게 구현했는지 기록합니다.
채팅 구현 방식
저희 팀에서는 채팅 구현을 아래 3가지 방식으로 논의했습니다.
- Poling
- Long Polling
- Websokect
Polling
폴링은 클라이언트가 일정 주기로 서버에게 필요한 데이터를 요청하는 방식입니다. 구현 난이도는 제일 낮지만 서버에 변경사항이 없어도 계속 요청을 보내 서버에 부담을 주게 되는 것이죠. HTTP Connection을 유지하기 위한 비용이 계속 발생할 뿐더러 데이터가 업데이트가 되었다고 해도 다음 폴링 주기까지 기다려야 업데이트가 되는 방식이기 때문에 실시간성이 중요한 상황에서는 적합하지 않은 방식일 수 있습니다.
Long Polling
Long Polling은 이름에서 알 수 있다시피 Polling에서 변형된 형태인데요, 클라이언트가 서버에 데이터를 요청하면 서버는 즉시 응답하지 않고, 데이터가 업데이트되거나 특정 이벤트가 발생할 때까지 대기하게 하는 것입니다. 주로 서버에서 클라이언트로 데이터를 push하는 방식이며 Polling과 비교해서 실시간성, HTTP Connection 유지에서 이점을 가질 수 있게 됩니다.
하지만 데이터가 빈번히 바뀌는 상황에서는 Polling 방식보다 많은 요청과 응답을 하게 되는 경우가 발생한다고 합니다.
Websocket
기본적으로 HTTP는 단방향 통신이기 때문에 서버가 먼저 클라이언트에게 응답할 수 없습니다. 하지만 Websocket은 HTTP 프로토콜 대신 WS 프로토콜을 이용해 양방향 통신을 가능하게 합니다. TCP라는 프로토콜 기반으로 동작한다고 합니다.
- Opening Handshake
- Data Transfer
- Closing HandShake
Opening Handshake
클라이언트가 서버에세 Websocket 연결을 요청합니다.
GET /chat HTTP/1.1
Host: localhost:3000
Upgrade: websocket // Websocket 요청시에 반드시 websocket 값을 가지며 없으면 cross-protocol attack이라고 간주하고 중지
Connection: Upgrade
Sec-WebSocket-Key: {key} // 요청 확인용 key값
Sec-WebSocket-Protocol: chat, superchat // 사용하고자하는 하나 이상의 Websocket 프로토콜 지정
Sec-WebSocket-Version: 13 // 클라이언트가 사용하고자 하는 Websocket 버전
Origin: http://localhost:3001
클라이언트가 요청 헤더에 "Upgrad: websocket"을 포함시키고, 서버는 이를 이해하고 웹소켓으로 업그레이드할 의사가 있으면 101 Switching Protocols 응답을 반환합니다.
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: {key}
Sec-WebSocket-Protocol: chat
핸드쉐이크가 성공하며 위처럼 Websocket으로 switching 됩니다
Data transfer
웹소켓은 양방향 통신입니다. 사용자들끼리 메시지 주고 받게될 때 메시지를 웹소켓 프레임이라고 합니다. 즉 프레임 단위로 통신을 하게 되는 것이죠
메시지 이외에도 여러 형태의 프레임이 있는데, Websocket Switching 이후 커넥션이 유지되고 있는지 확인할 때 사용하는 프레임으로 ping/pong frame라는 것이 있습니다. 클라이언트나 서버에서 자동으로 생성해서 커넥션 상태를 확인하는데, 이를 Heartbeat라고 합니다.
Close handshake
close frame 전송을 통해 클라이언트, 서버 양측 누구나 연결을 종료할 수 있습니다.
우리가 Polling을 선택한 이유
- 채팅 기능은 메인서비스가 아니다.
- 일반 사용자가 고객사에게 문의 사항이 있을 때 80프로는 전화연결을 통해 이루어진다고 예상했습니다.
- 1:1 채팅만 존재
- 여러 사용자가 동시에 접속해 이벤트가 많이 발생하는 일이 적다고 생각했습니다.
- 구현이 비교적 쉽다
- 채팅 기능구현에 약 3일 정도에 기간이 책정되어있어 웹소켓 방식으로 구현&테스트하기에는 시간이 촉박하다고 생각했습니다.
모클리 채팅 세부 구현 방식
서버에서는 보낸이와 메시지 두 가지 데이터를 보내줍니다. 이를 토대로 아래 두 가지 기능을 함께 구현하기 위해 데이터 형식을 수정했습니다.

- 날짜가 바뀌면 구분선이 생깁니다.
- 같은 시간에 메세지를 보낸 경우 메세지를 보낸 시간이 맨 마지막 메세지에 하나만 보입니다.
// 전 -------------------------
{
user: "상대방",
},
{
messages: [
"안녕하세요"
],
},
{
user: "나",
},
{
messages: [
"반갑습니다.",
"잘 지내시죠?",
],
},
{
user: "나",
},
{
messages: [
"수고하세요!",
],
}
// 후 -------------------------
[
{
key: "202401311940-상대방",
messages: [
"안녕하세요"
],
},
{
key: "202401311941-나",
messages: [
"반갑습니다.",
"잘 지내시죠?",
],
},
{
key: "202401311942-나",
messages: [
"수고하세요!",
],
}
]
1. 개별의 배열로 전달되는 메세지들을 하나의 객체에 담아
2. 기존의 'user'를 '시간 - 보낸사람' 형식의 key 값으로 대체하고
3. key 값의 date가 변경되면 구분선을 추가하고, key가 동일한 경우에는 메시지를 보낸 시간을 맨 마지막 메시지에만 표시되도록 구현했습니다.
롱 폴링
ko.javascript.info
웹소켓
ko.javascript.info
'Tech > Moqly (모클리)' 카테고리의 다른 글
| Webpack 알아보기 (0) | 2024.07.11 |
|---|---|
| Next13 - Amplify 배포 에러 디버깅 (0) | 2024.03.06 |
| [모클리] Next13 을 선택한 이유 (0) | 2024.02.06 |
| [모클리] Sass(SCSS) 사용성 개선하기 (0) | 2024.02.01 |
| [모클리] OAuth2.0 활용해 간편로그인 구현하기 (1) | 2024.01.30 |
