영화 랭킹 시각화 서비스 Movisualization(+ 엄복동 차트) 제작기

2020. 6. 29. 01:37IT/Retrospective

들어가며

이 글은 2019년 네이버 캠퍼스 핵데이 서머의 참가 후기 글입니다. 기존에 이 글이 이미 있었으나, 프로젝트에 대해 설명하는 글은 없었으므로 따로 작성했습니다.

핵데이 후기 잘 읽었습니다. 근데 뭘 만드신...?

한달에 한번 글이 올라올까 말까한 (주인이) 게으른 블로그지만, 어그로를 끌어주는(?) 글들이 좀 되는 덕에 한달 페이지뷰는 1만 좀 안되게 나오고 있다. 그 어그로를 끌어주는 글들 중 라인 인턴십 후기 1, 2네이버 캠퍼스 핵데이 후기, 그리고 우아한 테크코스 후기가 스테디셀러였는데, 이 후기들 모두가 정작 제일 사람들이 궁금해 할 "그래서 니가 한건 뭐냐고"에 대한 답은 없었기에 읽는 사람이 답답했을 것 같다.

내 기억으로 저 '진짜 자기 생각을 나누고 싶고... 없는 것 같다' 는 원래 '인터넷에 병X같은 글 더 늘리고 싶지 않았다'였던 것 같은데 검열당한 듯하다(...)

최근에 읽었던 글 중에 제일 뜨끔했던 글은 다름아닌 와디즈 개발 인턴 후기였다. 내 정신세계 내용물도 이와 유사했으나 의견을 공개적인 곳에 밝히는 것을 별로 좋아하지 않았던 터라 최대한 정상인인 척(?) 숨기고 있었다. 후기를 자세히 공개하지 않았던 것은 귀찮았던 것도 있지만, '이렇게 공개했을 때 문제 생기진 않나?' 싶은 우려가 제일 컸다. 그러나 내가 했던 것들을 기록으로 남기고자 싶은 욕망은 늘 있었다.

이 짤은 원래 '모방 범죄가 일어날까봐' 설명을 생략했다고 알려졌었는데 최근에 작가피셜로 '정말 자기도 몰라서'였음이 밝혀졌다. 어쨌든 내 글도 이런 느낌이었다.

1년이나 늦긴 했지만, 당시에 어떤 것들을 했는지 여기에 기록으로 남겨보고자 한다. 지금도 스린이(스프링 어린이)이긴 하지만 당시는 스프링 어린이 수준이 아니라 스프링 수정란 수준으로 아무것도 몰랐던지라 이제와서 소스 코드를 열어보기도 민망하다. 공개해도 되는 부분인지도 애매하고. 그러니 지난번 후기의 부연 설명 정도라고 생각하고 읽어줬으면 좋겠다.

소개합니다. Movisualization

설명

영화 + 시각화의 합성어인 Movisualization은 말 그대로 영화 정보를 시각화해서 볼 수 있는 웹 사이트입니다. 일간 박스오피스를 그래프를 통해 확인할 수 있고, 개별 영화, 영화인에 대한 정보도 확인할 수 있습니다.

링크는 여기로.

주요 기능

오늘의 박스오피스

전 날의 박스오피스의 랭킹을 가져와 관객수를 표시합니다. 그 전날 대비 순위 변동도 표시합니다.

기간별 박스오피스 순위 변동

특정 기간을 선택하여 모든 박스오피스의 순위 변동 추이를 볼 수있습니다. 전체 조회하면 서버가 터지니까 누르지 마세용! ^ㅇ^

영화 정보

개별 영화에 대한 정보를 보여줍니다. 좋아요와 평점 주기는 존재만 하고 쓸 수 없으니 눌러봤자 소용이 없답니다! ^ㅇ^

배우 정보

