Mini Project 01 — LLM/RAG 기반 영화 흥행 분석 시스템

전체 소스코드는 GitHub에서 확인할 수 있습니다. hojjang98 / skshielders-rookies-28 — projects/week_03 & week_04


프로젝트 소개

이 프로젝트는 SK쉴더스 루키즈 28기 첫 번째 팀 미니프로젝트로, Week 3 & 4 (총 2주) 를 통합한 집중 개발 기간에 수행되었다.

본인은 해당 프로젝트에서 팀장을 맡아 전체 아키텍처 설계, 역할 분담, QA, 발표 구성까지 총괄하였다.

단순한 기술 구현을 넘어, “왜 이 데이터가 이 결과를 내는가?” 라는 인사이트 중심의 분석을 팀 전체가 발표에서 설명할 수 있도록 이끄는 것이 팀장으로서의 핵심 목표였다.

팀원 모두가 혼자 앞서가는 100점이 아닌, 함께 도달하는 70~80점을 목표로 운영했다. 결과보다 과정의 이해를 강조하고, 최종 발표에서는 숫자가 아닌 “이유” 를 설명하도록 이끌었다.


프로젝트 개요

LLM/RAG 기반 영화 흥행 분석 시스템은 TMDB 영화 데이터를 기반으로 흥행 요인을 다각도로 분석하고, RAG(Retrieval-Augmented Generation) 기술을 통해 사용자 질의에 근거 기반 영화 추천AI 분석 리포트를 제공하는 종합 분석 플랫폼이다.

  • 데이터 소스 — TMDB (The Movie Database) API + 직접 수집한 정제 데이터셋
  • 핵심 기술 — ChromaDB Vector Store, LangChain, OpenAI GPT-4o-mini, Streamlit
  • 분석 범위 — 수천 편의 영화 데이터를 기반으로 ROI / Profit / 평점 / 장르 / 감독 등 다차원 분석

프로젝트 일정 (Week 3 & 4)

날짜 주요 작업
11.15 (Day 1) 데이터 클리닝 계획 수립, TMDB 데이터 인코딩 / 이상치 / 결측치 처리 기준 정의
11.17 (Day 2) TMDB API 연동, Embedding용 텍스트 결합 및 Vector DB 구축
11.18 (Day 3) Streamlit 멀티 페이지 구조 설계, @st.cache 전략 적용, Plotly 시각화 구현
11.19 (Day 4) LangChain / RAG 분석 모델 통합, ProductionRAG 클래스 완성, PPT 초안 제작
11.20 (Day 5) RAG 일관성 검증, 시연 스크립트 확정, 최종 발표 자료 완성
11.21 (Day 6) 최종 프레젠테이션 발표 및 Q & A

시스템 아키텍처

전체 시스템은 데이터 레이어 -> 분석 레이어 -> 서비스 레이어 의 3단 구조로 설계했다.

데이터 레이어

  • TMDB API 호출 (tmdb_api.py) => 최신 인기 / 개봉 예정 영화 수집
  • Movie_Preprocessing.ipynb => 이상치 제거, 결측치 보정, ROI / Profit 컬럼 생성
  • Movie_Vector_DB.ipynb => 정제된 데이터를 텍스트로 변환, OpenAI Embedding 후 ChromaDB 저장

분석 레이어

  • data_loader.py => @st.cache_data 기반 DataFrame 로드 및 캐싱
  • vector_db.py => @st.cache_resource 기반 ChromaDB 클라이언트 로드 및 검색
  • llm_utils.py => RAG 추천 체인 + 대화형 추천 + 흥행 요인 분석 (OpenAI 호출)
  • production_rag.py => ProductionRAG 클래스 — 보수적 ROI 예측 + LLM 종합 리포트 생성

