Node.js

node>채팅기능 만들기 1 (채팅방이 뭐임)

연습노트 2024. 9. 19. 09:36

여태까지 서버랑 통신할 때 GET, POST 요청 이런 걸로 통신하는 법을 배워봤는데

이걸 멋있는 말로 'HTTP 요청'이라고 부릅니다.

 

근데 일반적인 HTTP요청은 항상 유저가 먼저 요청을 해야 서버가 응답할 수 있는데

그런데 가끔 실시간 데이터를 요청하지도 않았는데 먼저 막 쏴주는 사이트들이 있습니다.

그런게 어떻게 가능하냐면 서버랑 유저가 통신하는 법이 몇개 더 있어서 그렇습니다. 

서버와 유저가 통신하는 법은 크게 3가지 정도가 있는데 

 

1. 일반 HTTP 요청

2. Server sent events

3. Websocket

각각 뭔지 알아봅시다.

 

 

 

 

1. 일반 HTTP 요청

 

우리가 지금까지 했던 GET, POST 등의 요청을 HTTP 요청이라고 부릅니다.

 

 

 

이건 비유하자면 편지같은겁니다.

편지는 쓸 때 마다 쓸데없이 주소적어야하고

내 정보도 적어야하고

거기까지 갔는지 확인도 해야하고 그러지 않습니까?

 실제 HTTP 통신할 때도 TCP라는걸 이용하기 때문에 실제로도 그런 번거롭고 오래걸리는 작업을 거칩니다. 

 

참고로 HTTP 2, 3 버전을 지원하는 서버를 만들면

HTTP요청을 좀 더 효율적으로 가볍게 만들 수 있는데

예를 들어 3버전 부터는 TCP가 아니라 더 가벼운 UDP를 쓰고 그런 식입니다.

근데 실 성능은 크게 차이는 안난다는 통계도 있습니다.

 

또 단점이 있는데 

꼭 유저가 먼저 편지를 보내야 서버가 응답해준다는 겁니다.

서버가 먼저 뭔가를 보내는 일은 없습니다.

그래서 이것만 쓰면 수동적인 서버기능 밖에 만들 수 없습니다.

 

 

 

 

 

 

2. Server sent events

 

둘째로 server sent events로 통신하는 방법도 있습니다.

- 서버에 한번 연결해두면 서버가 원할 때 맘대로 데이터를 유저에게 보내줄 수 있습니다.

- 서버에서 유저로 이렇게 일방향으로만 전달이 가능합니다. 

- 가벼워서 실시간 데이터 전달에 좋음

 

그래서 비유하자면 라디오같은거라고 생각하면 되겠습니다.

일방향으로 수신만 가능하니까요. 

참고로 이거 쓰고 싶으면 server sent events 쓰겠다고 서버에 HTTP요청을 날리면

서버가 이걸 server sent events로 업그레이드해주는 식으로 사용합니다.

 

 

 

 

 

 

3. Websocket

 

Websocket을 이용해서 유저와 서버가 통신할 수도 있는데

- 서버랑 유저가 자유롭게 실시간으로 데이터를 주고받을 수 있습니다.

- 유저가 먼저 보낼 수도 있고 서버가 먼저 보낼 수도 있습니다.

- 가벼워서 실시간 데이터 전달에 좋음

 

그래서 비유하자면 전화같은겁니다.

참고로 이거 쓰고 싶으면 websocket이라는 프로토콜을 사용하고싶다고 서버에 HTTP요청을 날리면

서버가 websocket으로 업그레이드해주는 식으로 사용합니다.

 

그럼 여기서 websocket이 가장 뭔가 좋아보이는데 그만큼 여러분이 코드짤 것도 많기 때문에

평소에는 그냥 일반 HTTP요청 하던거 그대로 쓰고 

- 서버에서 계속 유저에게 데이터를 푸시만 해주면 되는 경우엔 server sent events

- 채팅기능, 게임기능같은 실시간 양방향 통신을 구현하고 싶으면 websocket

쓰는게 좋습니다.

 

 

 

 

 

 

 

4. long polling

 

참고로 long polling 같은 방법도 있습니다.

 

 

(사진 : javascript.info)

 

서버로 HTTP 요청 날린 다음에 서버가 바로 응답.어쩌구()를 해주지 않고 계속 기다리는겁니다.

뭔가 새로운 내용이 들어오면 서버가 그제서야 응답.어쩌구()를 해주고

서버가 응답할 때 마다 다시 HTTP 요청을 날리는 테크닉같은 것인데

그럼 실시간 데이터를 계속 받아볼 수 있습니다.

실시간 메세지가 적을 때 유용합니다.

 

Node.js 서버는 long polling 써도 상관없는데

다른 서버는 응답 제때 안해주면 램초과로 서버가 다운될 수도 있습니다.

 

 

 

 

 

 

채팅기능을 만들어보자

 

그래서 오늘부터 Websocket 사용법을 알아볼 것인데

그냥 배우면 재미없으니 채팅기능을 만들면서 배워봅시다.

