1. 프로젝트 개요

  • 프로젝트 명: SyncMovie(싱크무비)
  • 핵심 컨셉: 단순한 평점 기반 추천을 넘어, 사용자가 선택한 줄거리와 인물(감독/배우)영화를 기반으로 영화를 추천하고, 리뷰를 공유하는 커뮤니티 서비스
  • 개발 기간: 2025.12.20 - 2025.12.24(5일)
  • 개발 인원: 2인
    • 이영종(팀장): 인증, 권한관리, 커뮤니티 기능 및 페이지 개발
    • 문희원(팀원): 데이터 수집, 추천 기능 및 페이지 개발
  • 기술 스택
    • Backend: Django REST Framework (DRF)
    • Frontend: Vue3, Pinia, BootStrap
    • Database: SQLite
    • Data: TMDB API
  • GitHub Link

2. 주요 기능 및 아키텍처

주요 기능

  • 사용자가 선택한 영화의 줄거리와 배우, 감독 정보를 기반으로 TMDB 데이터를 필터링하여 추천 영화 제공
  • TMDB API 와 YOUTUBE API를 활용하여 영화의 예고편 제공
  • 리뷰 커뮤니티: 영화별 평점 및 상세 리뷰 작성, 사용자 간 소통을 위한 소셜 피드 및 마이페이지 기능 제공.
  • RESTful API: Django를 활용해 프런트엔드와 백엔드를 완전히 분리하여 데이터 교환 효율성 극대화.

아키텍처

- ERD

- Vue Tree

3. 기술적 도전과 해결 과정 (Trouble shooting)

1. 프로젝트에 사용할 데이터 취득과 전처리 문제

프로젝트에 사용할 영화 데이터를 구하고 전처리 하는 과정에 많은 시간을 투자했고

TMDB API로 최신 인기 영화 데이터를 호출해서 사용하기로 결정하기까지 많은 의사결정을 거쳤음.

1. Kaggle에 TMDB 1M 데이터 사용

가장 처음 선택한 데이터는 Kaggle에 있던 공개된 데이터로 출시일, 유명도, 평점 등을 기준으로 최신영화, 평점이 일정 점수 이상인 영화 등을 필터링 하고 Null 값과 비어있는 값 등을 전처리해서 약 20,000개의 데이터를 확보, 사용했음.

그러나 데이터가 모두 영어여서 한국인 사용자를 가정하고 진행하는 프로젝트 특성 상 UI, UX적인 측면에서 문제가 있었음.

2. TMDB API 사용

TMDB API 중 popular를 이용하여 평점이 높은 영화 데이터 1차 호출, 이후 응답받은 데이터 중 TMDB ID를 이용해 detail과 actor 정보를 추가로 요청해서 최종 데이터 수집

이후 포스터 URL을 완성하고 배우 정보를 5명 까지만 수집하는 등 전처리 과정을 거쳐 최종 1,000개 데이터 확보(data_preprocessing.py 파일 참고)

한글로 된 최신 영화 데이터들을 확보할 수 있었으나 데이터 수가 부족한 문제가 있었음. -> 추천 기능 약화

3. TMDB API 사용 (데이터 수 증가)

초기 수집하는 데이터 수를 증가하여 전처리 이후 약 2,700개 데이터를 확보. -> 추천 기능 강화

그러나 overview(줄거리) 컬럼에 빈 문자열이 제대로 필터링 되지 않았던 것을 발견

4. TMDB API 사용 (데이터 수 증가 및 전처리 강화)

최종적으로 초기 6,000개 데이터를 불러온 후 전처리를 좀 더 꼼꼼히 진행하고 최종적으로 약 3,700개 데이터를 확보 및 사용

이로 인해 가장 양질의 데이터를 확보하여 추천 품질도 가장 좋았으며, 기본 UI, UX 측면에서도 가장 좋은 데이터 확보

 

2. 생성형 AI를 API로 연동하여 닉네임 추천 받기

간단한 작업이라 생각하여 gemini-2.0-flash 모델을 사용하고 프롬프트에도 "한글만 사용하라", "5~12자로 생성하라", "특수문자를 사용하지 말아라" 등 꼭 필요한 요청사항 외에 다양한 요구사항을 넣고 길게 작성하였음

