LiveKit + React + TypeScript

임성룡·2025년 8월 20일

FE

목록 보기
1/1

LiveKit은 WebRTC 기반의 실시간 통신을 위한 오픈 소스 플랫폼입니다. livekit-client는 이 플랫폼에 접속하여 영상/음성 스트림을 송수신하는 클라이언트 라이브러리이며, React 개발을 더 쉽게 하기 위해 @livekit/react-components 같은 보조 라이브러리도 제공됩니다.

LiveKit 핵심 개념

LiveKit 클라이언트를 이해하기 위해서는 다음의 주요 개념을 아는 것이 중요합니다.

  • Room (방): 여러 참가자가 모여 소통하는 가상 공간입니다. 모든 통신은 이 Room 내에서 이루어집니다.
  • Participant (참가자): Room에 접속한 각 사용자(클라이언트)를 의미합니다. 자신은 로컬 참가자(LocalParticipant)이고, 다른 사용자는 원격 참가자(RemoteParticipant)로 구분됩니다.
  • Track (트랙): 미디어 스트림의 기본 단위입니다. 일반적으로 비디오 트랙(카메라)과 오디오 트랙(마이크)으로 구성됩니다.
  • Publication (게시): Participant가 자신의 TrackRoom에 공유하는 행위를 의미합니다. 다른 Participant는 게시된 Track을 구독하여 볼 수 있습니다.

필수 패키지

  • livekit-client: LiveKit 서버와의 연결을 관리하는 핵심 라이브러리입니다.
  • @livekit/react-components: LiveKit 기능을 React 컴포넌트와 훅(hook)으로 추상화하여 제공합니다. 이를 사용하면 복잡한 연결 및 상태 관리를 쉽게 처리할 수 있습니다.

React 컴포넌트 구성

LiveKit React 컴포넌트 라이브러리를 사용하면 복잡한 WebRTC 로직 없이 다음과 같은 순서로 화상 통화 앱을 구성할 수 있습니다.

LiveKitRoom 컴포넌트 사용하기:@livekit/react-componentsLiveKitRoom이라는 상위 컴포넌트를 제공합니다. 이 컴포넌트는 연결 상태, 참가자 목록 등 Room의 모든 상태를 관리하며, 내부 컴포넌트에 상태를 전달합니다.

import { LiveKitRoom, VideoConference } from '@livekit/react-components';
import { useToken } from './hooks'; // 토큰을 가져오는 커스텀 훅

const MyVideoRoom = () => {
  // 1. LiveKit 서버에 접속하기 위한 토큰을 가져옵니다.
  const token = useToken(); // 이 토큰은 LiveKit 서버에서 발급받아야 합니다.

  // 토큰이 없으면 연결할 수 없습니다.
  if (!token) return <div>토큰을 불러오는 중...</div>;

  return (
    // 2. LiveKitRoom 컴포넌트로 전체 방을 감쌉니다.
    <LiveKitRoom
      token={token}
      serverUrl="wss://<your-livekit-server-url>" // LiveKit 서버 URL
      connect={true}
      // 연결 성공 및 실패 시 동작을 정의할 수 있습니다.
      onConnected={() => console.log('연결 성공!')}
      onError={(error) => console.error('연결 실패:', error)}
    >
      {/* 3. 내부에 비디오 컴포넌트들을 추가합니다.
           VideoConference는 참가자의 비디오를 보여주는 사전 제작된 컴포넌트입니다. */}
      <VideoConference />
    </LiveKitRoom>
  );
};

주요 기능 구현

(1) 참가자 비디오/오디오 표시하기

@livekit/react-components의 훅을 사용하면 개별 컴포넌트에서 참가자의 상태를 쉽게 가져올 수 있습니다.

  • useParticipants(): 현재 Room에 있는 모든 참가자 목록을 가져옵니다.
  • useTracks(): 특정 참가자의 트랙 목록을 가져옵니다.

예시: 로컬 참가자의 비디오를 렌더링하는 컴포넌트

import { useLocalParticipant, useTracks } from '@livekit/react-components';
import { Track } from 'livekit-client';

const MyLocalVideo = () => {
  // 로컬 참가자 객체를 가져옵니다.
  const { localParticipant } = useLocalParticipant();

  // 로컬 참가자의 비디오 트랙을 가져옵니다.
  const videoTracks = useTracks([Track.Source.Camera]);

  if (videoTracks.length === 0) {
    return <div>카메라를 불러오는 중...</div>;
  }

  // 첫 번째 비디오 트랙을 사용하여 비디오 요소를 렌더링합니다.
  const videoTrack = videoTracks[0];

  return (
    <div>
      <h3> ({localParticipant.identity})</h3>
      <video ref={(el) => videoTrack?.attach(el)} />
    </div>
  );
};

LiveKit 클라이언트를 React와 TypeScript로 구현할 때의 핵심은 다음과 같습니다.

  • livekit-client와 *@livekit/react-components를 함께 사용합니다.
  • LiveKitRoom 컴포넌트로 전체 애플리케이션의 상태를 관리하고, 그 내부에 UI 컴포넌트들을 배치합니다.
  • useLocalParticipant(), useParticipants(), useTracks() 등 라이브러리에서 제공하는 훅(hook)을 활용하여 비디오, 오디오 및 참가자 상태를 쉽게 제어합니다.

전체 동작 흐름

  1. 세션 진입 및 준비
    • location.state 등 세션/유저정보 확인 → 사용자 토큰 저장
    • 먼저 유저 인터랙션(버튼) 유도 → 누르면 connectToRoom으로 비디오 세션 참가 시도
    • 배경 이미지 등 초기 리소스 비동기 로드
  2. 룸 연결 및 트랙 설정
    • useRoom.connectToRoom에서 LiveKit Room 개설 및 연결
    • 배경 제거 트랙을 생성해 publish, 로컬/원격 트랙 관리
    • 데이터채널(Data Packet) 수신 핸들러 세팅, 트랙 이벤트 처리
  3. 캔버스 렌더링
    • useEffect로 mainCanvas에 배경, 원격 트랙, 로컬 비디오(배경 제거) 동적 렌더링
    • 임시 캔버스를 통해 투명화/밝기/위치 등 세밀하게 처리 및 그리기
    • remoteTracks와 localTrack을 합성하여 협업 환경 구현
  4. 이벤트 핸들링과 채팅/동기화
    • 사용자의 드래그·사이즈·밝기 등 상태변화를 sendData로 데이터채널 broadcast
    • 채팅/선택/배경변경/공유URL 등 모두 브로드캐스트로 상태/메시지 동기화
    • 서버(중앙처리) 없이 직접적인 Peer간 동기화 구조
  5. 촬영/녹화/업로드
    • 캔버스 전체를 이미지(PNG) 또는 비디오(MP4)로 캡처
    • S3API로 S3 업로드 후, 결과 URL을 참가자 전체에 broadcast
    • 녹화는 MediaRecorder+captureStream 활용, 제한 시간 자동 stop 지원
  6. 카운트다운·상태 관리
    • 캡처/녹화 전, 카운트다운 startSharedCountdown로 모든 참가자 UI 동기화
    • processing status(처리중 플래그), 녹화 타이머 등은 전파 및 UI 반영
  7. 세션 종료 및 이동
    • 나가기버튼/코드 잘못 진입시 leaveRoom 실행 후, /film 등 다른 URL로 리디렉션
    • 편집 화면 이동 시 “navigateToEdit” 이벤트로 전체 참가자 상태 전파
profile
(아마도) 풀스택 개발자

0개의 댓글