Vue와 ZEGO SDK를 활용한 웹 멀티 유저 실시간 화상 채팅 구현

웹 환경에서 실시간 멀티 유저 오디오 및 비디오 통신은 다양한 인터랙티브 서비스의 핵심 기능입니다. 이 글에서는 Vue 프레임워크와 ZEGO Express SDK를 사용하여 복잡한 설정 없이 안정적인 다중 화상 채팅 기능을 구축하는 방법을 다룹니다.

주요 적용 시나리오

  • 기업용 화상 회의: 원격 근무 및 팀 협업을 위한 다중 참여자 실시간 커뮤니케이션.
  • 온라인 소규모 클래스: 교육 환경에서의 실시간 강의, 질의응답 및 조별 토론.
  • 소셜 비디오 채팅: 소셜 네트워크 서비스 내 그룹 영상 통화 및 커뮤니티 상호작용.
  • 원격 의료 및 고객센터: 대면 상담이 필요한 의료 및 고객 지원 서비스.

사전 준비 사항

개발을 시작하기 전에 다음 사항이 완료되어야 합니다.

  1. ZEGO 콘솔에서 프로젝트를 생성하고 유효한 AppIDServer 주소를 발급받아야 합니다.
  2. 프로젝트에 ZEGO Express SDK가 정상적으로 설치되어 있어야 합니다.

핵심 구현 단계

1. 엔진 인스턴스 초기화

ZEGO SDK를 사용하기 위해 ZegoExpressEngine 인스턴스를 생성합니다. 발급받은 AppID와 서버 주소를 전달합니다. (SDK 3.6.0 이상 버전에서는 서버 주소를 빈 문자열이나 임의의 값으로 설정할 수 있습니다.)

import { ZegoExpressEngine } from 'zego-express-engine-webrtc';

const appConfig = {
  appId: 123456789, // ZEGO 콘솔에서 발급받은 AppID
  serverUrl: ''     // 3.6.0 이상 버전에서는 빈 문자열 허용
};

const engine = new ZegoExpressEngine(appConfig.appId, appConfig.serverUrl);

2. 룸 입장 및 유저 상태 알림 활성화

다중 채팅 환경에서 다른 참여자의 입장 및 퇴장을 감지하려면 룸 로그인 시 userUpdate 옵션을 반드시 true로 설정해야 합니다.

const roomCredentials = {
  roomId: 'room_1001',
  token: 'your_generated_token',
  userInfo: { userID: 'user_01', userName: 'Alice' }
};

const roomOptions = {
  userUpdate: true // 유저 상태 변경 콜백 활성화
};

try {
  const loginResult = await engine.loginRoom(
    roomCredentials.roomId,
    roomCredentials.token,
    roomCredentials.userInfo,
    roomOptions
  );
  console.log('룸 입장 성공:', loginResult);
} catch (error) {
  console.error('룸 입장 실패:', error);
}

3. 이벤트 리스너 등록

룸 내의 유저와 미디어 스트림의 변화를 실시간으로 처리하기 위해 콜백 이벤트를 등록합니다. 주의: 이벤트 리스너는 반드시 loginRoom을 호출하기 전에 등록되어야 합니다.

유저 상태 변화 감지
roomUserUpdate 이벤트를 통해 참여자의 증감을 처리합니다.

engine.on('roomUserUpdate', (roomId, updateType, userList) => {
  console.log(`룸 ${roomId} 유저 변경 감지: ${updateType}`);
  
  switch (updateType) {
    case 'ADD':
      userList.forEach(user => {
        console.log(`새로운 유저 입장: ${user.userID}`);
        // UI에 새로운 유저 프로필 또는 비디오 뷰 추가 로직
      });
      break;
    case 'DELETE':
      userList.forEach(user => {
        console.log(`유저 퇴장: ${user.userID}`);
        // UI에서 퇴장한 유저의 뷰 제거 로직
      });
      break;
  }
});

스트림 상태 변화 감지
roomStreamUpdate 이벤트를 통해 미디어 스트림의 생성과 삭제를 감지하고, 스트림 구독(재생) 또는 구독 중지를 수행합니다.

engine.on('roomStreamUpdate', async (roomId, updateType, streamList) => {
  if (updateType === 'ADD') {
    for (const stream of streamList) {
      console.log(`새로운 스트림 감지: ${stream.streamID}`);
      const videoElement = document.getElementById(`video-${stream.streamID}`);
      // 스트림 구독 및 재생
      await engine.startPlayingStream(stream.streamID, { audio: true, video: true });
      // videoElement에 스트림 바인딩 (SDK 매뉴얼 참조)
    }
  } else if (updateType === 'DELETE') {
    for (const stream of streamList) {
      console.log(`스트림 삭제 감지: ${stream.streamID}`);
      // 스트림 구독 중지 및 리소스 해제
      await engine.stopPlayingStream(stream.streamID);
    }
  }
});

4. 스트림 게시 및 구독

로컬 미디어 스트림을 생성하고 룸에 게시(Publish)하는 과정은 공식 문서의 기본 스트림 게시 및 구독 가이드를 참조하여 구현합니다. createStream으로 로컬 스트림을 생성한 후 startPublishingStream을 호출합니다.

주요 API 레퍼런스

API 메서드 기능 설명
ZegoExpressEngineSDK 엔진 인스턴스 초기화
loginRoom지정된 룸에 입장
logoutRoom현재 입장한 룸에서 퇴장
createStream로컬 오디오/비디오 스트림 생성
startPublishingStream로컬 스트림을 서버로 게시(푸시)
stopPublishingStream스트림 게시 중단
startPlayingStream원격 스트림 구독 및 재생(풀)
stopPlayingStream원격 스트림 구독 중단
roomUserUpdate룸 내 유저 입장/퇴장 이벤트 콜백
roomStreamUpdate룸 내 스트림 생성/삭제 이벤트 콜백

주의사항 및 트러블슈팅

  • HTTPS 환경 필수: 웹 브라우저의 보안 정책상 카메라와 마이크 접근을 위해서는 HTTPS 환경이어야 합니다. (단, localhost는 예외로 테스트 가능합니다.)
  • 이벤트 바인딩 순서: roomUserUpdateroomStreamUpdate 리스너는 반드시 룸에 로그인(loginRoom)하기 전에 등록해야 초기 상태 데이터를 놓치지 않습니다.
  • userUpdate 옵션: 다중 유저 환경에서 입장/퇴장 알림을 받으려면 로그인 시 userUpdate: true 설정이 필수적입니다.
  • 리소스 정리: 컴포넌트가 언마운트되거나 통화가 종료될 때는 반드시 stopPublishingStream, stopPlayingStream을 호출하고 logoutRoom으로 룸에서 퇴장하여 메모리 누수와 하드웨어 점유를 방지해야 합니다.
  • SDK 버전 호환성: SDK 3.6.0 미만 버전을 사용할 경우 server 파라미터에 정확한 서버 주소를 입력해야 하며, 빈 문자열을 전달하면 초기화에 실패합니다.

태그: vue ZEGO SDK WebRTC JavaScript Real-time Communication

5월 24일 07:04에 게시됨