서비스 레이어 (Streamlit 멀티 페이지)

  • 홈.py => 대시보드 진입점, 데이터 통계 요약 카드 UI
  • 1_영화 데이터 탐색 대시보드.py => EDA (장르 / 연도 / 국가 분포)
  • 2_흥행 지표 분석.py => ROI / Profit 기반 Top 10% 영화 분석
  • 3_감독별 흥행 분석.py => 감독 랭킹, 흥행 성공률, 장르별 분석
  • 4_영화 제작 분석 시스템.py => 기획안 입력 -> AI 투자 판단 리포트 출력

주요 기능

  • RAG 기반 영화 추천 — 자연어 질의 또는 영화 제목 입력 시 Vector DB 검색 후 LLM 이 추천 사유를 자연어로 설명
  • 흥행 지표 분석 — ROI (투자 수익률) 와 Profit (이익) 기준으로 Top 10% 영화의 특징 분석
  • EDA 대시보드 — 연도별 / 장르별 / 국가별 통계 및 추이를 Plotly 인터랙티브 차트로 시각화
  • 성능 최적화 — @st.cache_data (데이터 로드) 와 @st.cache_resource (Vector DB 클라이언트) 를 분리 적용
  • 모듈 분리 — llm_utils.py / vector_db.py / data_loader.py / production_rag.py 로 책임을 명확히 분리
  • AI 투자 판단 시스템 — 기획안 (장르 / 예산 / 시놉시스) 입력 시 보수적 ROI 계산 + LLM 종합 리포트 생성

핵심 코드 설명

1. RAG 추천 파이프라인 — 검색과 생성의 결합

RAG 의 핵심은 “Vector DB 에서 가져온 실제 데이터를 LLM 에게 근거로 제공” 하는 것이다. 할루시네이션 없이 우리 데이터셋 안에서만 추천하도록 설계한 이유도 여기에 있다.

전체 흐름 (get_rag_movie_recommendation):

1. 사용자 질의 (user_query) 를 ChromaDB 에 벡터 검색
   => collection.query(query_texts=[user_query], n_results=5)

2. 검색된 메타데이터 (제목, 장르, 평점, 줄거리 등) 를 문자열로 변환
   => documents_text 리스트로 조합

3. LangChain ChatOpenAI (gpt-4o-mini) 에 컨텍스트로 삽입
   => SystemMessage + HumanMessage 구조

4. LLM 이 "왜 이 영화를 추천하는가" 를 자연어로 설명
   => response.content 반환

핵심 RAG 프롬프트 구성 (축약):

context = "\n\n---\n\n".join(documents_text)

prompt = f"""
사용자 요청: "{user_query}"

검색된 영화 정보:
{context}

위 영화들을 바탕으로 추천 사유를 작성해주세요:
1. 사용자 요청과 추천 영화들의 연관성
2. 각 영화의 주요 특징 (장르, 평점, 분위기 등)
3. 왜 이 영화들을 추천하는지 구체적인 이유
"""

2. Vector DB 캐싱 — @st.cache_resource 적용

Streamlit 에서 ChromaDB 클라이언트를 매 렌더링마다 새로 생성하면 심각한 성능 저하가 발생한다. @st.cache_resource 데코레이터를 사용해 최초 1회만 로드하고 이후 재사용한다.

@st.cache_resource
def load_vector_db():
    openai_api_key = os.getenv('OPENAI_API_KEY')

    embedding_function = embedding_functions.OpenAIEmbeddingFunction(
        api_key=openai_api_key,
        model_name="text-embedding-ada-002"
    )

    # 두 경로를 순차 탐색하여 DB 위치 유연하게 처리
    possible_paths = [
        Path("../vector_db/chroma_db"),
        Path("vector_db/chroma_db"),
    ]
    db_path = next((p for p in possible_paths if p.exists()), None)

    chroma_client = chromadb.PersistentClient(path=str(db_path))
    collection = chroma_client.get_collection(
        name="movies",
        embedding_function=embedding_function
    )
    return collection

@st.cache_data 와의 역할 구분:

  • @st.cache_data => DataFrame 같은 직렬화 가능한 데이터 객체 캐싱 (data_loader.py)
  • @st.cache_resource => DB 연결, API 클라이언트 등 공유 자원 캐싱 (vector_db.py)

