이 포스팅은 2021년 7월 중순부터 11월 중순까지 Under5 팀이 약 4개월간 개발하여 2021 공개SW개발자대회 일반부 대상을 수상한, ‘GiggleForest 프로젝트’의 경험에 대한 공유와 회고를 위해 작성되었습니다.

시연 영상

기글 포레스트 시연 영상

팀 구성

IntraTech Stack(before)Tech Stack(after)
kilee(팀장)BreathingAWS, Github Action, CI/CD, React, TypeScript
honleePOE, LOLAWS, React, NestJS, Typescript
hyeonkim<undefined | null>React, NestJS, Typescript
mijeongEat and PlayReact, NestJS, Typescript
* 위 Tech Stack 은 프로젝트를 진행하며 습득하였습니다.

배경

저희는 42서울의 마지막 과제인 ft_transcendence 를 위해 모였습니다. 가장 많은 인원이 모여서 진행하는 마지막 과제를 남겨두고, 팀원 모두 두 가지 아쉬움이 남았습니다. 하나는 체계적인 협업 과정을 겪어보지 못했다는 것이었고, 다른 하나는 명세서가 나와있는 과제를 단순히 구현만 해왔다라는 것이었습니다. 

그래서 ft_transcendence  과제에 착수하기 전, 체계적인 협업 과정을 통해 하나의 서비스를 기획부터 배포까지 해보자’라는 생각으로 프로젝트를 시작하게 되었습니다.

어떻게 하면 체계적으로 협업을 할 수 있을지 도움을 구하고자, 42서울의 비상근 멘토이신 이광헌 멘토님(그저 빛)께 멘토링을 신청하였습니다. 이광헌 멘토님께서 애자일 방법론으로 프로젝트를 진행하는 것을 추천해 주셨고, 또한 이 프로젝트가 끝날 때까지 매 스프린트 회의때 멘토링을 해주시기로 하셨습니다. 또한 멘토님께서는 과학기술정보통신부가 주최하는 ‘공개소프트웨어 개발자대회’에 참가하는 것을 권하셨습니다. 저희가 생각한 프로젝트 기간과 비슷한 시기에 대회가 진행됐고, 정해진 시간 안에 프로젝트를 진행한 뒤 프로젝트를 평가받을 수 있는 좋은 기회라고 생각해서 대회에도 참가하게 되었습니다.

협업 과정

기획

어떤 서비스를 만들지는 팀이 결성된 이후에 논의되었습니다. 약 2주간 각자 프로젝트 아이템을 구상해온 뒤 투표를 통해 최종 아이템을 선정하기로 했습니다. 팀원 모두 어떤 프로젝트를 하고 싶은지 자유롭게 얘기했고, 모두가 만족하는 아이템 선정과 프로젝트 목표에 대한 합의를 위해 ‘프로젝트 기획안 평가표’를 작성했습니다.

프로젝트 기획안 평가표

현실성
– 아이디어 배경 → 타당한지?
– 현실적으로 구현 가능한가? (3달간의 프로젝트 진행 기간동안 현실적으로 불가능 한지)
– 해당 아이템의 한계가 무엇인가?

커리어
– 이 프로젝트를 진행해서 우리에게 남게 되는 것이 많은가?
– 완성이 되었을 때 다른사람들에게 자신감있게 보여줄만한가?
– 기술적 도전이 있는가? (기술의 숙련 말고)
– 프로그래밍적 배경지식 보단 측정 사업분야에 대한 배경지식을 더 요구하진 않는가?
– 경쟁, 대체제와 기술적 차별성이 존재하는가

팀원들이 하고싶은가
– 팀원들의 흥미도
– Honlee 가 하고싶은가 (제일중요)
– 이 프로젝트에 몇명의 팀원이 관심있는가?

효과성
– 사용자가 적더라도 누군가는 꼭 필요한 서비스(기술) 인가?
– 목표 시장의 타당성(꼭 경재적인 타당성을 요구하지는 말자, 추정치라면 근거 타당성 입증 필요)
– 비교할만한 서비스가 있는가?

