πŸŽ₯ μ˜ν™” μ‚¬μ΄νŠΈ

πŸ“Œ SSAFY 8κΈ° 1ν•™κΈ° 관톡 ν”„λ‘œμ νŠΈ

ν˜„μž¬ μƒμ˜μ€‘μΈ μ˜ν™”μ˜ μ˜ˆκ³ νŽΈλ“€μ„ 보고
μ˜ˆλ§€κΉŒμ§€ μœ λ„ν•  수 μžˆλŠ” νŽ˜μ΄μ§€λ₯Ό λ§Œλ“€μž!

Contents

핡심 κΈ°λŠ₯

  1. μ˜ν™” μΆ”μ²œ
def algorithm(request):
    movies = get_list_or_404(Movie)
    me = request.user
    prefer = defaultdict(int)
    already_like = []
    for movie in me.like_movie.all():
        already_like.append(movie.pk)
        res = json.loads(movie.genres) # λ¬Έμžμ—΄ μ œμ΄μŠ¨μ„ 제이슨으둜
        for genre in res['result']:
            prefer[genre['genre']] += 1 # λ‚΄κ°€ λ³Έ μž₯λ₯΄λ₯Ό prefer에 μΆ”κ°€

    movie_list = []
    for movie in movies:
        if movie.pk in already_like: # λ³Έμ˜ν™”λŠ” 패슀
            continue

        score = movie.vote_average * 0.3 # 평점 κ°€μ€‘μΉ˜ 0.3
        res = json.loads(movie.genres)
        for genre in res['result']:
            score += prefer[genre['genre']] * 0.4 # λ‚΄κ°€ λ³Έ μž₯λ₯΄ κ°€μ€‘μΉ˜ 0.4

        data = movie.release_date
        score += releaseDate(data) * 0.2 # μ΅œμ‹  μ˜ν™” κ°€μ€‘μΉ˜ 0.2

        movie_list.append([score, movie.pk])

    movie_list.sort(reverse=True)

    my_movie = []
    for s, i in  movie_list[:10]:
        rec_movie = Movie.objects.get(pk=i)
        my_movie.append(Movie.objects.get(pk=i))

    serializer = MovieSerializer(my_movie, many=True)

    return Response(serializer.data, status=status.HTTP_201_CREATED)

μ‚¬μš©μžκ°€ μ˜ˆλ§€ν•œ μ˜ν™”μ •λ³΄λ₯Ό λ°”νƒ•μœΌλ‘œ κ°€μ€‘μΉ˜λ₯Ό κ³„μ‚°ν•œλ‹€. κ°€μ€‘μΉ˜: μ˜ν™”ν‰μ  0.3 // λ‚΄κ°€ λ³Έ μž₯λ₯΄λ“€ 0.4 // κ°œλ΄‰μΌμž 0.2

  1. μ‚¬μš©μžκ°€ λ³Έ μ˜ν™”λ₯Ό 가지고 μž₯λ₯΄λ₯Ό μΉ΄μš΄νŠΈν•΄μ€€λ‹€.

        already_like = []
        for movie in me.like_movie.all():
            already_like.append(movie.pk)
            res = json.loads(movie.genres) # λ¬Έμžμ—΄ μ œμ΄μŠ¨μ„ 제이슨으둜
            for genre in res['result']:
                prefer[genre['genre']] += 1 # λ‚΄κ°€ λ³Έ μž₯λ₯΄λ₯Ό p
  2. DB μ €μž₯λ˜μ–΄ μžˆλŠ” λͺ¨λ“  μ˜ν™”λ₯Ό μˆœνšŒν•˜λ©΄μ„œ 이미 μ˜ˆλ§€ν•œ 적이 μžˆλŠ” μ˜ν™”λ©΄ λ„˜κΈ°κ³  μ•„λ‹ˆλΌλ©΄ κ°€μ€‘μΉ˜λ₯Ό μ μš©ν•˜κ³  (점수, μ˜ν™” pk ) 의 νŠœν”Œ ν˜•νƒœλ‘œ λ¦¬μŠ€νŠΈμ— μ €μž₯ν•œλ‹€.

    movie_list = []
    for movie in movies:
        if movie.pk in already_like: # λ³Έμ˜ν™”λŠ” 패슀
            continue
    
        score = movie.vote_average * 0.3 # 평점 κ°€μ€‘μΉ˜ 0.3
        res = json.loads(movie.genres)
        for genre in res['result']:
            score += prefer[genre['genre']] * 0.4 # λ‚΄κ°€ λ³Έ μž₯λ₯΄ κ°€μ€‘μΉ˜ 0.4
    
        data = movie.release_date
        score += releaseDate(data)
    

 3. μœ„μ—μ„œ μ €μž₯ν•΄μ„œ λ‚΄λ €μ˜¨ 리슀트λ₯Ό λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ν•˜κ³  10개λ₯Ό μŠ¬λΌμ΄μ‹±μ„ ν•œλ‹€. κ·Έ ν›„ λ¦¬μŠ€νŠΈμ— λ‹΄κΈ΄ μ˜ν™”pk κ°’μœΌλ‘œ 전체 μ˜ν™”μ •λ³΄λ₯Ό μΆ”μΆœν•˜μ—¬ λ¦¬ν„΄ν•œλ‹€

 movie_list.sort(reverse=True) 
