Giter VIP home page Giter VIP logo

2021_pjt_sinbak-movie's Introduction

Sinbak Movie

Generic badgeGeneric badge

TMDB API์™€ YOUTUBE API๋ฅผ ํ™œ์šฉํ•œ ์‹ ๋ฐ•ํ•œ ์˜ํ™” ์ •๋ณด ์ œ๊ณต ๋ฐ ์ปค๋ฎค๋‹ˆํ‹ฐ ์‚ฌ์ดํŠธ์ž…๋‹ˆ๋‹ค.


Goal

  • Django์™€ Vue.js๋กœ ํ’€์Šคํƒ ๊ฐœ๋ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์™ธ๋ถ€ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • CORS์™€ simple jwt๋กœ ์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ํ†ต์‹ ๊ณผ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • SPA์˜ ํ•œ๊ณ„์ ์„ ๋ณด์™„ํ•˜๊ณ ์ž, vue-router ๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž๋กœ ํ•˜์—ฌ๊ธˆ url์ด ์ด๋™๋œ ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•˜๋ฉฐ, ๋’ค๋กœ ๊ฐ€๊ธฐ๋ฅผ ์ง€์›ํ•œ๋‹ค.
  • RESTfulํ•œ url์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค์–‘ํ•œ method๋กœ axios ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

Preview

ezgif.com-gif-maker


Architecture

Django Vue.js
django rest framework
image-kit
simple jwt
django cors headers
requests
vuex
vue-router
axios
vue-bootstrap
vue-fontawesome

Roles

Back๊ณผ front๋ฅผ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š์•˜๊ณ , ์ดˆ๋ฐ˜ ์„ค๊ณ„๋ฅผ ๊ฐ™์ด ์ง„ํ–‰ํ–ˆ๋‹ค.

๋ฐ•์ง€์ˆ˜ ์‹ ๋™์œค
์˜ํ™” ๋ฉ”์ธ, ๋””ํ…Œ์ผ ํ”„๋ก ํŠธ ๋””์ž์ธ
์˜ํ™” ์ถ”์ฒœ
์˜ํ™” ๊ฒ€์ƒ‰
์˜ํ™” ์ปค๋ฎค๋‹ˆํ‹ฐ ๋””์ž์ธ
backend์—์„œ model ์ˆ˜์ •
Modal

Implementation rate

์ถ”๊ฐ€๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋ คํ–ˆ์œผ๋‚˜,

  • ์˜ˆ์ƒ ๋ณ„์ 
  • ๋‚ด ํด๋” ๊ธฐ๋Šฅ
  • ์„ฑ๋ณ„ ๋ฐ ์—ฐ๋ น๋Œ€๋ณ„ ๋ณ„์  ํ•„ํ„ฐ๋ง

์งง์€ ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„์œผ๋กœ ์ธํ•ด, ์ฃผ์š”๊ธฐ๋Šฅ์— ์ถฉ์‹คํ•˜๊ณ ์ž ํ–ˆ๋‹ค.


ERD

erd

User์™€ movie ๋‘ ๊ฐœ์˜ ๋ชจ๋ธ์„ ์ค‘์‹ฌ์œผ๋กœ Comment, RatedMovie, LikedMovie ๋“ฑ์„ 1:N ๋˜๋Š” M:N์œผ๋กœ ๋ชจ๋ธ๋งํ–ˆ๋‹ค.


์ฃผ์š”๊ธฐ๋Šฅ

1. ๋ฉ”์ธํŽ˜์ด์ง€

๋ฉ”์ธ

๐Ÿ› ๊ธฐ๋Šฅ

  • ๊ฒ€์ƒ‰๊ธฐ๋Šฅ
  • ๊ฐ€์žฅ ์ธ๊ธฐ ๋งŽ์€ ์˜ํ™”์˜ ํŠธ๋ ˆ์ผ๋Ÿฌ
  • ์ธ๊ธฐ์˜ํ™”, ํ˜„์žฌ ์ƒ์˜์ž‘, ์ด๋ฒˆ ์ฃผ ์ธ๊ธฐ์ž‘ ์ •๋ณด ์ œ๊ณต
  • ํ™”๋ฉด์— ์กด์žฌํ•˜๋Š” ํฌ์Šคํ„ฐ๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋ชจ๋‘ ๋””ํ…Œ์ผ ํŽ˜์ด์ง€๋กœ ์ด๋™

