나 자신을 인터뷰할 수 있다면 어떨까
개발 동기
지금까지는 블로그에 내가 기획해서 내가 개발했던 사이드 프로젝트를 주로 작성했었는데, 이번에는 외부에서 기획된 서비스를 맡아 개발하게 된 경험을 적어보고자 한다. 결국은 대가를 지불받으며 외주의 형태가 되긴 했지만 처음에는 나의 창업 동아리 팀이 기획했던 서비스를 접하고 개발을 해주겠다고 나섰던 것에서 시작되었다.
해당 팀이 기획한 서비스의 이름은 INNERVIEW 인데, 무인 사진 촬용 부스와 같은 구조에 질문을 화면에 띄우고, 이용자는 그 질문에 답하여 자기 자신을 알아가는, 자기 자신을 인터뷰한다는 의미의 서비스였다. 자신의 과거를 돌아보거나, 나의 지금까지의 연애 혹은 친구 관계에 대한 고찰 등 생각해볼 만한 주제들이 있어 개인적으로도 상당히 매력적인 서비스라 생각했다.
그 3인 팀에는 안타깝게도 개발자가 없었는데, 개발자가 항상 필요한 것은 아니지만 소프트웨어 서비스를 제작하기 위해서는 있으면 정말 편한 것이 사실이다. 사실 당장 3-4주 가량 남은 우리 학교 축제에서 서비스를 만들어 운영해보고 싶다는 뜻을 전해왔으며, 그러기 위해서는 PC에서 실행할 모종의 소프트웨어가 필요했고, 카메라, 마이크 연동과 실시간 영상 송출, 영상 처리(흑백 필터, 자막 생성), 그리고 QR코드로 영상 다운로드까지 이어지는 일련의 기능을 구현할 서비스가 필요했다.
관련하여 개발 환경 세팅도 도와주고, 사용할 만한 언어/프레임워크에 대한 추천까지 해주었지만 사실 개발을 한 번도 해보지 않은 사람이 위와 같은 기능을 가진 서비스를 최대 3주 안에 만든다는 것이 조금은 비상식적으로 느껴졌다. 물론 그 팀의 역량에 대한 의문은 아니었고, 충분히 가능할 것이라 생각했지만, 개발 외에도 정말 할 것이 많은 초기 창업이기에, 그리고 소프트웨어적으로 빨리 결과물이 나올 수록 할 것이 많아지기에 도와주고 싶은 마음이 생겼다. 사실 학교 축제에서 원활하게 부스 진행을 하려면 개발자가 필요했기 때문에 부스에서 인터뷰를 직접 해보고 싶은 마음이 컸던 것 같다.

개발 환경 선정
최근 AMS를 개발하며 웹 애플리케이션을 통한 파일 업로드, S3 스토리지로 관리, QR 생성 및 제공의 일련의 프로세스를 가진 서비스를 구축해보았기 때문에, 이 프로젝트에서 Baseline 코드를 일부 가져올 수 있었고, 초기 서비스 구축에 대한 부담 없이 2일 동안 1차 배포를 마칠 수 있었다. 유사하게 웹 애플리케이션 제작에 Next.js, 데이터베이스에 PostgreSQL을 이용하였고, Minio object store를 영상 저장 스토리지로 이용하였다. 항상 느끼지만 Minio는 S3 compatible하다는 점이 매력적인 것 같다. 단기간에 서비스의 확장이 필요하다면 큰 구조 변경 없이 Amazon S3 storage로 이전할 수 있기 때문이다. 그리고 한 서비스에 instance가 두 개 이상으로 많아지면 배포하기 번거롭다는 생각에 Docker compose 환경을 애용한다.
Overview






어드민 페이지
기존에는 팀에서 주제와 질문을 상의하여 엑셀 형태로 제공하면, 내가 js로 하드코딩하여 넣는 방식을 이용하였다. 사실 주제와 질문이 몇 개 되지 않을 것이라는 전제 하에 기술적인 빚으로 남겨둔 것이었는데, 점점 주제와 질문이 쌓이고, 질문이 한 글자라도 바뀌면 서비스를 재배포 해야하는 비효율적인 방식이라는 생각이 들어 DB로 주제, 질문 데이터를 옮긺과 동시에 어드민 페이지를 제작하였다.
주제, 질문에 대한 CRUD기능이 전부였기 때문에 Next.js에 tailwind를 이용하여 (생성형 AI는 tailwind를 상당히 잘 작성한다.) 매우 쉽게 제작할 수 있었다. 실질적으로 내가 한 것은 api url을 작성해준 것 밖에 없는 듯 하다.