시장성
– 경제적 지표를 보여줄 수 있는 시장이 존재하는가.
– 핵심 고객층은 누구인가
– 동일한 아이템이 있다면 차별점이 있는가?
– 프로젝트의 미래 발전성이 높은가?
– 국내 경쟁 서비스 조사 / 시장 환경
– 해외 경쟁 서비스 조사 / 시장 환경

기타
– 위 사항만 가지고 평가하라는 것은 결코 아님. 팀원들의 막고라의 대비용임 (최소 이 정도의 공격은 준비해라 라는 뜻)

아래 아이디어들 중 위 평가표를 기준으로 가장 높은 점수를 얻은 ‘웹 기반 음성 채팅 메타버스'(가제 ‘Voice Space’)를 선정하게 되었습니다.

◦ 언제 어디서나, 어떤 기기로든 접근할 수 있는 원터치 개인 클라우드

◦ 자신이 있는 위치를 기반으로 펫 시터를 쉽게 구할 수 있는 어플리케이션

◦ 비대면학습을 위한 실시간 학습 노트 서비스

✓ 웹 기반의 음성 채팅 메타버스

나름의 이유를 가지고 아이템을 선정했지만, 그 아이템이 실제로 어떤 문제를 해결할지는 확실치 않았습니다. 따라서 기획을 발전시키기 위해 42서울 카뎃을 대상으로 인터뷰를 진행했습니다. 

사업을 위한 프로젝트였다면 시장 조사에 더 많은 시간을 들여 실제 문제를 발견하고, 문제를 해결할 수 있는 아이템을 선정했어야 했을 것입니다. 그러나 이번 프로젝트의 목적 중 ‘팀원들의 흥미’가 최우선이었기 때문에 이와 같은 순서로 진행했습니다.

인터뷰 계획

알고자 하는 내용

관심사/취미에 대해 어떤 활동을 하는지.

– 관심사/취미에 관한 커뮤니티 경험에 대해(경험의 깊이 등을 확인)

– 같은 관심사를 가진 사람과 어떤 방식으로 관계를 형성해왔나요?

– 같은 관심사를 가진 새로운 상대와 거부감 없이 대화할 수 있는가?

Q 요즘 여러분의 주요 관심사나 취미에 대해서 자유롭게 얘기 나눠주세요!

-> 취미는 어떻게 즐기시는지?

-> 취미를 혼자즐기시나요? 아니면 다른사람들과 같이 즐기시나요? (웜업)

Q 본인의 관심사나 취미를 공유해본 경험에 대해서 얘기해주세요

-> 누구와 어떤 방식으로 공유하셨나요?

-> 취미 공유하는 것에 있어서 좋았더 점 아쉬웠던 점이 있다면 이야기 해주세요

원격 커뮤니케이션에 대한 사람들이 가지고 있는 생각(인지한 문제점, 불편함 등)

– 화상채팅에서 얼굴이 노출되는 것에 대해 부담이 존재하는가?

– 원격 커뮤니케이션 툴을 이용하는 목적은 무엇인가?

– 코로나 시국 전에도 원격 커뮤니케이션을 이용했는가?

– 원격 커뮤니케이션 채널을 통해서 새로운 사람과 대화를 나눠본 경험이 있는가? 그 경험은 어땠는가?

Q1 줌이나 디스코드나 토크온 구글밋 같은 원격 커뮤니케이션을 이용해본 경험에 대해 자유롭게 얘기나누세요.

→ 혹시 원격커뮤니케이션을 진행하면서 오프라인에 비해서 아쉬웠던점?

→ 어떠한 목적으로 이용해보셨는지 얘기해주세요.

Q2 (원격 커뮤니케이션이 필요할 때 )주로 사용하는 서비스는 무엇인가요?

→ 만약 인터뷰이 들이 서로 다른 서비스를 사용한다면