๐Ÿ– ๋””์ž์ธ

  • Navbar ์•„๋ž˜์— tmdb์˜ backdrop_path๋ฅผ ํ†ตํ•œ ๊ทธ๋ผ๋ฐ์ด์…˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ

  • ๋งˆ์šฐ์Šค hover์— ๋ฐ˜์‘ํ˜•์œผ๋กœ ์ œ์ž‘.

  • Hooper swiper๋ฅผ ์ด์šฉํ•ด ๋งˆ์šฐ์Šค ํด๋ฆญ ๋˜๋Š” ๋“œ๋ž˜๊ทธ๋กœ ๋‹ค์–‘ํ•œ ์˜ํ™” ์ •๋ณด๋ฅผ ํ•œ๋ฒˆ์— ์ œ๊ณต.


2. ๋””ํ…Œ์ผ ํŽ˜์ด์ง€

๋””ํ…Œ์ผ

๐Ÿ› ๊ธฐ๋Šฅ

  • starating๋ฅผ ํ†ตํ•ด ํด๋ฆญ ๋˜๋Š” ๋“œ๋ž˜๊ทธ๋กœ ๋ณ„์  ๋งค๊ธฐ๊ธฐ.

  • ํ˜„์žฌ ์šฐ๋ฆฌ ์‚ฌ์ดํŠธ์— ๊ฐ€์ž…ํ•œ ์œ ์ €๊ฐ€ ๋งค๊ธด ํ‰์ ์˜ ํ‰๊ท  ๋ฐ ์œ ์ €๊ฐ€ ๋ˆ„๋ฅธ ์ข‹์•„์š” ์ˆ˜ ์ œ๊ณต

  • TMDB ์‚ฌ์ดํŠธ์˜ ์ •๋ณด ์ œ๊ณต (๋ฐฐ์šฐ ์ •๋ณด, TMDB ํ‰์  ๋ฐ ํˆฌํ‘œ์ˆ˜, overview ๋“ฑ)

  • ํ•˜๋‹จ์— ํ˜„์žฌ ๋””ํ…Œ์ผ ํŽ˜์ด์ง€ ์ƒ์˜ ์˜ํ™”์™€ ๊ด€๋ จ๋œ ์œ ์‚ฌ ์˜ํ™” ์ œ๊ณต

  • comment ํด๋ฆญ ์‹œ, ๋Œ“๊ธ€ ํŽ˜์ด์ง€๋กœ ์ด๋™ ๊ฐ€๋Šฅ

๐Ÿ– ๋””์ž์ธ

  • starating์„ ์‚ฌ์šฉํ•˜์—ฌ, ๋ณ„์  ์ฃผ๊ธฐ ํŽธ์˜์„ฑ์„ ๋†’์ž„.
  • ๊ทธ๋ผ๋ฐ์ด์…˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ
  • bootstrap icon์„ ํ†ตํ•ด ์•Œ์•„๋ณด๊ธฐ ์‰ฌ์šด ์•„์ด์ฝ˜ ์‚ฝ์ž….

3. ๋Œ“๊ธ€ ํŽ˜์ด์ง€

๋””ํ…Œ์ผ ํŽ˜์ด์ง€์—์„œ comment ํด๋ฆญ ์‹œ, ๋ฒ ์ŠคํŠธ ๋Œ“๊ธ€ ๋ชจ์Œ modal ๋“ฑ์žฅ

1) ๋ฒ ์ŠคํŠธ ๋Œ“๊ธ€

๋ฒ ๋Œ“

๐Ÿ› ๊ธฐ๋Šฅ

  • ๋””ํ…Œ์ผ ํŽ˜์ด์ง€์˜ ์˜ํ™” ๋Œ“๊ธ€ ์ค‘, ๊ฐ€์žฅ ์ข‹์•„์š”๊ฐ€ ๋งŽ์€ ์ˆœ์„œ๋กœ ๋ณด์—ฌ์คŒ.
  • ๊ธด ๋Œ“๊ธ€์˜ ๊ฒฝ์šฐ์— ์ „๋ถ€ ๋ณด์—ฌ์ฃผ์ง€ ์•Š์Œ.
  • more comments ๋ฒ„ํŠผ์„ ํ†ตํ•ด ๋Œ“๊ธ€ ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ ๊ฐ€๋Šฅ
  • ์ข‹์•„์š” ๋ˆ„๋ฅด๊ธฐ ๊ฐ€๋Šฅ