my_movie = []
 for s, i in movie_list[:10]:
 rec_movie = Movie.objects.get(pk=i)
 my_movie.append(Movie.objects.get(pk=i)) 
serializer = MovieSerializer(my_movie, many=True) 
return Response(serializer.data)
  1. μ˜ν™” μ˜ˆλ§€ν•˜κΈ°

μ˜ν™” 예맀의 μˆœμ„œλŠ” μ˜ν™”μ„ νƒ -> λ‚ μ§œ(년월일) -> μ˜ν™”μ‹œκ°„ -> μƒμ˜κ΄€ -> μ’Œμ„μ„ νƒ μˆœμ„œλ‘œλ§Œ 이루어 질 수 μžˆλ„λ‘ ν•œλ‹€.

예맀 νŽ˜μ΄μ§€λŠ” μ˜ν™”μ˜ pk 값을 router params 둜 κ°€μ Έκ°€κΈ° λ•Œλ¬Έμ— μ˜ν™”μ„ νƒ 뢀뢄은 ν•΄κ²° λœλ‹€.

λ‚ μ§œ, μ‹œκ°„, μƒμ˜κ΄€μ€ 각각 ν•΄λ‹Ήλ˜λŠ” ν…Œκ·Έμ— v-if문을 μ΄μš©ν•˜μ—¬ μ „λ‹¨κ³„μ˜ 값이 μ„ νƒλ˜μ—ˆμ„ λ•Œλ§Œ ν™œμ„±ν™”λ˜λ„λ‘ ν•˜μ—¬ μˆœμ„œλ₯Ό 지킬 수 μžˆλ„λ‘ ν•œλ‹€.

κ·Έλ ‡κ²Œ ν•¨μœΌλ‘œμ„œ μƒμ˜κ΄€ 선택값이 μ‘΄μž¬ν•  경우(μ„ νƒλ˜μ—ˆμ„ 경우)μ—λ§Œ μ’Œμ„ 선택 μ»΄ν¬λ„ŒνŠΈκ°€ λ‚˜μ˜¬ 수 있게 ν•œλ‹€.

μ’Œμ„ 각각의 식별값은 ν–‰(i)κ³Ό μ—΄(j)λ‘œμ„œ μƒμ„±λ˜λ©° κ²°μ œκΉŒμ§€ μ§„ν–‰ν•œ 뢀뢄은 Django DB에 μ €μž₯ν–ˆλ‹€.

μœ„μ˜ λͺ¨λΈμ—μ„œ μ˜ν™” μ‹œκ°„ μ‹λ³„μžλ‘œ νŠΉμ • μ˜ν™”μ˜ μ‹œκ°„λŒ€, μƒμ˜κ΄€μ˜ μ’Œμ„μ •λ³΄λ₯Ό 뢈러봐 이미 DB에 μ €μž₯된 값이라면 클릭을 λ§‰μ•„λ†“μ•„μ„œ μ’Œμ„ 선택이 λ˜μ§€ μ•Šκ²Œ λ§Œλ“€μ—ˆλ‹€.