→ 자신이 주로 사용하는 서비스를 다른 분들도 사용하게끔 설득해주세요!

→ 만약 모두가 같은 것을 사용하거나 비율이 너무 맞지 않는다면 → 한쪽으로 쏠렸다는 것이니까 아쉬운점!

인터뷰 결과 및 분석

인터뷰를 통해 원격 커뮤니케이션에 대한 사람들의 경험을 들을 수 있었다.

– 주로 디스코드, 슬랙(42동료평가를 위해), 줌, 구글 밋을 이용한다.

– 줌은 주로 발표 강의 등 일대 다의 경우에 많이 이용한다고 함.

– 디스코드는 게임 / 모임 – sns 성향

– 원격 커뮤니케이션 서비스를 이용하는 이유는 [ 어쩔 수 없어서(코로나) / 원래 사용(주로 게임) ]

– 사용 목적은 [ 게임 중 음성채팅 / 직장,학업 등 소통 도구(반강제) / 원거리 통화 / 모임 ]

– 사람들이 느끼는 불편은 [ 오프라인 소통 보다 아쉬운 소통 경험 / 통화 품질 불안정 / 얼굴을 공개하면서 통화하는 점 ] 등이 있었다.

또한 인터뷰 후 시장 조사 계획에서 세운 가설에 대해 조금더 방향성을 잡을 수 있었다.

가설 1 : 원격 커뮤니케이션 서비스 이용 시 오프라인 커뮤니케이션과의 괴리에서 오는 PAIN POINT가 존재한다.

가설 1에 대한 검증 : 존재한다. → 하지만, 오프라인 커뮤니케이션 경험을 온라인에 완벽하게 이식하는 것이 이들이 원하는 것은 아니다. ex) 얼굴 맞대고 대화

가설 2 : 사람들은 공감대를 형성할 수 있는 사람들과의 소통 채널을 필요로 할 것이다.

가설 2에 대한 검증 :

→ 최초 목표 고객군을 가정할 때, 여가시간을 혼자 보내는 것보다 타인과 함께 보내는 것을 좋아하는 사람들이 타인과의 소통 채널을 필요로 할 것이라 생각했으나, 이는 모든 사람이 원하는 것이었다. 오히려 여가시간을 혼자 보내는 것을 선호하는 사람들이 느슨한 커뮤니케이션 채널(원격 커뮤니티를 이미 많이 이용하던 like discord)을 훨씬 더 애용한다.

→ 관심사/취미에 대한 좀 더 세분화된 그룹핑을 제공하는 것에 대한 지불의사가 존재한다.

+A 초반에는 특정 주제 관심 집단만을 위한 서비스로 출발하는 것도 좋을듯하다.

인터뷰 결과 분석 → 골든서클

WHY :

문제 정의 : 디스코드로 대표되는 보이스챗 유저들에게 오프라인 커뮤니케이션과의 괴리에서 오는 불편이 존재한다.

불편 요소는

– 오디오 겹쳐서 눈치게임 하는 부분 → 나를 기준으로 다른 유저들의 공간적 위치가 정의되지 않아 방향성이 없다. ex)현실에서 사람들은 소리의 방향성을 느낀다

– 여러명이서 얘기할 때 옆사람에게 귓속말 못하는거 ex) 현실에서 사람들은 여러명이 대화 중에도 옆사람한테만 말하고 싶은 경우에 귓속말 한다.

– 소통 공간에 대한 유저의 상태가 0 또는 1이다 (IN or OUT) → ex) 멀찍이서 저사람들 뭔얘기하지 간보고싶다.

HOW :

이러한 문제를 기존 보이스챗에 오프라인 커뮤니케이션의 장점을 더하여 해결한다.

WHAT :

디코 + 아바타 + 아바타가 움직일 수 있는 공간

개발

1. 오디오에 반응하는 아바타 구현

인터뷰 결과 및 분석을 통해서 최종적으로, 디스코드 + 아바타 + 공간 이라는 개발 목표를 설정했습니다.