๐Ÿ– ๋””์ž์ธ

  • vue-js-modal์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ๋Œ“๊ธ€ ํŒŒ์•…๊ฐ€๋Šฅ
  • ์ž‘์„ฑ์ž ์˜†์— ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ฝ์ž…
  • boostrap icon ์‚ฌ์šฉ

2) ๋Œ“๊ธ€ ์ƒ์„ธ ํŽ˜์ด์ง€

๋Œ“๊ธ€2

๋Œ“๊ธ€3

๐Ÿ› ๊ธฐ๋Šฅ

  • ๋Œ“๊ธ€ ์ž‘์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ, ๋Œ“๊ธ€ ์ž‘์„ฑ modal์ด ๋ฐœ์ƒํ•˜๊ณ  ์ž‘์„ฑ๊ฐ€๋Šฅ.

  • ๊ฐ ๋Œ“๊ธ€์— ๋Œ€ํ•œ ๋Œ€๋Œ“๊ธ€ ์ž‘์„ฑ ๊ฐ€๋Šฅ

  • ์ž์‹ ์ด ๋‹จ ๋Œ“๊ธ€์— ํ•œํ•ด ์‚ญ์ œ ๋ฐ ์ˆ˜์ • ๊ฐ€๋Šฅ

  • ๊ฐ ์œ ์ €๊ฐ€ ๋งค๊ธด ๋ณ„์ ์ด ์กด์žฌํ•  ์‹œ, ์ขŒ์ธก ์ƒ๋‹จ์— ๋Œ“๊ธ€ ์“ด ์œ ์ €์˜ ๋ณ„์  ์ œ๊ณต.


4. ์ถ”์ฒœ ํŽ˜์ด์ง€

์ƒ๋‹จ navbar์—์„œ Recommendation ํด๋ฆญ ์‹œ, ์ถ”์ฒœ ํŽ˜์ด์ง€๋กœ ์ด๋™

์ถ”์ฒœ1

์ถ”์ฒœ2

๐Ÿ› ๊ธฐ๋Šฅ

  • ๋‚ด๊ฐ€ ์ตœ๊ทผ์— ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅธ ์ˆœ์„œ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด ์ œ๊ณต.
  • ๋งˆ์Œ์— ๋“œ๋Š” ์˜ํ™” ํด๋ฆญ ์‹œ, TMDB์˜ recommendation์„ ํ†ตํ•ด ์˜ํ™” ์ถ”์ฒœ.
  • ์˜ํ™” ํด๋ฆญ ์‹œ, ๋””ํ…Œ์ผ ํŽ˜์ด์ง€๋กœ ์ด๋™.

๐Ÿ– ๋””์ž์ธ

  • ์˜ํ™” ํฌ์Šคํ„ฐ hover ์‹œ, ํŒ์—… ๊ธฐ๋Šฅ.

5. ๊ฒ€์ƒ‰

๊ฒ€์ƒ‰

๐Ÿ› ๊ธฐ๋Šฅ

  • ์ƒ๋‹จ navbar์˜ search ์ฐฝ์— ๊ฒ€์ƒ‰ ํ›„, enter ๋˜๋Š” ๋‹๋ณด๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅ
  • ๋งจ์œ„์— ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณต
  • ํ•˜๋‹จ similar movie์—์„œ๋Š” ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ๊ด€๋ จ๋œ ์˜ํ™”๋ฅผ ์ œ๊ณต
  • ํฌ์Šคํ„ฐ ํด๋ฆญ ์‹œ, ๋””ํ…Œ์ผ๋กœ ์ด๋™.

6. ํ”„๋กœํ•„

ํ”„๋กœํ•„

ํ”„๋กœํ•„2

ํ”„๋กœํ•„3

