영화 리뷰 감성 분석 서비스
감성 분석 모델을 FastAPI 백엔드와 Streamlit 프런트로 서비스화
Repository개인 저장소
malit9999/llm-sentiment-movie-review-app-mission-18(새 탭에서 열림)Contents · 목차
무엇을 하는 미션인가
영화와 리뷰를 CRUD로 관리하면서, 리뷰가 등록될 때 감성을 분석해 함께 저장하는 서비스입니다. FastAPI 백엔드와 Streamlit 프런트를 나눠 만들었습니다.
입력은 리뷰 텍스트(+선택적 별점), 출력은 감성 라벨과 점수, 그리고 영화별 평균 점수입니다.
API 구성
/movies 영화 등록·목록
/movies/{id} 단건 조회·수정·삭제
/movies/{id}/reviews 해당 영화 리뷰
/movies/{id}/rating 평균 평점
/reviews, /reviews/{id} 리뷰 등록·조회·수정·삭제
DB는 SQLAlchemy로 다루고, 영화-리뷰는 관계로 묶여 joinedload로 함께 조회합니다.
감성 분석을 3단으로 쌓은 부분
이 미션에서 가장 손이 많이 간 곳입니다. 모델 하나로 끝내지 않고 모델 → 도메인 규칙 → 별점 보정 순으로 겹쳤습니다.
# backend/sentiment.py — 모델이 없거나 실패해도 결과는 돌려준다 (발췌)
def analyze_sentiment(text, user_rating=None):
sentiment_pipeline = get_sentiment_pipeline()
if sentiment_pipeline is None: # 모델 미로딩
rule_result = analyze_sentiment_rule_based(text)
return apply_user_rating_rule(rule_result, user_rating)
try:
result = sentiment_pipeline(text[:512])[0]
model_result = normalize_model_result(result)
domain_result = apply_review_domain_rule(text, model_result)
return apply_user_rating_rule(domain_result, user_rating)
except Exception as error: # 추론 실패
print(f"[WARN] Hugging Face 추론 실패: {error}")
rule_result = analyze_sentiment_rule_based(text)
return apply_user_rating_rule(rule_result, user_rating)
모델은 sangrimlee/bert-base-multilingual-cased-nsmc를 transformers.pipeline으로 올리고
@lru_cache(maxsize=1)로 한 번만 로드합니다. transformers import 자체를 try로 감싸서,
모델을 못 올리는 환경에서도 서버가 뜨고 규칙 기반 결과를 돌려줍니다.
도메인 규칙은 리뷰 특유의 표현을 다룹니다 — 긍정 단어가 2개 이상이고 부정이 0개면 점수를
0.85 이상으로 올리고, 반대면 0.2 이하로 내립니다. 신뢰도가 낮으면(0.55 미만) 중립으로
떨어뜨립니다.
구현에서 드러나는 판단
모델 결과를 최종값으로 두지 않았습니다. "또 보고 싶다", "긴말 안 하겠다" 같은 리뷰 관용 표현이 범용 감성 모델에서 잘 잡히지 않아, 단어 목록과 별점을 후처리로 얹는 쪽을 택했습니다. 규칙 목록이 코드에 그대로 노출돼 있어 무엇을 보정하는지 확인할 수 있습니다.
한계
- 정확도·F1 같은 평가 수치가 저장소에 없습니다. 규칙 보정이 실제로 나아졌는지는 측정되지 않았습니다
- 긍정·부정 단어 목록이 사람이 쓴 고정 목록이라 도메인이 바뀌면 다시 만들어야 합니다
- 리뷰는 앞 512자만 모델에 넣습니다