그 결과 생성 시간도 30초 정도로 매우 길고 계속 비슷한 닉네임만을 추천해서 결과가 매우 만족스럽지 못했음

이에 모델을 gemini-2.5-flash로 변경했는데 그래도 크게 성능이 개선되지 않았음

결국 gemini-2.5-pro로 최종 결정하고 프롬프트도 꼭 필요한 것들로만 작성해서 최종 생성 시간을 10초 정도로 줄일 수 있었음

간단한 기능이라 프롬프트 대충 작성해서 api로 요청 받아서 결과값 띄워주면 될 거라고 생각했는데 생각보다 정교한 프롬프트 작업과 모델 선정이 필요했음

 

3. 배포하기(배포 쉬워졌다며,,, 왜 이렇게 어려운건데,,,)

1. CloudType(back) + Netlify(front)

- github repository를 연동해서 바로 배포하는 방법을 사용했는데 프로젝트 repository에 back과 front가 둘 다 들어있고
각각 다른 툴로 배포하려고 할 때는 work directory를 잘 설정해줘야 함!!(은근 까먹음)
- django secret key, 사용한 여러 API key 등 환경 변수 세팅 잘 해줘야 함(당연하지만 은근 까먹음)
- migrate나 gunicorn 실행을 위한 Run command 설정 해줘야 함
- front 배포할 때는 코드에 local로 작성한 요청 주소들을 배포한 back요청 주소로 모두 교체해야 함
(처음 코드를 작성할 때부터 배포할 때를 고려해서 하드코딩하지 말기 ㅠㅠ)
- front와 back이 서로 통신할 수 있도록 django settings.py에서 ALLOWED_HOST, CORS, CSRF 등 설정해줘야 함
(이게 진짜 초보자에게 어려운 부분인듯 ㅠㅠ)

이런 여러가지 사항들을 Gemini를 통해 알아가면서 거의 4시간 만에 배포에 성공...했으나...!

무료 티어에서 제공하는 메모리가 너무 작아서 추천 기능에서 out of memory 발생!! 백엔드 서버가 강제로 꺼짐!!!!

뿐만 아니라 CloudType는 무료티어일 경우 매일 한 번씩 강제로 서버가 꺼져서 다시 켜줘야 하고 둘 다 무료사용량을 테스트 하는 동안 전부 사용해버려서 아예 새로운 조합으로 다시 배포해보기로 결정

2. Supabase(DB) + Koyeb(back) + Vercel(front)

DB가 없으면 back 서버가 켜질때마다 DB를 migrate 해야하고 기존 데이터도 모두 날아가니까 다시 하는 김에 DB도 해보기로 함

배포툴마다 UI가 달라서 "환경 변수 설정하는게 어디있지...?", "run command는 어디에..?", "요청 주소는 뭐지" 등등 조금 헤매기는 했지만 일단 기본 설정은 한 번 해봤다고 전보다는 조금 빠르게 했음

그러나 새롭게 추가한 Supabase에 데이터를 적재하는게 생각보다 쉽지 않았음ㅠㅠ

거기에 프론트랑 백엔드랑 기본적인 통신조차 자꾸 실패하니까 배포따위 안해버리고 싶었지만

거의 6시간 만에 DB에 테이블 생성(데이터 없음), 백엔드 서버 배포, 프론트 배포, 백엔드와 프론트 통신 성공(회원가입 후 로그인 성공 (근데 겁나 느림))까지 할 수 있었다,,,

그 험난했던 여정은 gemini가 아래와 같이 정리해줬다

🚩 1단계: 데이터베이스 연결 및 로컬 접근 시도
로컬 컴퓨터의 데이터를 Supabase 클라우드 DB로 옮기려 했으나, 네트워크 계층의 장벽에 부딪혔던 시기입니다.
- 시도: Git Bash 및 로컬 Django 설정을 통해 Supabase에 loaddata 시도.
- 발생 에러:
    - bash: !1204: event not found: 비밀번호 내 특수문자(!)가 Bash 히스토리 확장 기능을 건드려 발생.
    - django.db.utils.OperationalError: could not translate host name: 로컬 ISP(인터넷 서비스 제공업체)의 DNS가
      Supabase 도메인을 해석하지 못함.
    - Connection timed out (10060): IP 주소로 직접 접근했으나 로컬 방화벽/네트워크에서 DB 포트(5432) 접속 자체를 차단함.
