본문 바로가기
개발 기초 다지기

socket io 1:1 채팅 구현 (1)채팅방 DB 저장

by 너의고래 2024. 8. 1.
반응형

socket.io를 통한 1:1 채팅을 구현했다. 이 과정을 진행하며 여러 부분에서 고민이 되었는데, 그 중 고민되었던 부분들을 정리해보려 한다.

1. 채팅방 각 유저 id 에 대해 각자의 DB 칼럼에 어떻게 알맞게 넣을 것인가?

문제

이번에 구현하는 채팅 기능의 경우 2가지 도메인에서 접근이 가능하다. 1. 서비스 유저 2.CP(Content Provider) 그렇다보니 chat 테이블의 칼럼도 userId와 cpId로 나눠져있다. 채팅방에 입장할시 서비스 유저 입장에서는 CP의 ID를 입력하고 들어올 것이고, CP의 입장에서는 서비스 유저의 ID를 입력하고 들어올 것이다. 이 상황에서 데이터베이스에 채팅방을 저장할 때 cpId와 userId가 어떻게 적절히 분류되어서 들어가게 만들 수 있을 것인가?

해결과정

처음에는 반대되는 2가지 상황에 바로 생각이 나지 않아 고민을 많이했다.

1. jwt 토큰에서 로그인 한 user의 ID를 빼낸다.

2. body에서 userId 또는 cpId를 받는다.

 

1번같은 경우, 항상 같은 key값으로 들어오지만, 2번은 주체가 누구냐에 따라 다른 key값이 들어오기 때문에 2번에서 조건을 넣어주기로 했다.

 결국 서비스 유저의 경우, 클라이언트에서 cpId를 입력받고, 데이터베이스 userId 칼럼에 jwt에서 추출한 Id값을, cp 칼럼에 입력 받은 cpId를 저장한다.

 

<구현해낸 코드>

  //채팅방 생성
  @SubscribeMessage('joinRoom')
  async handleJoinRoom(@ConnectedSocket() client: Socket, @MessageBody() data: { cpId?: string; userId?: string }) {
    try {
      let chatRoom
      const loginId = client.data.user.uid

      if (!data.cpId && data.userId) {
        const cpId = loginId
        const userId = data.userId
        this.logger.log('joinRoom 이벤트 수신 - 사용자:', JSON.stringify({ cpId, userId }))
        chatRoom = await this.chatService.findCreateChatRoom(cpId, userId)
      } else if (!data.userId && data.cpId) {
        const cpId = data.cpId
        const userId = loginId
        this.logger.log('joinRoom 이벤트 수신 - 사용자:', JSON.stringify({ cpId, userId }))
        chatRoom = await this.chatService.findCreateChatRoom(cpId, userId)
      } else {
        throw new Error('cpId 또는 userId가 제공되지 않았습니다.')
      }

      client.join(chatRoom.uid.toString())
      client.emit('joinedRoom', chatRoom.uid)
      this.logger.log('채팅방에 입장:', chatRoom.uid)
    } catch (error) {
      this.logger.error(`joinRoom 이벤트 처리 중 에러 발생: ${error.message}`)
    }
  }

 

 

이 조건 저 조건 넣어보다가 완성시킨 로직.

처음에는 단순하게 각 Id가 있을 때의 조건을 넣어주었는데,  변수가 생기는 경우가 있어 강력하고 확실하게 두 ID의 존재 여부를 && 논리 연산자로 묶어주었다.

 

 

 

반응형

댓글