๐Ÿ› ๊ธฐ๋Šฅ

  • ์ƒ๋‹จ ์šฐ์ธก, profile ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ด๋™๊ฐ€๋Šฅ
  • ๋‚ด ํ”„๋กœํ•„์—์„œ๋Š” ์„ค์ •๋ฒ„ํŠผ์„, ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ํ”„๋กœํ•„์—์„œ๋Š” ํŒ”๋กœ์šฐ ๋ฒ„ํŠผ์„ ์ œ๊ณต
  • ์•„๋ž˜์— ๋‚ด๊ฐ€ ์ข‹์•„์š”์™€ ํ‰๊ฐ€ํ•œ ์˜ํ™” ์ •๋ณด๋ฅผ ์ œ๊ณต ํด๋ฆญ์‹œ ๋””ํ…Œ์ผ ์ด๋™.
  • ์„ค์ • ํด๋ฆญ ์‹œ, ์ •๋ณด ์ˆ˜์ • ๋˜๋Š” ํƒˆํ‡ด ์„ ํƒ.
  • ํƒˆํ‡ด ํด๋ฆญ ์‹œ, ๊ท€์—ฌ์šด ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ์™€ ํ•จ๊ป˜ ํƒˆํ‡ด์—ฌ๋ถ€ ์„ ํƒ

7. ํšŒ์›์ •๋ณด ์ˆ˜์ •

ํšŒ์›์ •๋ณด์ˆ˜์ •2

ํšŒ์›์ •๋ณด์ˆ˜์ •2

ํšŒ์›์ •๋ณด์ˆ˜์ •3

๐Ÿ› ๊ธฐ๋Šฅ

  • ํšŒ์›์ •๋ณด ์กฐํšŒ ๋ฐ ์ˆ˜์ • ๊ฐ€๋Šฅ
  • ์ˆ˜์ • ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ˆ˜์ • ๋ชจ๋“œ ์ง„์ž…
  • ์ด๋ฏธ์ง€ ํ”„๋กœํ•„๋„ ์ˆ˜์ •๊ฐ€๋Šฅํ•˜๋ฉฐ, ์—…๋กœ๋“œ๋ฅผ ํ•˜์ง€ ์•Š์„ ์‹œ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€ ์ œ๊ณต.
  • ๋˜ํ•œ ์—ฌ๊ธฐ ํด๋ฆญ ์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ •๋ณด ์˜ค๋ฅ˜ ์‹œ ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ.

8. admin

ํšŒ์›์ •๋ณด์ˆ˜์ •3

์–ด๋“œ๋ฏผ2

๐Ÿ› ๊ธฐ๋Šฅ

  • ๊ด€๋ฆฌ์ž ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ ์‹œ ์šฐ์ธก ์ƒ๋‹จ์— admin ํƒœ๊ทธ ๋…ธ์ถœ.
  • ํด๋ฆญ ์‹œ admin ํŽ˜์ด์ง€๋กœ ์ด๋™.

client

vuex

  • vuex ์‚ฌ์šฉ ์‹œ ๋น„๋™๊ธฐ์  ์ฒ˜๋ฆฌ์—์„œ ์–ด๋ ค์› ์œผ๋ฉฐ, ์ง€์—ญ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ์—๋Š” component ๋‚ด์—์„œ method์™€ state๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒŒ ํ›จ์”ฌ ์ข‹์•˜๋‹ค.
  • state๋ฅผ ๋‹ค์‹œ computed์— ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•  ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ์˜ ๋™์ž‘์‹œ๊ธฐ๊ฐ€ ๋‹ฌ๋ผ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.
  • v-if ๋“ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•  ๋•Œ์—๋งŒ ๋™์ž‘ํ•˜๋„๋ก ํ•˜์—ฌ ์—๋Ÿฌ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.
  • vuex์—์„œ๋„ ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด์„œ ๋ชจ๋“ˆ๋กœ ๋‚˜๋ˆ„์–ด ๊ด€๋ฆฌ์šฉ์ด์„ฑ์„ ์ฆ๊ฐ€์‹œ์ผฐ๋‹ค.