- 해결방안(해결 못함): 비밀번호 인코딩(%21) 적용 및 로컬 시도 중단.
           대신 이미 DB와 통신이 검증된 Koyeb 서버 내부에서 해결하기로 전략 수정.

🚩 2단계: 백엔드 서버 구축 및 헬스 체크 통과
Koyeb에 Django 서버를 올리는 과정에서 서버 부팅과 데이터 적재가 충돌했던 시기입니다.
- 시도: Koyeb Run command에 loaddata와 gunicorn 실행 명령을 동시에 넣음.
- 발생 에러:TCP health check failed on port 8000: 3,800개가 넘는 데이터를 넣느라 Gunicorn이 정해진 시간 내에 응답
                 하지 못해 Koyeb이 서버가 죽었다고 판단하고 강제 종료함.
- 해결: loaddata 명령을 분리하고 서버 실행(gunicorn)만 집중시켜 Healthy 상태를 먼저 확보함.

🚩 3단계: 프론트엔드-백엔드 연동 및 통신 이슈
Vercel에 올린 프론트엔드와 Koyeb 백엔드가 서로 대화하게 만드는 과정입니다.
- 시도: Vercel 환경 변수에 Koyeb URL을 설정하고 API 요청.
- 발생 에러:
    - 404 Not Found (Vercel 도메인 포함): 요청 주소가 https://sync-movie.vercel.app/https://urban-sheila... 처럼 형성
     됨. 프론트엔드에서 상대 경로로 인식해 자기 자신(Vercel)에게 요청을 보낸 상황.
     Failed to load resource: CORS 설정 미비로 인해 브라우저가 보안상 요청을 차단함.
- 해결:Vercel 환경 변수에 https://를 명확히 포함하여 절대 경로로 수정.
          settings.py에서 CORS_ALLOW_ALL_ORIGINS = True 및 미들웨어 순서 조정을 통해 통신 허용.


✅ 요약: 현재까지 해결된 것 vs 남은 숙제
상태 항목 내용
성공 네트워크 통로 프론트(Vercel)에서 백엔드(Koyeb)로 요청이 전달됨
성공 서버 상태 Django 서버가 Koyeb에서 Healthy 상태로 구동됨
미결 데이터 적재 api_data.json의 영화/장르/배우 데이터가 DB에 아직 없음

원래 하려고 했던 추천 기능은 테스트 해보지도 못하고 두 번째 배포 시도도 상처 뿐인 마음과 함께 종료,,,

이후 Koyeb서버 빌드 후 console에서 loaddata를 하려고 했는데 그것도 메모리 문제로 안돼서 데이터를 적재하는 별도의 python 코드를 짜서 push 하고 바로 loaddata 하는 대신 새로 만든 fast_load.py 파일을 실행하는 방법으로 데이터 적재를 시도했다

그런데 이것도 장르별, 배우별, 영화별로 데이터를 넣으려니 그것도 메모리가 부족해서 100개 단위로 넣는 방법을 시도했다가 그것도 계속 멈춰서 10개씩 시도하는 방법으로 반복 시도...

파이썬 코드 짜고 ->  push -> 재배포 -> console에서 명령실행의 무한 루프....

그 결과 전체 데이터의 일부인 장르(19개), 배우(852개), 영화(213개) 정도의 데이터를 supabase에 적재했다

그리고 배포한 사이트에서 회원가입 후, 로그인까지 잘 되는 것을 확인했으나

회원가입 페이지
백엔드 서버 로그 기록
supabase에 새롭게 들어간 user data
적재한 data에 M:M 관계 데이터가 들어가지 않아서 메인페이지에서 영화 데이터를 불러오지는 못했다...
데이터 로딩에 실패한 메인 화면...
결과적으로 배포는 실패했지만 리소스 부족 때문이라고 여기며좀 더 공부해서 다음 프로젝트에서 제대로 해보는 것으로 마무리했다끝까지 해보고 싶기도 했지만 더 중요한 공부들이 많고 여기에 시간을 더 쓰면 안 될 것 같아서 이건 여기서 끝!

 

4. 협업 및 프로젝트 관리

Git 규칙

branch 운영 방식

  1. master branch에 직접 수정 x
  2. yj, hw 브랜치로 분리해서 작업 후 이상 없을 시 master branch로 merge
  3. 최종 merge전 팀원과 상의하고 conflict 발생 시 협의 후 코드 선택