개별 배우의 정보를 보여줍니다. 이와 관련된 차트도 표시합니다. 평균평점, 네이버 검색량, 인기도, 작품수를 표시하며, 출연한 작품의 장르들을 파이 차트로 표시해줍니다.

UBD(엄복동...) 차트

당시 한창 유행이었던 엄복동 놀이에 편승해 만들어진 기능입니다. 영화 관객수 17만을 1UBD(Unit of Box office Dealing)으로 잡고, 해당 영화가 몇 UBD를 달성했는지를 그래프로 보여줍니다.

기술 스택

Front-End

  • React.js + TS(TypeScript)
  • Billboard.js

Back-End

  • Spring Boot
  • Maria DB
  • Crontab -> Python Scheduler

Used Open API

어떻게 만들었나

아이디어

프로젝트 아이디어의 개괄은 Geon Lee님으로부터 나왔다. 본래 영화가 취미인 건님은 이전에도 이미 영화를 이용한 사이드 프로젝트를 한 적이 있었다. 다른 아이디어 후보가 뭐가 있었는지는 기억나지 않는다.. 여하튼 아이디어 채택은 스무스하게 이뤄졌다.

기술 스택 협의

우리 팀은 프론트 엔드 2명과 백엔드 1명의 조합이었다. 이 프로젝트의 팀 협업은 2가지 레이어로 나눌 수 있었다. 하나는 같은 기술군 내에서의 협의, 두 번째는 서로 다른 직무간의 협의였다. 전자의 경우는 백엔드는 해당하지 않았지만, 프론트엔드 쪽에서는 두 명이서 하나의 프로젝트를 만들어야 했다.

프론트 팀의 기술 스택 협의 : JavaScript vs TypeScript

개인 프로젝트만 하다가 협업 프로젝트를 하면 생각보다 기술 스택 맞추는 데에 들이는 공이 크다는 것을 알게 된다. 일단 팀원들간 지식이 동일할 수 없기에 조율을 해야하는데, 이 과정에서 전체 개발 속도를 위해 자신이 알고 있는 익숙한 방법을 접어야 하는 상황도 종종 생긴다. 백엔드 개발자 5명이 모여있는데, 나 혼자 Python Django를 쓰고 나머지가 전부 Node.js Express를 쓴다면 높은 확률로 내가 Node.js Express를 뒤늦게 배워가며 참가하는 형태가 된다. 물론 이렇게 경로 의존성에만 따라가지는 않고, 멀리 봤을 때 Python Django를 쓰는게 더 좋다는 합의가 이끌어지면, 다른 사람들이 이 기술스택에 따라올 수도 있다.

프론트 팀의 논의에 직접적인 참가를 하진 않았지만, JS를 쓰냐 TS를 쓰냐를 가지고 이야기를 했던 게 기억이 난다. 건님은 TS 유경험자, 다른 프론트엔드 개발자인 정민님은 TS 무경험자였다. 건님은 아래와 같이 주장했다.

"예전에 개인 프로젝트를 하다가 동적 타이핑 때문에 디버깅에 어려움을 겪어봤고, 그 때 TS를 적용해본 이후로 개발에서의 시행착오가 많이 줄었다. 그래서 TS를 쓸 수 있는 환경이라면 적극 도입하는게 맞는 것 같다"

이 주장은 받아들여졌고, 건님이 정민님의 적응을 도와준다는 조건으로 프론트 팀은 TS를 사용하기로 결정이 났다.

백엔드 팀의 기술 스택 협의 : Java Spring Boot VS Node.js Express

백엔드는 나 혼자였으므로 팀이라고 부르기도 애매했지만, 멘토님이 백엔드 개발자셨기에 나는 백엔드 관련 논의를 멘토님과 했었다. 첫 난관은 바로 언어와 프레임워크의 선택이었다. 취준생 시절만 해도 나는 Node.js Express 이외의 프레임워크로 백엔드 개발을 해본 적이 없었으며, 이 때 라인 인턴십으로 겨우겨우 Spring boot의 세계에 발가락 정도만 담그는 정도였다. 그렇다고 노드를 잘했느냐면 그것도 아니긴 했으나.. 적어도 당시의 내 숙련도는 Node.js Express가 Java Spring Boot보다 높았다.