axios

  • axios์˜ default ๊ฐ’(intercept, baseurl)์„ ๋ณ€๊ฒฝํ–ˆ์„ ๋•Œ, ๋ชจ๋“  axios์—์„œ ์ ์šฉ์ด ๋˜์–ด์„œ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์ง€ ๋ชปํ–ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ์ดํ›„, axios ์š”์ฒญ๋งˆ๋‹ค ๋”ฐ๋กœ header ๋˜๋Š” URL๋ฅผ ์ง€์ •ํ•˜์—ฌ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.
  • get์˜ ๊ฒฝ์šฐ 2๋ฒˆ์งธ ์ธ์ž๋กœ header๋ฅผ ๋ฐ›๊ณ , post, put ๋“ฑ์€ 3๋ฒˆ์งธ ์ธ์ž๋กœ header๋ฅผ ๋ฐ›์•˜๋Š”๋ฐ ์ „๋ถ€ ๋‘๋ฒˆ์งธ์— ๋„ฃ์–ด์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.
  • ์ฆ‰ ํ—ค๋”๊ฐ€ ์•„๋‹Œ payload๋กœ ๋ณด๋ƒˆ๊ณ , ์ดํ›„ Network ํƒญ์—์„œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ˆ˜์ •ํ•˜์˜€๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด์šฉํ•  ๋•Œ README๊ฐ€ ๋ถ€์‹คํ•˜์—ฌ ์ฒ˜์Œ์— ์žฌ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ค์› ๋‹ค.
  • ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ , ์ง์ ‘ node module ์•ˆ์— ์žˆ๋Š” ์ฝ”๋“œ๋„ ์ˆ˜์ •ํ•˜๋ฉฐ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋Œ์—ˆ๋‹ค.
  • vue-js-modal์€ ์›ฌ๋งŒํ•˜๋ฉด ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž!

transition

  • ๋„ทํ”Œ๋ฆญ์Šค์˜ ๋ชจ๋‹ฌ๊ณผ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ, transition์ด๋ผ๊ณ  ํ•˜๋Š” css ๊ตฌ๋ฌธ ์‚ฌ์šฉํ–ˆ๋‹ค.
  • ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์š”์†Œ๊ฐ€ ์„ ํƒ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค.

UX

  • ์œ ์ €์—๊ฒŒ ์„ ํƒ๊ฐ€๋Šฅํ•จ์„ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด, ์„ ํƒ ๊ฐ€๋Šฅํ•œ ์š”์†Œ์— ๋Œ€ํ•ด cursor๋ฅผ pointer๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์—ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋‚˜ API๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ๋”ฉ ํŽ˜์ด์ง€๋ฅผ ๋„ฃ์–ด ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ ์‹œ๊ฐ„์„ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•ด์ฃผ์—ˆ๋‹ค.
  • modal๋ฅผ ํ†ตํ•ด ์ด๋™ํ•˜์ง€ ์•Š๊ณ ๋„ ์ˆ˜์ •๊ณผ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜์˜€๋‹ค.
  • starating์œผ๋กœ ์†์‰ฝ๊ฒŒ ๋ณ„์ ์„ ์ค„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.
  • router ์‚ฌ์šฉํ•ด์„œ URL๋งŒ ๋ณ€๊ฒฝํ•จ์œผ๋กœ์จ ์‚ฌ์šฉ์ž์—๊ฒŒ ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ–ˆ์Œ์„ ์ธ์‹์‹œํ‚ค๊ณ  ํžˆ์Šคํ† ๋ฆฌ ๋ชจ๋“œ๋ฅผ ํ†ตํ•ด ๋’ค๋กœ๊ฐ€๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ–ˆ๋‹ค.

router

  • router ์ „์—ญ ๊ฐ€๋“œ๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธ ์‹œ์—๋งŒ ์„œ๋น„์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œํ•œํ•˜์˜€๋‹ค.
  • ๋น„๋กœ๊ทธ์ธ ์‹œ์—๋Š” ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋งŒ ๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.
  • ๋™์  ๋ผ์šฐํŒ…(query, params)์„ ์ด์šฉํ•ด URL ์ž์ฒด์— ์ •๋ณด๋ฅผ ์‹ค์—ˆ๋‹ค.

localstorage

  • ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋ฌธ์ž์—ด๋กœ ์ €์žฅ๋œ๋‹ค.
  • ๋งŒ์•ฝ ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•˜๋”๋ผ๋„ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•  ์‹œ, ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋กœ์ปฌ์— ์ €์žฅํ•˜์ž.

