정글님탑갱점
80
2021-01-19 18:20:56
5
220

socket.io 카카오톡 같은 채팅 코드 질문 드립니다. (Node.js + Socket.io)


안녕하세요! 

추운날 코딩하시느라 다들 고생이 많으십니다!! 

다름이 아니라 카카오톡 같은 채팅 프로그램을 구현하려고 하는데 궁금한 점이 있어서 문의를 드립니다...


1.  Socket이 접속 할 때마다 ID가 바뀌는데 채팅 기록을 관리하는 경우 아래와 같이 DB에서 관리를 하면 되는지 궁금합니다.    

프론트단에서 소켓으로 넘길 때 내 아이디와 상대방 아이디를 함께 넘겨서 아이디로 관리를 하면 되지 않을까 싶어서요 ㅠㅠ...  아니라면 힌트를 조금만 주시면 제가 더 공부를 해보겠습니다.

내아이디 | 상대방아이디 | 채팅방이름(room) | 메세지                  | 읽음 여부 

apple      |  banana          |       fruits                | 과일사실래요?!  |  0:읽지않음, 1: 읽음


2. 아래와 같이 다른 사람의 최근 메세지를 나타내어 주려면 항상 소켓이 연결이 되어 있어야 할 것 같은데... 이게 맞는지 우선 궁금합니다. 

상대방이 메세지를 보내면 그걸 DB에 저장하고 성공시 해당 채팅방(room)에 있는 모든 아이디에게 소켓으로 뿌리면(앱푸시도 함께?) 될 것 같은데 사실 감이 잘 안잡히네요 ㅠㅠ ... 

  1. 메세지를 전송한다 

  2. DB에 저장한다

  3. 메세지 내용을 해당 채팅방(room)에 있는 모든 아이디에게 뿌린다.

  4. 프론트에서는 해당 이벤트를 받으면 메세지 카운트를 업데이트 한다.

-- ↓ 맞는지 모르겠습니다 ㅠㅠ 

  5. 앱이 종료된 상태라면 재 접속시 채팅 리스트에서 유저아이디를 기반으로 읽지 않음인 카운트를 모두 가져와 업데이트한다....


코린이가 힘을 내서 코딩을 할 수 있도록 조금만 도와주시면 정말 감사드리겠습니다!

다들 새해 복 많이 받으세요!! 

