Minseong Code Lab
← Projects
Bootcamp MissionAI Service / AX

영화 리뷰 감성 분석 서비스

감성 분석 모델을 FastAPI 백엔드와 Streamlit 프런트로 서비스화

게시 2026-07-10
PythonFastAPIStreamlitSQLAlchemyTransformersPyTorchSQLite
Contents · 목차
  1. 무엇을 하는 미션인가
  2. API 구성
  3. 감성 분석을 3단으로 쌓은 부분
  4. 구현에서 드러나는 판단
  5. 한계

무엇을 하는 미션인가

영화와 리뷰를 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자만 모델에 넣습니다