κ·Έλ ‡κ²Œ 정해진 μ˜ν™” μ˜ˆλ§€μ •λ³΄(μ˜ν™”, λ‚ μ§œ, μ‹œκ°„, μ’Œμ„) 을 μœ μ €μ™€ 연결지은 λͺ¨λΈ(Reservation)을 λ§Œλ“€μ–΄ 후에 μœ μ €κ°€ μ˜ˆμ•½ν•œ μ˜ν™” 정보λ₯Ό μ‰½κ²Œ 확인할 수 μžˆλ„λ‘ ν–ˆλ‹€.

  1. 뱃지 μ‹œμŠ€ν…œ

μ˜ˆλ§€ν•œ μ˜ν™”μ˜ 개수, μž‘μ„±ν•œ 리뷰의 개수, μ‚¬μš©μžλ₯Ό νŒ”λ‘œμš°ν•œ μˆ˜μ— 따라 상징적인 보상을 μ€ŒμœΌλ‘œμ„œ μ›Ήμ‚¬μ΄νŠΈ ν™œλ™μ— 집쀑할 수 있게 ν•˜κΈ°μœ„ν•΄ λ§Œλ“€μ—ˆλ‹€.

뱃지쒅λ₯˜λŠ” 총 9개둜 λ¨Όμ € 전체 뱃지λͺ©λ‘μ„ λ§Œλ“€κ³  μœ μ €κ°€ 생성(νšŒμ›κ°€μž…)λ λ•Œλ§ˆλ‹€ κ·Έ λͺ©λ‘μ„ μœ μ €μ™€ μ—°κ²° 지어 ν…Œμ΄λΈ”μ„ μƒμ„±ν–ˆλ‹€. ν•„λ“œμ—λŠ” νšλ“ μ—¬λΆ€λ₯Ό κ°€λ₯΄ν‚€λŠ” ν•„λ“œλ₯Ό ν•˜λ‚˜ λ§Œλ“€μ–΄ μœ μ €κ°€ κ·Έ 뱃지λ₯Ό νšλ“ν–ˆλŠ”μ§€ μ•ˆν–ˆλŠ”μ§€λ₯Ό DB 에 μ €μž₯ν•˜μ˜€λ‹€.

μœ μ €κ°€ μƒμ„±λœν›„ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜ 1~9 의 pk 값을 κ°€μ§€λŠ” BadgeList 의 값이 μœ μ €μ™€ μ—°κ²°λ˜μ–΄ Badge 에 μ €μž₯λœλ‹€.

μ„œλΉ„μŠ€ ν™”λ©΄

메인 νŽ˜μ΄μ§€

  • μ΅œμ‹  μ˜ν™” 예고편 보기
  • κ°€μž₯ 인기 μžˆλŠ” μ΅œμ‹  μ˜ν™” TOP 10 λͺ©λ‘ 보기
  • κ°€μž₯ 인기 μžˆλŠ” 리뷰듀 λͺ¨μ•„보기



μ˜ν™” 검색

  • κ²°κ³Όκ°€ μ—¬λŸ¬κ°œμΌ 경우 λͺ©λ‘ν˜•/κ°€λŸ¬λ¦¬ν˜• 택 1ν•˜μ—¬ μ—¬λŸ¬ 개의 κ²°κ³Ό νŽ˜μ΄μ§€
  • κ²°κ³Όκ°€ ν•œ 가지일 경우 μ˜ν™” 상세 νŽ˜μ΄μ§€λ‘œ 이동



μ˜ν™” 상세 νŽ˜μ΄μ§€

  • μ˜ν™” 상세 정보 λ‚˜νƒ€λ‚΄λŠ” νŽ˜μ΄μ§€
  • 리뷰 μ“°κΈ°



마이 νŽ˜μ΄μ§€

  • ν˜„μž¬κΉŒμ§€ μ˜ˆλ§€ν•œ μ˜ν™” 정보 보기
  • ν˜„μž¬κΉŒμ§€ 받은 뱃지 정보 보기
  • μ˜ν™” μ·¨ν–₯ 보기



μ‹œμž‘ νŽ˜μ΄μ§€

  • 둜그인 μœ μ €λ§Œ μ„œλΉ„μŠ€λ₯Ό 이용 κ°€λŠ₯
  • 메인 νŽ˜μ΄μ§€μ—μ„œ λ°”λ‘œ νšŒμ›κ°€μž… μœ λ„
  • 랜덀으둜 λ³€κ²½λ˜λŠ” λ°°κ²½ 이미지

Development

기술 μŠ€νƒ

  • Vue.js
  • Vuex
  • Django
  • SQLite3
  • Bootstrap
  • Javascript
  • Python3