서버개발한다고 하면 그 정도는 알아야 할 거 아닙니까 

 

예를 들어 지금 있는 글들이 중고 물품 거래사이트라고 생각해봅시다.

그래서 이 글 작성자와 채팅을 하고싶은겁니다.

 

websocket을 쓰면 좋겠지만 그건 아직 안배웠기 때문에

일단 실시간은 신경쓰지말고 채팅기능부터 구현해봅시다. 

지금까지 배운걸로 알아서 다 할 수 있습니다.

 

한글로 설명부터 하면 될텐데

근데 한글로 설명하라고하면 이런 식으로 대충작성하는 분들이 있습니다.

1. 채팅페이지 들어가서 

2. 채팅메세지를 보낸다 

 

 

▲ 기능 설명할 땐 저딴 식으로 대충하면 하는 의미가 없습니다.

아무것도 모르는 7살 어린애한테 설명하듯이 자세히 구체적으로 적도록 합시다.

잘 생각해보십시오 카톡이나 중고거래 앱같은거 켜보시면

앱 처음 설치하고 켜자마자 채팅페이지가 마법처럼 나오고 채팅을 막 보낼 수 있습니까?

님 마법사임?

 

 

 

 

- 일단 누구랑 채팅하고 싶은지 골라서 채팅방을 만들어야하고

- 채팅방 목록도 있고

- 채팅방 하나 누르면 채팅메세지 보낼 수 있는 페이지도 있습니다.

 

 

그래서

1. 글 주인에게 채팅요청하면 채팅방을 하나 만들어줌

2. 내가 들어있는 채팅방 목록도 볼 수 있는 페이지가 필요함 

3. 채팅방 하나 선택하면 채팅방의 상세페이지가 뜸

채팅방 상세페이지에는 인풋과 버튼이 있음

4. 메세지 보내면 그걸 DB에 저장해주고 상세페이지에도 실시간으로 메세지들을 띄워줘야함

 

카톡이나 당근마켓 동작방식 그대로 따라해봤습니다.

그대로 구현하면 성공일듯요

 

 

 

 

 

채팅방이 뭐임

 

근데 채팅방을 만들어준다는게 뭐죠?

채팅방의 정체가 뭐임?

 

여러분들 혼자 기능개발할 때 팁이 하나 있는데 

웹에 있는 거의 모든 기능은 그냥 글발행 기능이랑 똑같습니다. 

알아서 코드 잘 짜고 싶으면 잘 기억해두도록 합시다.

 

 

 

- 쇼핑몰의 주문기능도 그냥 글발행 기능입니다.

근데 글에 주문수량 가격 상품명 이런게 적혀있을 뿐임

 

 

 

- SNS의 알림같은 것도 그냥 글입니다.

누가 어떤 글에 좋아요 했는지 적혀있을 뿐입니다.

 

채팅방을 만들어준다는 것도 실은 그냥 글발행 기능입니다. 

글에 채팅참여자는 누구인지 채팅내용은 뭐가 있었는지 그런게 적혀있을 뿐입니다.

 

 

 

 

▲ 그래서 누가 채팅방 개설원하면 document 하나 DB에 발행하면 끝인데

- 채팅 참여자들이 누군지

- 어떤 채팅메세지들이 있었는지

적어두면 될 것 같습니다. 

메세지는 1억개 이렇게 많을 수 있으니 다른 document로 빼는게 좋을 수도 있습니다.

 

이런 장면 어디서 많이 본거같은데

그래서 채팅방 / 채팅메세지는

그냥 글 / 댓글 기능이랑 아예 똑같습니다.

그래서 집에가서 알아서 구현해옵시다.

 

 

 

 

오늘의 숙제 :

 

1. 글 주인에게 채팅요청하면 채팅방을 하나 만들어줌

2. 내가 들어있는 채팅방 목록도 볼 수 있는 페이지가 필요함 

3. 채팅방 하나 선택하면 채팅방의 상세페이지가 뜸

여기까지 구현해옵시다.

실시간 채팅 이런건 저랑 같이 해볼 것임

 

채팅방 상세페이지 레이아웃

 

.chat-screen { width: 100%; }
.chat-box { margin-top: 15px; display: flex; }
.chat-box span { padding: 10px; background: #eee; }
.mine { justify-content: end; }
.chat-input {
  margin-top: 15px;
  padding: 10px;
  border-radius: 5px;
}
.chat-button {
  padding: 10px;
  border : none;
  background : lightgrey;
  border-radius: 5px;
}

 

<div class="detail-bg">
      <div class="chat-screen">
        <div class="chat-box"><span>안녕하세요</span></div>
        <div class="chat-box"><span>안녕하세요</span></div>
        <div class="chat-box mine"><span>안녕하세요</span></div>
      </div>
    </div>
    <div class="chat-form">
      <input class="chat-input">
      <button class="chat-button">전송</button>
</div> 

이것도 상세페이지니까

detail.ejs 파일내용 복사한 다음에 안의 html만 이걸로 바꾸면 이쁠듯요