안녕하세요 개발자 doro입니다.
Duckie가 출시된지 5개월가량 흘렀습니다. 현재 Duckie는 2,000개 이상의 덕력고사 문제가 있고, 1,700명이 넘는 유저가 사용하고 있는 서비스가 되었네요. 총 유저가 응시한 덕력고사 기록은 10만건 이상으로 출시 5개월만에 꽤나 많은 데이터가 모였습니다.
PM이자 개발자로서 출시 후 가장 많이 고민했던 문제는 어떻게 컨텐츠의 종류와 수를 늘릴까였습니다.
컨텐츠를 통해 서비스의 몸집을 키울 때는, 단순한 반복 작업이 선행된다고 해서 유저들이 다양한 컨텐츠를 재밌게 즐길 수는 없습니다. 확장하려고 하는 도메인이 현재 제품에 잘 맞는지 실험과 검증을 해야합니다.
MVP에서의 탈출
가장 먼저 고민했던 부분은 덕력고사의 도메인 확장이었습니다. 기존의 인물 맞히기나 제목 맞히기 같은 덕력고사 외에도 유저들이 좋아할만한 컨텐츠로의 도메인 확장을 생각했습니다.
애매합니다.
위의 TextField
는 유저에게 어떠한 정보도 주고 있지 않기 때문에, 어떻게 정답을 적어야할지 감이 오지 않고, 경우에 따라서는 꽤나 멋진 오답으로 애매함 또는 억울함이 발생할 수 있을 것 같습니다.
위와 같은 도메인으로의 확장을 하기 위해서는 추가적인 기능 개발이 필요해보입니다. TextField
의 UI를 변경해야만 유저들이 어느정도 정답을 유추할 수 있음과 동시에 애매함도 없애줄 수 있겠군요.
띄어쓰기 구조를 보여주니 손웅정좌의 밈을 어느정도는 맞힐 수 있을 것 같습니다. 영화 명대사 덕퀴즈에서도 변경된 TextField
는 띄어쓰기 구조를 보여줌으로써 내가 왕이 될 상인가
라는 대사를 정확하게 유추할 수 있습니다.
기존의 TextField
처럼 글자 수만 가르쳐줬더라면 문제푸는 데 흥미가 많이 떨어졌을 것으로 생각이 됩니다. 가장 우측의 사진도 이전 TextField
였다면 지드래곤, 권지용, G-Dragon 등 다양한 답안으로 유저들이 불만을 표현할 수 있는 부분 또한 사라지게 됩니다.
단순히 여러 도메인의 컨텐츠를 가지고 있다고해서 MVP 제품으로는 업로드할 수가 없습니다. 컨텐츠가 MVP 수준을 벗어나려면 개발도 MVP를 넘어서야합니다. 개발과 컨텐츠는 마치 이인삼각 달리기를 하고 있는 셈이죠.
이런 개발과 컨텐츠의 생애주기를 결정할 때 유의해야할 것은 유저 관점에서 어떻게 컨텐츠가 소비되냐를 면밀히 관찰하고 끊임없는 UT를 진행해야 한다는 것입니다.
좋은 컨텐츠가 개발이 덜 된 제품을 만나 저평가 되지 않기 위해서는 앞으로 업로드될 컨텐츠에 맞는 기능이 개발되어야 하는것이죠.
원클릭 업로더
하지만 늘 개발과 컨텐츠가 서로 엮이며 서로가 서로의 발목을 잡게 내둘 수만은 없습니다. 추가적인 기능 개발 없이 컨텐츠 업로드만으로 서비스의 몸집을 키울 수는 없을까요? 그것도 가능 합니다. 효율적인 컨텐츠 업로드 파이프라인을 구축하는 것인데요.
이번에 배포한 듣기평가 컨텐츠들은 노래의 전주만 1초정도 짧게 들려주고 정답을 맞춰야 하는 기능입니다. 기존의 덕력고사에서 오디오 컨텐츠가 추가된 것이죠.
이런 듣기평가를 만들기 위해서 단순히 mp3나 aac 파일들을 모은다고 한다면 컨텐츠 하나 만드는데 꽤나 고생할 것 같습니다. 그래서 이미 존재하는 미디어 컨텐츠를 파싱할 수 있으면 제일 좋겠다고 생각이 들었습니다.
고민하다 찾은 방법은 Youtube를 이용하는 것이었습니다. Youtube는 컨텐츠에 DRM이 걸려있지 않기 때문에 메타데이터를 쉽게 구할 수 있는 서비스입니다. 실제로 ytdl이라는 라이브러리가 존재할만큼 많은 유저들이 사용하고 있기도 하더군요.
제가 구축한 듣기평가 업로드 파이프라인은 다음과 같습니다.
클라이언트로부터 Youtube Url을 넘겨 받으면 Youtube 서버에 데이터를 요청해 원하는 오디오 데이터를 받을 수 있습니다. 대부분 3–4분 정도 길이의 mp3파일입니다.
이 오디오 데이터 중 FFMPEG 명령어를 통해 원하는 구간의 오디오 파일만 mp3파일로 트랜스코딩할 수 있고, 이렇게 만들어진 1~2초 길이의 mp3파일은 AWS S3로 바로 업로드 합니다.
실제 구현한 메소드는 아래와 같습니다.
async invoke(req: ProblemCreateRequest, user: User) {
const id = this.YouTubeGetID(req.musicYoutubeUrl);
const stream = ytdl(id, {
quality: 'highestaudio',
});
const path = `${__dirname}/${id}.mp3`;
ffmpeg(stream)
.audioBitrate(128)
.seek(req.musicStartSecond)
.duration(req.musicEndSecond - req.musicStartSecond)
.save(path)
.on('progress', (p) => {
readline.cursorTo(process.stdout, 0);
process.stdout.write(`${p.targetSize}kb downloaded`);
})
.on('end', async () => {
const musicBuffer = await this.readFile(path);
req.question.audioUrl = await this.fileService.uploadBuffer(
FileType.PROBLEM_QUESTION_AUDIO,
musicBuffer,
);
await this.problemService.create({ id: req.examId }, user, req);
});
}
ffmpeg
으로 전처리가 완료된다면 업로드된 파일의 주소와 클라이언트로 받은 데이터를 종합해 problem
객체를 데이터베이스에insert
하는 것으로 듣기평가 문제 하나를 만들 수 있게 되는 것이죠.
끝으로 Next.js를 이용하여 간단한 웹 CMS를 구축해 편하게 서버와의 통신을 할 수 있는 클라이언트까지 만들었습니다. 이제 Youtube Url만 안다면 누구나 듣기평가의 컨텐츠를 빠른 시간내에 만들 수 있게 되는것이죠.
이렇게 구축한 업로드 파이프라인을 이용한다면 30문제 가량의 듣기평가 하나를 만드는데 10분정도가 소요됩니다. 덕력고사에 비해서 압도적으로 짧은 시간내에 많은 컨텐츠를 확보할 수 있던것이죠.
추가적인 개발없이 단순히 좋은 업로드 파이프라인 하나로 유저들은 다양한 종류의 컨텐츠를 즐길 수 있게 만들 수 있었습니다.
플랫폼의 집단지성
마지막으로 개발만으로 컨텐츠의 몸집을 키울 수 있는 방법은 없을까요? 당연히 있습니다. SNS 의 특성을 이용해 유저들이 컨텐츠를 만들 수 있는 플랫폼으로서의 기능을 제공하는 방법입니다.
유저 참여형 기능을 개발해서 서비스를 운영하다보면 몇 가지 느끼는게 있습니다. 유저가 원하는만큼 좋은 컨텐츠를 쉽게 주지 않는다는 점입니다.
좋은 컨텐츠는 많은 컨텐츠가 쌓이면서 생기게 되고, 많은 컨텐츠는 많은 유저로부터 나오고, 많은 유저는 좋은 컨텐츠로부터 생기기 때문에 결국 닭과 달걀의 문제를 맞닥드리게 됩니다. 어느 지점에선가는 해결을 해야합니다.
출제중 기능은 관리자가 덕력고사의 주제를 정해주면 그 안에 들어갈 세부 문제들은 유저들이 직접 출제를 하는 기능입니다.
MVP 기능에서는 유저들은 만들어진 덕력고사를 응시만 했고, 한 걸음 나아가 만들어진 시험에 문제를 출제하는 걸로 확장이 됐습니다. Retention을 보았을 때 그렇게 충성도가 높은 서비스는 아니라고 판단해 유저가 시험까지 직접 출제하는데는 아직 무리인 것 같더군요.
기능으로서 서비스의 확장은 당연하게도 현재 서비스의 지표에 따라 방향성이 많이 달라집니다. 데이터는 등대니깐요.
위와 같이 유저가 여러 종류의 문제를 업로드 할 수 있고, 만든 문제는 특정 갯수 이상이 되었을 때 서비스에서 이용할 수 있게 됩니다. 저희는 데이터를 기준으로 적절한 시험의 주제만 정해주면 됩니다.
후에는 시험까지 유저가 생성할 수 있으면 컨텐츠가 컨텐츠를 만드는 구조를 만들어 커뮤니티로서의 Duckie도 생각해볼 수 있을 것 같습니다.
결국은 크로스 도메인이다.
3가지 방법 모두 좋은 컨텐츠를 확보하기 위한 방법들이고 앞으로 꾸준히 개선해 나가야할 과제들입니다.
그 중에 TextField 개선과 도메인 확장은 유저들의 긍정적인 피드백과 퀄리티 좋은 컨텐츠를 바로 얻을 수 있었습니다. 결국 타팀과의 협업으로 인한 시너지가 좋은 서비스를 만들고 유저들도 더 재밌게 컨텐츠를 소비할 수 있었습니다.
기술의 문제가 아닌 영역을 기술로 해결할 수는 없습니다. 문제를 잘 정의하고 필요한 도구와 역량을 적재적소에 사용하는 것이 좋은 서비스와 조직을 만드는데 도움이 되는구나를 느끼며 개발을 하고 있습니다.
감사합니다.