ERD

fff_pjt_erd



μ»΄ν¬λ„ŒνŠΈ ꡬ쑰



νŒ€ μ†Œκ°œ

ν”„λ‘ νŠΈμ—”λ“œ
  • λ””μžμΈ 레퍼런슀 μˆ˜μ§‘
  • νŽ˜μ΄μ§€ λ ˆμ΄μ•„μ›ƒ 섀계
  • μ˜ν™” 예맀 νŽ˜μ΄μ§€ λ ˆμ΄μ•„μ›ƒ
  • λ°±μ—”λ“œ
  • 기획 및 λ°μ΄ν„°λ² μ΄μŠ€ 섀계
  • μ˜ν™” 리뷰 API 섀계
  • μ˜ν™” 데이터 DB μ €μž₯ μžλ™ν™”
  • API 섀계
  • μ˜ν™” 예맀 & 뱃지 μ‹œμŠ€ν…œ κ΅¬ν˜„
  • μ˜ν™” μΆ”μ²œ μ•Œκ³ λ¦¬μ¦˜ κ΅¬ν˜„
  • 기획 및 λ°μ΄ν„°λ² μ΄μŠ€ 섀계

  • 회고

    얻은 점

    • λ°μŠ€ν¬νƒ‘, λ…ΈνŠΈλΆ, λͺ¨λ°”일 λ“± λ°˜μ‘ν˜• UI 섀계 과정을 κ²½ν—˜ν•˜μ—¬ 이에 λŒ€ν•œ μ—­λŸ‰μ„ μŒ“μ„ 수 μžˆμ—ˆμŒ
    • ERD ꡬ상/섀계 과정을 톡해 Model κ°„μ˜ 관계λ₯Ό μ΄ν•΄ν•˜κ³  이λ₯Ό ν™œμš©ν•œ API 섀계 μ—­λŸ‰μ„ μŒ“μ„ 수 μžˆμ—ˆμŒ
    • Client - Server κ°„ μ›Ή 데이터 톡신 과정에 λŒ€ν•΄ 이해할 수 μžˆμ—ˆκ³ , 이 κ³Όμ •μ—μ„œ Javascript의 비동기 κ°œλ…μ„ ν™•μ‹€ν•˜κ²Œ μ΄ν•΄ν•˜κ³  λ‘œμ§μ„ 섀계할 수 μžˆλŠ” μ—­λŸ‰μ„ μŒ“μ„ 수 μžˆμ—ˆμŒ
    • ν”„λ‘œμ νŠΈμ˜ μ „λ°˜μ μΈ(기획/섀계/개발) 과정을 톡해 μ›Ή μ„œλΉ„μŠ€μ˜ λ™μž‘ 과정에 λŒ€ν•΄ 이해할 수 μžˆμ—ˆμŒ

    κ°œμ„ ν•  점

    • Git Issue, Branch μ „λž΅ 등을 ν™œμš©ν•˜μ—¬ ν˜‘μ—…μ˜ μœ μš©μ„± 높이기
    • ERD 섀계 투자 μ‹œκ°„ 높이기
    • MVP μœ„μ£Όμ˜ 개발 & μœ μ§€λ³΄μˆ˜ν•˜λ©° λΆ€κ°€ κΈ°λŠ₯ 개발
    • AWS EC2 ν™œμš©ν•œ μ‹€μ œ 배포

    Get Started

    Client

    $ git clone https://github.com/SuhyungK/final_project.git
    $ cd final_project
    $ cd final-pjt-front
    $ npm install 
    $ npm run serve
    

    Server

    • Mac OS
    $ git clone https://github.com/SuhyungK/final_project.git
    $ cd final_project
    $ cd final-pjt-back
    $ python3 -m venv venv
    $ source venv/bin/activate
    $ python3 -m pip install -r requirements.txt
    
    $ python3 manaage.py makemigrations
    $ python3 manage.py migrate
    
    $ python3 manage.py runserver
    
    • Windows 10
    $ git clone https://github.com/SuhyungK/final_project.git
    $ cd final_project
    $ cd final-pjt-back
    $ python -m venv venv
    $ source venv/Scripts/activate
    $ pip install -r requirements.txt
    
    $ python manaage.py makemigrations
    $ python manage.py migrate
    
    $ python manage.py runserver