3. ProductionRAG — 보수적 투자 분석 엔진

이 프로젝트에서 가장 공을 들인 부분이다. 단순히 “평균 ROI 가 몇 배입니다"가 아니라, 실제 투자 판단에 쓸 수 있는 보수적 수치를 제공하는 것이 목표였다.

보수적 기준 설계 원칙:

  • 기대 수익 기준 => 평균(mean) 이 아닌 하위 40% (quantile 0.40)
  • 최악 시나리오 => 하위 15% 수익을 별도 제시
  • BEP (손익분기점) 기준 => ROI 2.5배 이상 을 수익성 달성으로 판정
  • 투자 판단 체계:
    • ROI 2.5배 이상 => 투자 추천
    • ROI 2.0 ~ 2.5배 => 조건부 추천
    • ROI 2.0배 미만 => 재검토 필요

핵심 계산 로직 (_analyze_similar_performance 축약):

# 예산 범위 ±50% 내 유사 영화만 필터링
budget_range = (proposed_budget * 0.5, proposed_budget * 1.5)
similar_subset = [m for m in similar_movies if budget_range[0] <= m['budget'] <= budget_range[1]]

rev_series = pd.Series([m['revenue'] for m in similar_subset])

# 보수적 기준: 하위 40% 수익을 베이스로 설정
conservative_base = rev_series.quantile(0.40)

# 상업성 페널티 × 예산 효율 페널티 동시 적용
final_adjusted_revenue = conservative_base * commercial_factor * budget_efficiency
final_adjusted_roi    = final_adjusted_revenue / proposed_budget

is_profitable = final_adjusted_roi >= 2.5   # BEP 달성 여부

4. 상업성 리스크 스코어링 — 시놉시스 분석

시놉시스 내 특정 키워드가 포함될 경우 기대 수익을 자동으로 하향 조정하는 로직이다. 예술 영화 또는 실험적 작품처럼 대중성이 낮은 기획안에 현실적인 경고를 제공한다.

주의 키워드 예시:

  • 치명적 독소 => “실험적”, “흑백”, “다큐멘터리”, “관조적”, “철학적”

  • 중간 수준 주의 => “초현실”, “전위”, “미니멀”, “독백”, “무대극”

    penalty_factor = 1.0 for word in caution_keywords: if word in synopsis.lower(): penalty_factor *= 0.8 # 키워드 발견 시마다 기대 수익 20% 삭감 return max(penalty_factor, 0.4) # 최소 40% 보장 (극단적 경우도 기회 부여)


5. 대화형 RAG — 의도 분류 후 분기 처리

단순 추천 응답이 아닌, 사용자 발화 의도를 먼저 분류 한 뒤 처리하는 2단계 구조로 설계했다.

1단계 — 의도 분류 (LLM 호출)
   형식: RECOMMEND | 검색키워드  또는  CHAT | 응답내용

2단계 — 분기 처리
   RECOMMEND => Vector DB 검색 후 RAG 추천 체인 실행
   CHAT      => 이전 대화 컨텍스트(최근 5개)를 포함하여 일반 대화 응답

이 구조 덕분에 “액션 영화 추천해줘” 와 “지금 몇 시야?” 를 같은 채팅창에서 자연스럽게 처리할 수 있다.


프로젝트 파일 구조