commit 기록 내역 원칙

  1. 개발 기능 단위로 commit 진행
  2. 개발 중 잘못된 사항이 발견되어 수정한 경우 동일한 commit내용에 _수정을 붙여서 commit
  3. commit 내용 양식: 요구사항번호[_기능명][_수정(수정한 경우)]
기존에 많이 알려진 검증된 branch 전략들은 모두 무시한 채
단순히 master 브랜치는 건들지 말고 니꺼 내꺼 브랜치 만들어서 필요 시점마다 협의해서 merge하자! 전략 선택!
그 결과 의외로(?) 아무런 문제 없이 원활한 협업과 코드 관리가 이루어졌는데
이건 순전히 함께 개발한 인원이 2명으로 매우매우 적고 팀워크가 잘 맞았기 때문이라고 생각
commit 기록 원칙도 처음에 정했는데 정작 개발하면서 거의 지켜지지 않았음...ㅋㅋㅋ

하지만 이런 모든 전략들과 원칙은 결국 "원활한 협업"을 위한 것이기 때문에 이번 프로젝트에서는 중요도가 좀 떨어졌던 부분이라고 생각하고 앞으로의 프로젝트에서는 필요하다면 철저히 잘 지킬 수 있을 것이라 생각함

 

5. 잘한 점 및 아쉬운 점 (Self-Reflections)

잘한 점

기획부터 백엔드, 프론트 개발, 배포까지 모두 직접 진행함으로 모든 과정을 이해할 수 있었던 것

티어와 자주 소통함으로서 원활한 협업을 진행한 것

error 메세지를 분류하여 사용자가 현재 상황을 인식할 수 있도록 하고(진행중이여서 기다리면 되는지, 아니면 문제가 있어서 뭔가를 수정해야 하는지 등) 다음 행동을 가이드 해서 UI, UX를 개선해 나간 것

처음 데이터를 수집한 것에서 만족하지 않고 계속해서 더 양질의 데이터를 얻기 위해 찾아보고 전처리 한 것

아쉬운 점

개발 기간이 짧아서 정말 홈페이지의 기본적인 틀만 잡고 기능들도 간단한 것들 밖에 추가하지 못했던 점이 아쉬웠다

생성형 AI로 닉네임만 추천해주는 것이 아니라 프로필 이미지도 추천해주는 기능도 추가하고 1달 주기로 TMDB API에서 최신 영화 데이터를 자동으로 불러와서 영화 데이터들을 자동으로 업데이트 하도록도 만들고 싶었는데 시도해 보지 못한 것이 아쉽다

하지만 만약 다 구현했다면 배포 과정에서 또 어떤 지옥을 맞이했을지 상상만 해도 아찔하다,,,

그리고 개발 초반에는 문서화 하는 것에도 집중했는데 점점 시간이 없어지면서 문서화에 들이는 시간이 줄어들었던 게 조금 아쉽다

개발에 투자하는 시간과 문서화에 투자하는 시간이 어느 정도 되어야 가장 효율적이고 균형 있는가는 항상 고민이겠지만

이번 프로젝트에서는 문서화에 투자했던 시간이 많이 부족했던 것 같기도 하다 

 

6. 마무리하며

SyncMovie는 나의 첫 그럴듯한 프로젝트로, 프로젝트 기획부터 배포까지 모든 과정을 직접 해볼 수 있었던 소중한 프로젝트였다

비록 개발 기간도 짧고 함께한 인원도 적은 토이프로젝트 수준이었지만 풀스택으로 모든 과정을 경험해보고 협업도 해보면서 앞으로 있을 프로젝트를 성공적으로 해나가기 위한 훌륭한 초석이었다고 생각한다

제일 재밌었던 건 Gemini-2.5-pro로 닉네임 추천 기능 완성하고 닉네임 추천 받았을 때 재밌는 닉네임이 나왔을 때,

제일 기억에 남는 건 인증과 권한 관리 부분을 개발할 때, 회원가입과 로그인 과정부터 UI, UX적인 측면에서 개선할 수 있는 부분이 얼마나 많고 다양한지 깨달았을 때,

제일 힘들었던 건 배포를 시도했던 전 과정,,,

+ Recent posts