ํŒŒ์ผ ๊ด€๋ฆฌ

  • ์• ์ดˆ์— component๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ์žก์•„์„œ ์ƒ์„ฑํ•˜๋„๋ก ํ•˜์ž.
  • ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด ๊ด€๋ฆฌ๊ฐ€ ํž˜๋“ค๋‹ค.

Component

  • ๋งŒ์•ฝ ๋””ํ…Œ์ผ ํŽ˜์ด์ง€์—์„œ ๋””ํ…Œ์ผ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐˆ ๊ฒฝ์šฐ์—๋Š”created์™€ ๊ฐ™์€ life cycle hook์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ด๋Ÿด ๋•Œ์—๋Š”, ๋™์  ๋ผ์šฐํŒ…์„ ์ด์šฉํ•˜์—ฌ watch๋กœ $route ๋ฅผ ๊ฐ์‹œํ•˜์—ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ ์šฉํ•œ๋‹ค.
  • style์˜ ๊ฒฝ์šฐ์—๋„ computed๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

server

  • ๋ชจ๋ธ ์„ค๊ณ„๋ฅผ ์ž˜ํ•˜์ž!!! ๋‚˜์ค‘์— ์ˆ˜์ •ํ•˜๋ ค๋ฉด front-end๋„ ๋ชจ๋‘ ์ˆ˜์ •ํ•ด์•ผํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

Model

from django.db import models
from django.conf import settings
from django.db.models.fields import CharField

User = settings.AUTH_USER_MODEL

class Movie(models.Model):
    tmdb_id = models.CharField(max_length=50, unique=True)
    title = models.CharField(max_length=100, null=True)
    poster_path = models.CharField(max_length=200, null=True)
    backdrop_path = models.CharField(max_length=200, null=True)
    like_users = models.ManyToManyField(User, related_name='like_movies')


class Comment(models.Model):
    like_users = models.ManyToManyField(User, related_name='like_comments')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name='comments')
    content = models.CharField(max_length=1000)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class ReComment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    comment = models.ForeignKey(Comment, on_delete=models.CASCADE, related_name='recomments')
    content = models.CharField(max_length=1000)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class RatedMovie(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='rated_movies')
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name='rates')
    rate = models.IntegerField()

URL

# movie_api/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    # TokenRefreshView,
)