movie_project/
├── app/
│   ├── 홈.py                           -- Streamlit 메인 앱 (통계 카드 + 기능 소개)
│   ├── pages/
│   │   ├── 1_영화 데이터 탐색 대시보드.py   -- EDA 시각화
│   │   ├── 2_흥행 지표 분석.py             -- ROI / Profit 기반 분석
│   │   ├── 3_감독별 흥행 분석.py            -- 감독 랭킹 및 성공률
│   │   └── 4_영화 제작 분석 시스템.py       -- AI 기획안 투자 판단
│   └── utils/
│       ├── data_loader.py              -- @st.cache_data 기반 데이터 로드
│       ├── llm_utils.py               -- RAG 추천 체인 + 흥행 요인 분석
│       ├── production_rag.py          -- ProductionRAG 클래스 (보수적 ROI)
│       ├── tmdb_api.py                -- TMDB API 호출 유틸리티
│       └── vector_db.py              -- @st.cache_resource ChromaDB 관리
├── data/                             -- 원본 / 정제 데이터 저장소
├── notebooks/
│   ├── Movie_Analysis.ipynb          -- EDA 및 일반 분석
│   ├── Movie_Preprocessing.ipynb     -- 전처리 상세 기록
│   └── Movie_Vector_DB.ipynb         -- Vector DB 구축 기록
└── vector_db/                        -- (Git 제외) ChromaDB 임베딩 저장소

SOC 관점 연계 — 데이터 기반 의사결정 파이프라인

이 프로젝트의 구조는 보안관제(SOC) 의 분석 사이클과 구조적으로 동일하다.

실무 단계 보안 관제 예시 본 프로젝트 대응
수집 (Collection) 로그 / 패킷 수집 TMDB API + CSV 영화 데이터 수집
전처리 (Preprocessing) 로그 정규화, 노이즈 제거 결측치 / 이상치 제거, ROI 컬럼 생성
분석 (Analysis) 이상 행위 탐지, 패턴 분석 흥행 지표 분석, 감독별 성공률 분석
인텔리전스 (Intelligence) 위협 인텔리전스 연계 TMDB API 실시간 트렌드 + RAG 근거 추천
보고 (Reporting) 대시보드 / 경보 발령 Streamlit 대시보드 + AI 투자 판단 리포트

학습 연결 포인트

  • Pandas & EDA => TMDB 데이터 클리닝, 결측치 및 이상치 제거, ROI / Profit 컬럼 생성
  • Streamlit Caching => @st.cache_data / @st.cache_resource 를 역할에 따라 분리 적용
  • RAG System => ChromaDB Vector Store 로 텍스트 임베딩 검색 구조 구현
  • LLM Prompting => 추천 사유 생성 및 흥행 분석을 위한 시스템 프롬프트 설계
  • Modularity => utils 폴더 내 기능별 모듈 분리로 유지보수성 확보
  • Plotly.express => 장르 분포, ROI 분포, 시계열 추이 동적 시각화

팀장으로서의 회고

이번 프로젝트는 기술보다 팀을 어떻게 이끌 것인가 를 더 많이 고민한 경험이었다.

  • 역할 분담 원칙 — 각자의 이해 수준에 맞는 파트를 맡기되, 전체 흐름을 모두가 알 수 있도록 공유
  • QA 과정 — 최종 발표 전날 RAG 응답 일관성을 직접 검증하고, 불안정한 케이스는 프롬프트를 수정
  • 발표 전략 — “이 데이터에서 이런 인사이트를 발견했고, 그 이유는 ~이다” 라는 구조로 전환하도록 팀원들을 코칭
  • 기술 선택 기준 — 화려한 기능보다 설명 가능하고 재현 가능한 구조 를 우선시

100점짜리 혼자 돌아가는 시스템보다, 팀 전체가 이해하고 설명할 수 있는 70점짜리 시스템 이 실제로 더 가치 있다는 것을 체감한 프로젝트였다.


확장 아이디어

  • 시계열 흥행 예측 — 개봉 전 데이터(예산, 장르, 감독 이력) 로 수익 예측 모델 구축
  • 실시간 트렌드 반영 — TMDB 실시간 API 를 주기적으로 호출하여 Vector DB 자동 업데이트
  • 지도 시각화 — 제작 국가별 흥행 성과를 Folium 지도로 시각화
  • 멀티 에이전트 확장 — 사용자 취향 기반 대화 이력을 누적하여 개인화 추천 품질 향상
  • 보안 인텔리전스 연계 — 영화 산업 사례를 보안 위협 인텔리전스 분석 구조로 전환하는 응용 연구