문제는 멘토님이 스프링 개발자셨기에 내가 노드를 선정할 경우 멘토님의 도움을 기대하기가 힘들었다는 점이다. 아직도 첫 만남 때 node.js express를 쓰고 싶다고 의견을 말했을 때, 멘토님이 "아.. 제가 도와드릴 일이 생각보다 별로 없겠군요" 하며 난감해하셨던 것이 떠오른다. 결국 고민 끝에 나는 Java Spring Boot를 사용하기로 결정했다. 쇠도 가장 뜨거울때 내리치는 게 제일 단단해지는 법이니, 지금도 학습 중이고, 앞으로도 계속 배워나가야 할 프레임워크를, 멘토님 도움을 받아가며 학습하는 것이 좋을 것이란 생각이었다.

그러나 그 결과 단단해진 게 아니라 부서졌다는 후문이 들려온다

비즈니스 로직 구상

UML 작성은 따로 하지 않았다. 해커톤에 UML 작성을 할 시간이 있을 리도 만무했고..

Use Case들을 뽑아보자면 이랬다.

하루 주기로 박스 오피스 랭킹 수집하기

박스오피스 랭킹은 변하지 않으므로 미리 가져오는 방식을 채택. python으로 KOBIS API 콜을 하고, 그 결과를 db에 저장하는 스크립트를 만들고, 이를 crontab을 이용해 스케줄링했다.

실행 시간은 매일 00시 15분. 박스 오피스 집계가 그 쯤에 끝나기 때문이었다.

영화 정보, 배우 정보 표시하기

영화, 배우 정보는 미리 수집하는 것이 의미가 없었고, 모든 영화에 대해서 수집하는 것이 불가능했으므로 해당 open API를 직접 사용하도록 했다. 콜할 때마다 API 토큰의 일일 사용 횟수가 줄어든다는 단점이 있었지만, 어차피 해커톤용 프로젝트였으므로 신경쓰지 않았다.

배우 정보에는 여러가지 정보를 한꺼번에 담아야만 했다. 네이버 검색량, 인기도, 작품수, 평균 평점 등이었는데, 이를 프론트에서 일일이 전부 ajax 요청을 넣는 것은 처리해줘야 할 예외가 많기도 했고,  프론트 팀으로부터는 "서버로부터 받은 정보를 최대한 가공하지 않는 기조로 가고 싶다"는 의견이 있었기에, 이 부분은 백엔드가 먼저 프론트의 요청을 받아 REST API call을 해서, 프론트가 받아서 쉽게 쓸 수 있도록 가공해서 보내주게 했다.

이렇게 가공되어 전달된 데이터는 프론트에서 billboard.js를 통해 정말 예쁘게 꾸며서 표시해줬다.

직면한 문제점

서로 다른 API 콜에서 어떻게 데이터를 일치시키지? 결측치는?

가장 큰 문제는 서로 다른 소스로부터 얻은 데이터들의 결합이었다. KOBIS로부터 얻을 수 있는 정보는 영화 랭킹, 그리고 각 영화에 대한 최소한의 정보였다. 좀 더 많은 영화 정보를 얻어오기 위해서는 TMDB의 API에서 call을 해와야 했는데, 문제는 KOBIS에서 얻은 영화를 TMDB에 조회한다고 100% 검색이 성공하는 게 아니란 점이었다.

영화 '투모로우'의 원제는 'The day after tomorrow'다. TMDB에서 '투모로우'를 검색하면 이 영화는 나오지 않는다.