0
  • 답변 5

  • esrse
    1k
    2021-01-19 19:10:18 작성 2021-01-19 19:15:03 수정됨

    날씨가 추워도 건물 안에서만 생활하기 때문에 코딩하는 게 추울 일은 없는 거 같습니다.


    채팅방은 subscribe/publish 구조로 만들면 될 듯합니다.

    따라서.. 상대방아이디는 필요 없을 거 같구요,

    서버에 저장돼야하는 클래스는 메시지와, 채팅방이 가장 주요할 거 같아요.

    메시지에 프러퍼티는

    - 보낸 사람 id

    - 보낸 시각

    - 채팅방 아이디

    - 텍스트

    - 안읽은 사람 id 목록


    채팅방에 프러퍼티는

    - 채팅방 id

    - 참여중인 사람 id 목록

    - 채팅방 제목


    토이프로젝트라면 보안적인 부분을 빼고 일단 쉬운 구조로 만들어볼 수 있을 거 같습니다. 원래는 사용자가 채팅방id, 보낸시각 등을 날조한 데이터를 서버로 보내지 못하도록, 서버단에서 검사하는 로직이 필요한데, 그런거는 다 빼고.. 그냥 쉽게 프론트에서 메시지를 만들어서 서버로 보내는 거로 하죠..

    프론트에서 사용자가 메시지를 치면, 메시지 객체를 만들고, 거기 프러퍼티를 담아서 서버로 보냅니다.

    서버로 보낼때는 객체를 json이나 protobuf 같은걸로 serialize해서 보내면 됩니다.

    서버에서는 메시지를 DB로 저장하고, 메시지를 보낸 클라이언트한테 OK응답을 보냅니다.

    그리고 그 메시지를 그대로 메시지를 보낸 사람 포함해서 채팅방 전체 인원에게 전송합니다.


    채팅방 프로그램을 꺼뒀다가 나중에 다시 채팅방으로 돌아왔을 때는 최근 대화 내용을 보여줘야 합니다.

    그런 경우에는 디폴트로 얼만큼을 보여주겠다는 정책을 세우고 그걸 따르면 됩니다. 예를 들어서 대화방의 최근 100개만 보여주겠다든지 정하면 되고, 스크롤 해서 위로 올라갔을 때, 과거꺼를 조회하는데, 채팅방에 가장 오래된 메시지의 id를 서버에게 알려주면, 서버는 그 id보다 더 오래된 것만 필터링해서 지정된 몇개를 꺼내어 응답하면 됩니다.

  • 정글님탑갱점
    80
    2021-01-19 19:59:48

    esrse

    정말 자세한 답변 감사드립니다 =)

    하나만 더 여쭤봐도 될까요?


    Sub/Pub 구조로 만들면 된다고 하셨는데 

    채팅방을 생성하면서 동시에 상대방을 초대하는 방법은 이렇게 하면 될까요?

    1. 채팅방 생성 (사용자 초대 시작)

    2. 서버단에서는 프론트에서 받은 상대방 아이디를 가지고 같은 채팅방 이름으로 DB에 Insert

    예)   [유저1]가 [유저2]초대 [채팅방입니다]로 채팅방 이름 생성 DB저장

            [유저2]의 아이디도 똑같이 [채팅방입니다]의 방 이름으로 DB에 저장


  • 피자7
    637
    2021-01-19 20:21:00

    질문이 너무 불분명한데여

    뭘 구현하려는건지 정확히 설명해주세여


    socket.io는 한번 접속하면 그 페이지를 나갈때까지 클라이언트랑 서버랑 연결을 계속 유지하는상태입니다

    그래서 실시간 알림받는게 가능한거고여

    새로고침할때마다 연결끊고 새로 연결하는거라 id도 매번 바뀝니다


    님이 지금만들려는건 말그대로 카카오톡같은 앱이면 웹상에서는 이메일기능하고 다를거 없어보이네요

  • 정글님탑갱점
    80
    2021-01-19 20:40:47

    피자7 

    안녕하세요.

    말 그대로 카카오톡 채팅 같은 채팅프로그램을 만들려고 합니다.

    카톡의 채팅방 리스트가 보여지고 실시간으로 채팅이 가능한 기능을 만들려고 합니다.


    예를들어

    1:1상담을 실시간으로 A,B,C상담사에게 했다고 하면

    사용자에게 A, B, C 채팅방 목록이 보이고 해당 방에서 실시간으로 채팅이 가능한 프로그램 입니다.


    말씀해주신 것처럼 소켓 ID가 계속 변하는데 나중에 다시 접속을 해도 채팅 기록이 남아있게 하려면 어찌 해야하는질 모르겠네요... 

  • esrse
    1k
    2021-01-19 21:10:39 작성 2021-01-19 21:13:53 수정됨

    토이프로젝트라고 치고, 개인 식별기능은 간단히 프론트에서 사용자가 입력한 id로 하면 될 거 같습니다. 서비스라고치면, 이렇게해선 안되고, 구글/페이스북 등의 oauth2를 활용하거나 서비스 자체적인 사용자 계정 정보를 디비에 관리하고 아이디/패스워드 입력으로 로그인 기능을 만들어야 할 것입니다. 로그인 된 이후에는 서버가 알고있는 매우 긴 랜덤 값 같은 거를 클라이언트에게 토큰처럼 제공을하는 거죠. 클라이언트는 요청을 할 때마다 그 토큰을 같이 서버로 보내고, 서버에서는 그 토큰이 유효한지 확인하고, 그 토큰이 실제 어떤 사용자 id와 대응되는지 알아냅니다. 그 토큰은 임시이기 때문에, 그 토큰에 대응되는 실제 디비의 사용자 id를 알아낼 수 있는 별도의 임시 테이블 같은 걸 들고 있어야겠죠..? 그리고 채팅이 수행되는 TCP 커넥션은TLS같은 걸로 암호화해서, 그 난수 토큰이 노출되지 않게 방어해야할 것이고요.


    아무튼, 토이프로젝트라고 치고 사용자가 입력한 id를 그대로 믿읍시다.


    프론트 클라이언트는 RoomCreationCommand라는 객체를 생성합니다.

    RoomCreationCommand의 프러퍼티로는

    - 채팅방에 참여한 id 목록

    - 채팅방 이름


    이걸 서버로 보내면, 서버는 채팅방을 DB에 저장하고 클라이언트에게 OK를 응답합니다.

    그리고 아까 받은 RoomCreationCommand에 있는 프러퍼티들과 새로 발급한 채팅방 id를 합쳐서 채팅방 객체를 만듭니다. 간단하게 ChatRoom 객체라고 하죠. 

    그리고 채팅방에 초대된 모든 사용자에게 ChatRoom를 보냅니다.

    그러면 프론트는 채팅방 목록에 새 채팅방을 추가합니다.


    나중에 브라우저 껐다가 다시 켰을 때,

    아이디 적으면, 그 아이디에 해당하는 모든 채팅방 목록을 서버에 조회하면 서버는 그 유저 id가 속한 모든 채팅방을 찾아서 ChatRoom목록을 만들어서 응답하면 됩니다.

  • 로그인을 하시면 답변을 등록할 수 있습니다.