인프런 커뮤니티 질문&답변

신유빈님의 프로필 이미지

작성한 질문수

Slack 클론 코딩[백엔드 with NestJS + TypeORM]

NestJS 강좌 시작!

socket.io 사용시 랜덤하게 객체가 emit 됩니다.

해결된 질문

작성

·

547

·

수정됨

0

안녕하세요 제로초님~ 백엔드 개발자 지망생이자 제로초님의 팬인 신유빈입니다.

1개월 가량 하기 문제를 구글링 하며 여러 경우의 수를 찾아보았지만 이유를 찾지 못하여 질문드립니다.

질문드리고자 하는 내용은 이렇습니다.

socket.io 로 이벤트를 emit 할때, 같은 메서드를 사용함에도 객체에 따라 클라이언트에 전송될 때도 있고, 전송되지 않을 때도 있는데 그 원인을 찾지 못하고 있습니다.

현재 저는 신규게시물 혹은 댓글이 작성되었을때 모든 사용자에게 알림을 emit 하고자 합니다.

현재 3가지의 경우 중 A만 성공중인 상태입니다.

A : 테스트를 위하여 handleConnection 메서드에서 소켓에 연결한 사용자의 정보 객체를 message 로 전송시 성공

B : 게시물 작성 시 생성한 알림 메시지 객체를 message 로 전송시 실패

C: 댓글 작성 시 생성한 알림 메시지 객체를 message 로 전송시 실패

모든 케이스에서 클라이언트에게 메시지를 성공적으로 보내려면 어떻게 해야할지 도움을 주실 수 있을까요?

// 실행 동영상
https://youtu.be/AgLmcV53EvM


// 코드
깃허브 저장소 전체 코드
https://github.com/fog-of-war/dev-be/blob/zerocho/README.md

EventsGateway

https://github.com/fog-of-war/dev-be/blob/zerocho/src/events/events.gateway.ts#L55


// fow-be/src/events/events.gateway.ts

  /** 웹소켓 연결시 */
  handleConnection(@ConnectedSocket() socket: Socket, client: any) {
    const interval = setInterval(() => {
      const userInfo = socket.userInfo;
      this.sendMessage(userInfo);
    }, 5000);

    socket.on("disconnect", () => {
      clearInterval(interval);
    });
  }

  /** 메시지 전송 */
  sendMessage(message?: any) {
    console.log(" \n 🌠 sendMessage \n", message);
    this.server.emit("message", message);
    return Promise.resolve("Message sent successfully");
  }



AlertService
https://github.com/fog-of-war/dev-be/blob/zerocho/src/alert/alert.service.ts#L12


// fow-be/src/alert/alert.service.ts
// B: 게시물 작성시 실행되는 알림 서비스 코드

async createNotifyAlert(id: number) {
    const data = { alert_place_id: id, alert_type: "NOTIFY" as Type };
    const alert = await this.prisma.alert.create({ data: data });
    const result = await this.makePostAlertMessage(id);
    await this.eventsGateway
      .sendMessage(result)
      .then((response) => {
        // console.log("🌠 Notification sent successfully:", response);
      })
      .catch((error) => {
        console.error("🌠 Error sending notification:", error);
        // 전송 실패 또는 오류가 발생한 경우에 실행할 로직을 여기에 추가
      });
    return result;
  }
// fow-be/src/alert/alert.service.ts
// C : 댓글 작성시 실행되는 알림 서비스 코드

  async createActivityAlert(id: number) {
    const data = { alert_comment_id: id, alert_type: "ACTIVITY" as Type };
    const alert = await this.prisma.alert.create({ data: data });
    const result = await this.makeCommentAlertMessage(id);
    await this.eventsGateway
      .sendMessage(result)
      .then((response) => {
        // console.log("🌠 Notification sent successfully:", response);
      })
      .catch((error) => {
        console.error("🌠 Error sending notification:", error);
      });
    return result;
  }

 

 

// 출력결과