미디어 업로드
이 서비스를 배포한 후 가장 고민이 되고, 문제가 있었던 부분은 바로 영상 업로드이다. 기본적으로 대용량 미디어를 업로드할 때에는 서버를 경유하지 않고 storage에 직접 업로드하는 방식을 선호한다. Presigned URL을 이용하면 보안 리스크를 적게 하면서도 서버에 부하를 적게 줄 수 있기 때문이다. 하지만 이번 프로젝트에서는 영상에 자막을 입히고, 흑백 모드일 경우 흑백 필터를 적용하는 등 영상 처리를 한 후 업로드를 해야했기 때문에 영상 자체가 필연적으로 서버를 거쳐야 했다. 엎친데 덮친격으로 테스트 환경에서는 노트북 웹캠으로 테스트하여 10-15분 녹화를 하여도 영상의 용량이 40MB 정도였는데, 실제 환경에서는 고성능의 디지털 카메라를 이용하며 10-15분 영상에 200-400MB까지 용량이 올라가는 사태가 발생하였다. 따라서 일단은 서버에 메모리와 CPU 리소스를 넉넉하게 할당하는 방식으로 해결하고자 하였다.
또 하나의 문제는 소프트웨어 자체의 문제라기 보다는 외부적인 문제였는데, 부스를 운영하는 곳의 네트워크 환경이 매우 좋지 않아 업로드에 시간이 30분에서 길게는 1시간 가량이 걸리고, 심지어는 네트워크가 도중에 끊기기까지 해서 업로드가 중단되기도 했다는 것이었다. 이 때문에 실 운영 1일차에 정말 많은 문제가 발생하였는데, 이를 해결하기 위해서 두 가지를 도입하였다.
-
인터뷰가 완료되면 영상을 서버에 전송하기 전 영상 및 자막 관련 Metadata를 로컬 머신에 저장하며, 서버에 인터뷰 완료 신호를 전송하여 DB에 row를 생성한다. 해당 row의 video_url은 NULL, video_status는 0(업로드 중)
-
백그라운드에서 영상 전송을 시작한다. 기존에는 영상 전송 -> 영상 처리 -> 영상 업로드 및 해당 링크로 QR 생성 -> 클라이언트에 제공이라는 절차였으나, 클라이언트에 QR을 제공하기까지에는 시간이 지연되면 안됐기 때문에, 로컬에 영상 저장 -> QR 생성 -> 영상 전송 -> 영상 처리 -> 영상 업로드 -> video_status = 1, url 업데이트 라는 절차로 변경하여 비동기적으로 처리할 수 있도록 하였다. 영상을 보여주는 화면은 실시간 DB 상태를 참조해야 했기 때문에, Webhook이나 Websocket을 이용할까도 생각해봤지만 영상을 한 번 다운로드 받으면 만료되는 화면이기 때문에 간편하게 주기적으로 Polling하는 것으로 처리하였다.
만약 네트워크 문제로 업로드가 정상적으로 완료되지 않을 시, 저장된 영상과 메타데이터를 서버로 재전송하여 완성된 영상을 저장하게 된다. 이로써 영상이 소실되는 리스크를 줄일 수 있게 되었다.
돌아보며
정말 예상치 못한 부분에서 문제가 터진다는 것을 몸소 느낄 수 있었고, 철저한 테스트와 개발/배포 환경의 분리의 필요성도 뼈저리게 느낄 수 있었던 프로젝트였다. 개발 측면에서 어려움이 많은 프로젝트는 아니었지만, 미디어를 처리하는 부분에서 미디어의 용량에 따른 문제를 예상하지 못한 나의 미숙함을 느낄 수 있었고, 개발자는 항상 극단적인 상황을 가정하고 코드를 작성해야한다는 사실을 다시금 상기하게 되었다.
그리고 최근에는 C++로 웹 서버를 개발하고 있는데 C++을 사용하다 JS로 작업을 하니 오히려 힐링이 되는 기분도 들었다. Python, JS 등 언어가 질린다면 C, C++로 개발을 하다가 오는 것도 가끔 써먹어볼만 한 방법인 것 같다. C++ 프로젝트의 경우에 대학 과제로 수행 중인 이유로 API Documentation과 보고서까지 의무적으로 작성해야 하기에 작성하는 김에 블로그 글까지 정리할 것 같다. 지금 Github의 Most used Languages 랭킹에서 절반 이상이 Typescript인게 마음에 걸렸는데, 이번에 C++ 코드를 좀 많이 작성해봐야겠다.
Enjoy Reading This Article?
Here are some more articles you might like to read next: