FreeTalker
미국 테마의 2D 메타버스 안에서 AI NPC와 음성으로 영어 회화를 연습하고, 다른 사용자와 화상·음성으로 대화할 수 있는 교육 서비스입니다. 메타버스 플랫폼과 음성 인식, 화상 채팅을 맡았습니다.
- 소속
- SW사관학교 정글 6기
- 팀 구성
- 팀 리더 1명 · 프론트엔드 2명 · 백엔드 2명
- 저장소
- github.com/five-guys-jungle/Free-talker
- 현재 상태
- 서비스 종료
- 스택
- TypeScriptReactPhaserReduxWebSocketWebRTC
어떤 서비스인가
미국 테마의 2D 메타버스를 돌아다니며 역할이 다른 AI NPC에게 영어로 말을 걸고, 나눈 대화는 교정과 분석으로 돌려받습니다. 같은 공간의 다른 사용자와 화상·음성으로 대화할 수도 있습니다.
5주 안에 개발과 배포까지 마치는 것이 조건이었습니다.
주요 기능
- 미국 테마의 2D 메타버스 플랫폼
- 프롬프트 엔지니어링으로 서로 다른 역할을 부여한 AI NPC
- NPC와 실제 음성으로 주고받는 영어 회화
- 저장된 대화 내용의 교정 및 분석
- 사용자 간 화상·음성 실시간 회화
맡은 일
- 메타버스 맵과 캐릭터의 컨셉을 정하고 제작
- NPC 대화창, 사용자 간 음성·영상 채팅에 필요한 컴포넌트 제작
- Whisper API로 STT를 구현하고, 변환된 텍스트를 ChatGPT API에 넘겨 답변을 받아오는 흐름 연결
- 화상 채팅 구현
문제 — 서버를 거치느라 느려진 화상 채팅
화상 채팅을 WebSocket으로 구현했더니 모든 스트림이 서버를 거쳐 지연과 서버 부하가 함께 커졌습니다. WebRTC의 simple-peer로 바꿔 최초 연결 이후에는 서버 없이 사용자끼리 직접 스트림을 주고받도록 했습니다.
문제 — 클래스로 관리되는 Scene에서 상태를 받지 못하다
함수형 컴포넌트를 전제로 한 Recoil로는 클래스로 관리되는 Phaser Scene의 상태 변화를 받아올 수 없었습니다. React와 독립적으로 동작하는 Redux로 갈아타, 게임 프레임워크와 React가 만나는 지점의 전제를 맞췄습니다.
문제 — Scene이 바뀔 때마다 처음부터 렌더링되다
게임 인스턴스를 React 컴포넌트 안에서 만들다 보니 컴포넌트 생명주기와 인스턴스 수명이 어긋나, Scene이 바뀔 때마다 서비스 전체가 처음부터 다시 그려졌습니다. 인스턴스를 컴포넌트 바깥에 두고 상태를 외부에서 관리하도록 바꿔 두 수명을 분리했습니다.
문제 — 5주, 이끌 사람이 없는 팀
경험이 적은 인원으로 팀이 짜여 5주 데드라인 안에서 진행이 계속 처졌습니다. 속도를 내는 대신 팀원 각자가 MVP를 만들어보게 해 통신 구조를 전원이 이해한 뒤 업무를 나눴고, 그때부터 협업과 진행 속도가 함께 붙었습니다.
기술 선택
- Phaser — 2D 게임 프레임워크로 메타버스 공간을 구현
- Redux — 클래스로 관리되는 Phaser Scene에서도 전역 상태를 다루기 위해 선택
- Socket.io — 사용자 이벤트와 상호작용을 실시간으로 감지해 모든 플레이어의 화면을 동기화
- WebRTC — 사용자 간 실시간 음성·화상 채팅을 P2P로 처리
- TypeScript — 프레임워크가 섞이는 구조에서 잘못된 타입으로 생기는 오류를 막기 위해 정적 타입을 적용
진행 방식
기획·디자인 확정 후 시나리오와 타임라인을 잡고, 기술 스택과 MVP 범위를 정해 인프라를 구축했습니다. 베타로 먼저 배포해 수용·부하 테스트를 거친 뒤 실제 배포로 넘어갔습니다.