# A : 클라이언트에 전송 성공
 🌠 sendMessage 
 {
  sub: 2,
  user_email: 'shin.yubin18@gmail.com',
  iat: 1695983169,
  exp: 1695986769
}


# B : 클라이언트에 전송 실패
🌠 sendMessage 
{
  place_id: 1,
  place_name: '코엑스',
  region_name: '강남구',
  post_id: 65,
  post_created_at: 2023-09-29T10:27:28.371Z,
  post_image_url: 'https://fog-of-war.s3.ap-northeast-2.amazonaws.com/랜드마크/1코엑스.jpeg'

}

# C : 클라이언트에 전송 실패
🌠 sendMessage 
 {
  user_nickname: '구글신유빈',
  user_image_url: 'https://fog-of-war.s3.ap-northeast-2.amazonaws.com/defaultProfile.png',
  comment_id: 15,
  comment_text: '우왕',
  comment_created_at: 2023-09-29T10:52:24.960Z
}



스크린샷 2023-09-29 오후 7.22.09.png

답변 3

0

신유빈님의 프로필 이미지
신유빈
질문자

정말 감사합니다 해결되었습니다!!

image

0

신유빈님의 프로필 이미지
신유빈
질문자

연휴중에 답변주셔서 감사합니다.
공유주신 방식으로 socket.broadcast.emit() 진행해보았으나 TypeError: Cannot read properties of undefined (reading 'broadcast') 라는 에러가 발생하네요.



  /** 메시지 전송 */
  sendMessage(message?: any, @ConnectedSocket() socket?: Socket) {
    console.log(" \n 🌠 sendMessage \n", message);
    // const stringMessage = JSON.stringify(message);
    // console.log(stringMessage);
    socket.broadcast.emit("message", message);
    return Promise.resolve("Message sent successfully");
  }
 🌠 sendMessage 

 {

  sub: 2,

  user_email: 'shin.yubin18@gmail.com',

  iat: 1696039406,

  exp: 1696043006

}

{"sub":2,"user_email":"shin.yubin18@gmail.com","iat":1696039406,"exp":1696043006}

/Users/claire/fow/fow-be/src/events/events.gateway.ts:58

    socket.broadcast.emit("message", stringMessage);

           ^

TypeError: Cannot read properties of undefined (reading 'broadcast')

    at EventsGateway.sendMessage (/Users/claire/fow/fow-be/src/events/events.gateway.ts:58:12)

    at Timeout._onTimeout (/Users/claire/fow/fow-be/src/events/events.gateway.ts:46:12)

    at listOnTimeout (node:internal/timers:569:17)

    at processTimers (node:internal/timers:512:7)


스크린샷 2023-09-30 오전 11.43.15.png

 

 

 

socket.io의 버전 문제인가 싶어 socket.io@2.0.3 을 설치해보니 하기 오류가 나타나 삭제하였습니다.

src/auth/strategy/ws.strategy.ts:7:16 - error TS2665: Invalid module name in augmentation. Module 'socket.io' resolves to an untyped module at '/Users/claire/fow/fow-be/node_modules/socket.io/lib/index.js', which cannot be augmented.

7 declare module "socket.io" {



https://github.com/socketio/socket.io-redis-adapter/issues/478

https://velog.io/@yeonnex/npm-%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%B2%84%EC%A0%84%EC%9D%98-%EC%A4%91%EC%9A%94%EC%84%B1feat.-socket.io%EC%99%80undefined

스크린샷 2023-09-30 오전 11.44.41.png

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

이거 다시 ConnectedSocket 안 쓰던 코드로 되돌려놓으시고 posts.module.ts에서 eventsGateway 빼보세요. 위에 import로 eventsModule했는데 아래에 필요 없을겁니다.

강의에서 eventsGateway 프로바이더로 넣는 실수 하지 말라고 말씀드린 부분입니다.

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

https://stackoverflow.com/a/65909231

이런 식으로 ConnectedSocket 주입받아서 했던 것 같습니다