KOBIS에서 내부적으로 얻어지는 영화 정보는 어디까지나 국내 상영 기준이었다. 그렇기에 개봉된 영화제목으로 TMDB에 검색하면 제대로된 정보가 나오지 않는 경우가 많았고, 따라서 "원제" 기준으로 검색을 해야만 했다. KOBIS가 영화의 원제를 같이 제공해주긴 하지만, 누락되어 있거나 잘못 기재되어 있는 경우도 있었다. 같은 영화가 여러번 리메이크된 경우 또한 잘못 검색될 여지가 있었다. KOBIS의 영화들은 각자의 id를 가지고 있어서 KOBIS 내부적으로는 식별이 되지만, 이를 TMDB와 연결시킬 수는 없었다. 이 과정에서 누락되거나 잘못 매칭되는 데이터들이 생겼다. 특히나 한국인 배우는 TMDB에 없는 경우도 많아서 난감했다.

화제도 -> 검색이 많이 되는 사람은 인기 있는 사람인가?

배우 설명의 아래에는 평균 평점, 인기도, 네이버 검색량, 작품수 4가지의 매트릭스로 구성된 그래프가 나온다. 이 중 "네이버 검색량"은 원래 인기도의 측정 지표 중 하나로 활용될 예정이었다. 그러나 네이버에서 많이 검색되는 사람이 모두에게 인기있는 사람인가? 는 한번 생각해볼 문제였다.

배우의 예명이기도 한 '공유'는 너무 널리 쓰이는 단어다. 이처럼 검색량이 많다는 것이 해당 인물의 인기를 증명하진 않는다. 물론 공유가 모두에게 사랑받는 배우란 사실은 자명하다.

동명이인이 있거나, 이름이 다른 다른 개념 혹은 사물과 겹친다면 당연히 검색량이 뻥튀기될 수밖에 없다. 여기에 덧붙여서, 논란을 일으킨 사람인 경우는 당연히 검색량이 많을텐데, 불미스러운 일과 관련된 사람이 제일 인기많은 사람이라는 결론이 나오게 되는 것이다.

그렇기 때문에 우리는 이를 "네이버 검색량"이라는 항목으로 따로 빼야만 했다.

API 콜 횟수 제한 문제

TMDB와 KOBIS에서 제공하는 OPEN API는 (당연하게도) Access Token을 발급받고, 이 토큰마다 일일 허용량을 할당해서 사용하는 방식이었다. 개인 사용일 경우는 모르겠지만, 이 토큰이 서버단에서 사용이 된다면, 해당 서비스에 요청이 한번 들어갈 때마다 API 콜을 하게된다는 것을 의미했다. 해커톤용 프로젝트였으니 토큰이 고갈될 일은 없었지만, 실제 서비스라면 이런 부분을 고민해야 했기에 조금 더 좋은 방법을 생각하고 싶었다.

그렇게 해서 떠오른게 백엔드가 프록시 겸 캐시 역할을 맡는다는 점이었는데, 모자란 시간으로 결국 구현되지는 못했다.

그래서 해커톤 어떻게 끝났나요

백엔드의 역량 부족으로 프로젝트 규모가 축소되었다. 프론트에서는 더 추가하고자 하는 기능들이 많았는데, 기본적으로 내가 스프링의 기초 사용법과 씨름하느라 버린 시간이 너무 많았고, 그 이후로도 내가 알지 못하는 에러가 발생해서 핸들링하는데 버린 시간이 많았다. 해커톤 종료를 몇 시간 앞두고 또 예상치 못한 에러가 떴을 때, 나는 "아.. 백엔드는 솔직히 여기까지인 것 같습니다. 기능 추가는 무리에요." 라고 선언했고, 그렇게 우리의 프로젝트는 종료되었다. 프론트의 역량을 내가 제한한 것 같아서 썩 좋은 기분은 아니었다.

그 이후에 있었던 일들은 이미 지난번 회고에서 언급을 다 했으니 이만 줄이도록 하겠슴미.