우선, 음성채팅에 몰입감을 줄 수 있는 기능을 고민했습니다.

– 아바타간의 거리에 따라서 볼륨이 조정되면 어떨까? (소리의 공간감을 느낄 수 있지 않을까?)

– 유저의 볼륨에 따라서 아바타의 크기가 변하면 어떨까? (화자를 식별하고, 활동감을 느낄 수 있지 않을까?)

위 두 가지 아이디어가 나왔고, 빠르게 WebRTC와 WebAudio를 사용해서 프로토타입을 구현했습니다.

초기 프로토 타입

빠르게 제작한 프로토 타입으로 팀원들과 테스트 했고, 결과는

재밌다 ㅋㅋㅋㅋㅋㅋ

였고, 이 두가지 기능을 핵심기능으로 개발을 진행하기로 결정했습니다.

2. 디자인 및 그래픽 엔진 개발

다음으로는 위 두가지 기능을 표현하기에 적합한 디자인을 고민했고, 2D top view 형식의 귀여운 동물들이 숲속에서 대화를 나누는 컨셉을 정했습니다(귀여우면 중간은 가니까요).

디자인을 적용하는 데에는 WebGL을 사용하여 구현한 자체적인 그래픽 엔진을 사용했습니다.

초기 버전 영상

3. 음성 채팅 구현

유저간 음성채팅을 구현하려면, 유저간에 실시간으로 오디오 데이터를 주고받을 수 있는 채널이 필요했습니다. 이는 화상회의 프로그램에서 많이 사용되는 WebRTC를 사용하여 P2P 형식으로 구현했습니다.

3. CI / CD 파이프라인 구축

동작하는 수준의 코드가 만들어지고 나서는 ‘개발 → 테스트 → 배포’에 드는 노력과 시간을 줄이기 위해 AWS Code Deploy 와 Github Actions을 사용해서 CI / CD 파이프라인을 구축했습니다. 이 덕분에 테스트를 통과하지 못하거나, 빌드되지 않는 branch의 pull request 자체가 이루어지지 않았습니다. 따라서 master를 항상 build가 가능하고 테스트가 전부 통과하는 상태로 유지 할 수 있었습니다. 이를 통해,정상적으로 업데이트 된 master를 배포하는 데에 드는 시간을 획기적으로 절약할 수 있었습니다.

4. 고도화

이후 더욱 몰입감 있는 소통 경험을 위한 고민을 하던 중 아바타가 유저의 목소리에 반응하여 립싱크를 할 수 있으면 좋겠다는 아이디어가 나왔고, 팀원들 모두 시도해보고 싶어했습니다. 하지만 이 때가 대회 최종 제출 한달 전 상황이었습니다. 저희는 발표를 준비하며 문서, 발표 자료 등의 완성도를 높이는 것이 좋을지, 리스크가 있지만 원하는 기능을 추가할지에 대해서 회의를 진행했습니다. 회의 결론은

해보고 싶으니까 눈으로 보고 결정하자!

였고, 빠르게 프로토타입을 만들어서 테스트를 진행했습니다. 

립싱크 프로토타입

팀원들 눈에는 너무 재미있어 보였고, 스프린트를 조금 더 타이트하게 진행하며 립싱크 기능을 추가해보기로 했습니다. (프로젝트 시작 시에합의했던 목표인 ‘팀원들의 흥미’를 기준으로 선택했습니다.)

기능 추가에 따른 Side Effect

– 립싱크 기능 추가에 따라, 이 기능을 돋보이게 하기 위해서는 디자인의 전면적인 수정이 필요하다 판단했고, 디자인 개편을 진행했습니다.

– 디자인 변경에 따라 큰 Side Effect가 발생했습니다. WebGL로 직접 만든 그래픽 엔진이 변경된 디자인과 물리를 반영하지 못하는 문제였고, 이를 해결하기 위해 그래픽 엔진의 수정이 필요했습니다. 

립싱크 기능 적용 결정 후 디자인 변경

5. 문제 및 해결

  1. 처음에는 3rd party library 를 사용하지 않고, WebGL만을 사용하여 직접 렌더링 엔진을 구현했습니다. 성숙도 낮은 엔진이, 큰 변경이 있는 의사 결정에 빠르게 대응하지 못한다는 치명적인 단점을 깨닫게 되었고, 장기적으로 생각한다면, 성숙도 높은 그래픽 라이브러리로 엔진을 교체하는 것이 좋겠다고 판단했습니다. 이후 별도로 PixiJS 라이브러리를 사용하여 렌더링 엔진 개발하였고 안정화를 진행하며 교체하였습니다. 이때 팀원 모두 ‘왜 개발자 커뮤니티가 중요하고, 이미 만들어진 것을 가져다 사용하는 것이 얼마나 가치 있는 일인지’ 깨달았습니다.
  2. 유저간 음성채팅 기능 구현에 있어서는 WebRTC를 사용했습니다. 그러나 특정 네트워크 상태에 있는 두 유저가 서로 연결되지 못하는 현상이 발생했고, 네트워크 트레블링에 대해 공부하면서 이러한 케이스에서는 TURN이라는 릴레이 서버가 필요하다는 것을 알았습니다. TURN 서버로는 coTurn 이라는 오픈소스 TURN 서버를 설치함으로써 해결했습니다. 이 문제를 해결 하면서 어떤 기술이든 접근하기는 쉬워도, 이것을 가지고 개발을 하려면 이 기술에 깔린 여러 개념들을 착실히 공부해야 된다는 것을 깨달았습니다.
  3. 마지막 주요 기능인 립싱크 기능을 구현할 때에는, 사용자의 ‘아애이오우’에 대한 모음 주파수 데이터를 미리 받아서 저장하고, 이 데이터를 서비스 사용 시 사용자가 입력하는 음성 신호의 스냅샷과 비교하여 유사도만 판별하면 된다고 생각했습니다. 그러나 실시간으로 입력되는 신호의 표준편차가 너무 크다는 문제가 있었습니다.

이러한 문제는 데이터 분석 전 전처리 과정 중 하나인 이동평균법을 적용하여 smoothing하는 것으로 해결했고, 미약하게나마 데이터분석에 있어서 전처리, 트렌스폼이 얼마나 중요한지 알 수 있었습니다.

결과물 & 결과

repo : https://github.com/VoiceSpaceUnder5/VoiceSpace

demo : https://giggleforest.com/

멘토님의 도움으로 나름 체계적으로 프로젝트를 진행한 덕에, 참가한 공개SW개발자대회에서 과학기술정보통신부 장관상(일반부 대상)을 수상할 수 있었습니다.

또한 이 프로젝트로 참가한 두번째 대회인 42서울 오픈프로젝트에서도 최고작으로 뽑혀 정보통신기획평가원장상을 수상했습니다.

느낀점

honlee : 개발자는 코드를 치는 것만이 전부가 아니라는 것을 깨달았습니다. 프로젝트가 성공하기 위해서는 코드 외적으로도 케어해야될 너무나 많은 부분들이 필요있고, 이 부분들을 혼자 모두 케어하지 못하더라도 어느정도는 알고 있어야 한다는 생각이 들었습니다. 또한 어느 기술을 배우거나 선택 할 때, 이 기술이 어떤 문제를 해결하기 위해 탄생했는지를 이해하지 못하고 그저 가져다 사용하는 것은 추후 엄청난 기술부채를 만들어 낸다는 것을 알았습니다. 지식 습득에 투자하는 시간이 길수록 이후 기술부채가 적어진다는 것을 여실히 느낄 수 있었습니다. 그 외에도 테스트, 모듈화 등 단순 기능구현을 벗어난 스킬들에 대한 중요성을 깨달을 수 있었습니다.

mijeong: 협업이라는 것이 얼마나 중요한 것인지 알게 되었습니다. 물론 개발 중 많은 부분은 honlee님이 담당하셨지만 각자의 역할을 정하고 그 역할을 수행하는 것에 있어서 개발 외적으 많은 난관이 있고 그 난관을 헤쳐나가는 것이 코드를 치는 것보다 많은 에너지가 들어갈 수 있다는 것을 알았습니다. 그래서 팀프로젝트를 진행하는 데에 있어 그런 부분에 대해 항상 생각을 해야한다는 것을 알았습니다. 그리고 팀원들이 열심히 하는 모습을 바로 옆에서 지켜보면서 아직 저는 노력이 부족하고 더 열심히 해야겠다는 생각을 했습니다.

kilee: 협업에서 기본은 합의된 목표와, 지켜야할 규칙이라고 생각합니다. 각 개인이 이 것을 잊지 않고 지키고자 노력한다면, 모두가 하나의 점을 향해 가고 있다는 신뢰가 형성됩니다. 신뢰가 형성된 팀은 선순환 고리를 연결해 나아가는 힘이 생깁니다. 팀 프로젝트를 할 때에, 무엇을 하고 있는지 보다는, 왜 하고 있는지를 잊지 않는게 더 중요하다는 생각이 듭니다. UNDER5 팀은 시작 단계에서, 이 프로젝트를 왜 진행 하는지에 대해서 충분히 서로의 생각을 듣고, 합의된 목표를 잘 정했기 때문에, 모두가 성장할 수 있는 좋은 프로젝트가 되었다고 생각합니다. 이번 프로젝트 경험을 통해, 의지와 시간, 믿고 함께할 수 있는 동료만 있다면 무엇이든지 만들 수 있다는 자신감을 얻을 수 있었습니다. 

hyeonkim: 42서울에 들어와서 (거의) 처음으로 코딩을 접하고 새로운 과제를 만날 때마다 들었던 생각은, ‘내가 이걸 할 수 있을까’였습니다. 프로젝트 아이템을 정할 때에도, 아이템이 정해진 다음 구현을 하는 와중에도 계속 비슷한 생각을 했습니다. 혼자라면 아마 기획 단계에서 지레 겁을 먹고 포기했을 것입니다. 하지만 옆에서 가능하다고 얘기하고, 실제로 처음 접하는 기술을 두려워하지 않고 사용하는 동료들이 있어서 저도 겁먹지 않을 수 있었습니다. 또한 지금까지는 경험해보지 못했던 큰 프로젝트를 하면서, 단순히 기능을 구현하는 것 외에 (글로만 접했던) 코드 구조나 자동화, 문서 정리 등의 중요성을 체감할 수 있습니다. 앞으로는 ‘내가 할 수 있을까’가 아니라 ‘어떻게 하면 잘 할 수 있을까’를 고민하고 그렇게 행동해야겠습니다.

보너스) 활용 도구 & 기술

멘토님께서는 협업과 관련된 여러 방법론, 현재 현업에서 사용하는 기술과 도구들에 대해 소개해주셨습니다.

  • 프로젝트 관리에는 Jira, 문서 관리에는 Jira와의 연동이 용이한 Confluence를 사용했습니다.
  • 디자인 및 기획, 화면설계서, 기능명세서 작성에는 Figma를 사용했습니다.
  • 코드 버전관리에는 Git과 Github, GUI를 통해 git을 다룰 수 있는 SourceTree를 사용했습니다.
  • CI / CD 파이프 라인 구축을 위해서는 Code Deploy와 Github Actions을 사용했습니다.
  • FrontEnd의 UI 작성에는 React, 테스트를 위해  jest를 기반으로 한 react-testing-library를 사용했습니다.
  • 브라우저 뷰표트의 대부분을 차지하는 그래픽은 PixiJS를 사용했습니다.
  • 립싱크 기능 구현에는 WebAudio 를 사용했습니다.
  • P2P 연결을 위해 WebRTC를 사용했습니다.
  • 연결 중개 서버 역할을 하는 BackEnd에는 NestJS를 사용했습니다.