urlpatterns = [
    path('admin/', admin.site.urls), # GET admin ํŽ˜์ด์ง€
    path('api/v1/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), # POST ๋กœ๊ทธ์ธ ์‹œ ํ† ํฐ ๋ฐœํ–‰.
    path('api/v1/accounts/', include('accounts.urls')), # accounts
    path('api/v1/movies/', include('movies.urls')), # movies
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # media ํŒŒ์ผ ์ €์žฅ์„ ์œ„ํ•œ URL ๋ฐ root
# movies/urls.py
from django.urls import path
from . import views
urlpatterns = [
    path('<int:tmdb_id>/comment/', views.comment_list_create), # GET POST comment ๊ด€๋ จ ์ •๋ณด ์ €์žฅ ๋ฐ ์กฐํšŒ
    path('<int:tmdb_id>/comment/<int:comment_id>/', views.comment_update_delete), # PUT DELETE ๋Œ“๊ธ€ ์ˆ˜์ • ๋ฐ ์‚ญ์ œ.
    path('<int:tmdb_id>/like/', views.movie_like,), # POST ์˜ํ™” ์ข‹์•„์š” ์ˆ˜์ • ๋ฐ ์ƒ์„ฑ
    path('comments/<int:comment_id>/like/', views.comment_like,), # GET POST ๋Œ“๊ธ€ ์ข‹์•„์š” ๋ฐ ์ข‹์•„์š” ์กฐํšŒ
    path('<int:tmdb_id>/rate/', views.movie_rate), # GET POST ์˜ํ™” ํ‰์  ์ˆ˜์ • ๋ฐ ์ƒ์„ฑ
    path('<int:comment_id>/recomment/', views.recomment_list_create), # GET POST ๋Œ€๋Œ“๊ธ€ ์ƒ์„ฑ ๋ฐ ์กฐํšŒ
    path('<int:comment_id>/recomment/<int:recomment_id>/', views.recomment_delete), # DELETE ๋Œ€๋Œ“๊ธ€ ์‚ญ์ œ
    path('<int:tmdb_id>/like/rate/', views.get_like_rate), # GET ์˜ํ™” ์ข‹์•„์š” ๋ฐ ๋ณ„์  ์กฐํšŒ
    path('<int:tmdb_id>/comments/best/', views.get_best_comment), # GET ๋ฒ ์ŠคํŠธ ๋Œ“๊ธ€ ์กฐํšŒ
    path('<int:tmdb_id>/', views.set_initial_movie_info), # POST ์˜ํ™” ๋””ํ…Œ์ผ ํŽ˜์ด์ง€ ์ตœ์ดˆ ์ง„์ž… ์‹œ์—๋งŒ ์ €์žฅ
    path('<int:tmdb_id>/backdrop/', views.get_backdrop), # GET ์˜ํ™” ๋’ท๋ฐฐ๊ฒฝ ๊ฐ€์ ธ์˜ค๊ธฐ.
]
# accounts/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('signup/', views.signup), # POST ํšŒ์›๊ฐ€์ž…
    path('users/', views.user_update_delete), # GET PUT DELETE ์œ ์ € ํšŒ์›์ •๋ณด ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ๊ทธ๋ฆฌ๊ณ  ์กฐํšŒ
    path('password-change/', views.user_password_change), # PUT ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ
    path('<username>/follow/', views.follow), # GET POST ์œ ์ € ํŒ”๋กœ์šฐ ์ •๋ณด ์กฐํšŒ ๋ฐ ์ˆ˜์ •
    path('issuperuser/', views.is_superuser), # GET ์Šˆํผ ์œ ์ €์ธ์ง€ ํŒ๋ณ„.
    path('<username>/user/movies/', views.user_movie_info), # GET ์œ ์ €์˜ rated movie & liked movie ์ •๋ณด ์กฐํšŒ
]

serializers

  • ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์“ด serializer method
  • get_<field_name>์œผ๋กœ ์ž‘์„ฑ ์‹œ, ์ƒˆ๋กœ์šด ํ•„๋“œ๋ฅผ serializer ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
class CommentListSerializer(serializers.ModelSerializer):
    username = serializers.SerializerMethodField()
    
    # ์ด๊ฑด read_only
    # get_<field_name>์œผ๋กœ ๋ฉ”์„œ๋“œ ์ƒ์„ฑ
    # self => instance, obj => Model
    def get_username(self, obj):
        return obj.user.username
    
    ...
    	fields=(...'username',) # ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€.

Pin.

์ง€์ˆ˜

  • ๋™์œค๋‹˜๊ณผ ํ•จ๊ป˜ ํ•˜๋ฉด์„œ ์ฆ๊ฑฐ์› ๋‹ค.
  • ์›๋ž˜๋Š” ๋ฐฑ์—”๋“œ๋งŒ ์ƒ๊ฐํ–ˆ์—ˆ๋Š”๋ฐ, ํ”„๋ก ํŠธ๋„ ํ•˜๋‹ค๋ณด๋‹ˆ ํฅ๋ฏธ๊ฐ€ ์ƒ๊ฒจ์„œ ์ด ๋ถ„์•ผ๋„ ๊ณ ๋ คํ•ด๋ด์•ผ๊ฒ ๋‹ค.

๋™์œค

  • ์ง€์ˆ˜๋‹˜๊ณผ ํ•จ๊ป˜ ํ•˜๋ฉด์„œ, css์™€ ๋””์ž์ธ์— ๋Œ€ํ•ด ๋งŽ์ด ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
  • ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„์ด ์ •๋ง ์งง๊ณ  ํž˜๋“ค์—ˆ์ง€๋งŒ, ๊ฐ™์ด ํ•˜๋‹ค๋ณด๋‹ˆ ์žฌ๋ฐŒ๊ฒŒ ์ž˜ ๋๋‚ผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
  • ์•ž์œผ๋กœ์˜ ์„ธ๋ฒˆ์˜ ํ”„๋กœ์ ํŠธ๋„ ์ž˜ ๋๋‚ด๊ณ  ์‹ถ๋‹ค.

2021_pjt_sinbak-movie's People

Contributors

parkjisu6239 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.