From bce4f7c79415b3af9d0a0230a65607f53a205ccf Mon Sep 17 00:00:00 2001 From: Soyeon Choe Date: Thu, 3 Oct 2024 21:47:58 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=98=81=ED=99=94=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B0=8F=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=20=EB=AA=A8=EB=8B=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/apis/constants.js | 20 ++++ ssr/apis/movies.js | 13 +++ ssr/server/index.js | 16 ++-- ssr/server/routes/index.js | 22 ++--- ssr/utils/renderModal.js | 56 +++++++++++ ssr/utils/renderMovieItemPage.js | 40 ++++++++ ssr/utils/renderMovieItems.js | 21 +++++ ssr/views/index.html | 153 ++++++++++++++++--------------- 8 files changed, 243 insertions(+), 98 deletions(-) create mode 100644 ssr/apis/constants.js create mode 100644 ssr/apis/movies.js create mode 100644 ssr/utils/renderModal.js create mode 100644 ssr/utils/renderMovieItemPage.js create mode 100644 ssr/utils/renderMovieItems.js diff --git a/ssr/apis/constants.js b/ssr/apis/constants.js new file mode 100644 index 0000000..8fdcbb6 --- /dev/null +++ b/ssr/apis/constants.js @@ -0,0 +1,20 @@ +export const BASE_URL = 'https://api.themoviedb.org/3/movie'; + +export const TMDB_THUMBNAIL_URL = 'https://media.themoviedb.org/t/p/w440_and_h660_face/'; +export const TMDB_ORIGINAL_URL = 'https://image.tmdb.org/t/p/original/'; +export const TMDB_BANNER_URL = 'https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/'; +export const TMDB_MOVIE_LISTS = { + POPULAR: BASE_URL + '/popular?language=ko-KR&page=1', + NOW_PLAYING: BASE_URL + '/now_playing?language=ko-KR&page=1', + TOP_RATED: BASE_URL + '/top_rated?language=ko-KR&page=1', + UPCOMING: BASE_URL + '/upcoming?language=ko-KR&page=1', +}; +export const TMDB_MOVIE_DETAIL_URL = 'https://api.themoviedb.org/3/movie/'; + +export const FETCH_OPTIONS = { + method: 'GET', + headers: { + accept: 'application/json', + Authorization: 'Bearer ' + process.env.TMDB_TOKEN, + }, +}; diff --git a/ssr/apis/movies.js b/ssr/apis/movies.js new file mode 100644 index 0000000..adf07b6 --- /dev/null +++ b/ssr/apis/movies.js @@ -0,0 +1,13 @@ +import { TMDB_MOVIE_LISTS, FETCH_OPTIONS, TMDB_MOVIE_DETAIL_URL } from './constants.js'; + +export const fetchMovies = async (category) => { + const response = await fetch(TMDB_MOVIE_LISTS[category], FETCH_OPTIONS); + + return await response.json(); +}; + +export const fetchMovieDetail = async (movieId) => { + const response = await fetch(`${TMDB_MOVIE_DETAIL_URL}${movieId}?language=ko-kr`, FETCH_OPTIONS); + + return await response.json(); +}; diff --git a/ssr/server/index.js b/ssr/server/index.js index 09efd9a..1f7760f 100644 --- a/ssr/server/index.js +++ b/ssr/server/index.js @@ -1,9 +1,9 @@ -import "./config.js"; -import express from "express"; -import path from "path"; -import { fileURLToPath } from "url"; +import './config.js'; +import express from 'express'; +import path from 'path'; +import { fileURLToPath } from 'url'; -import movieRouter from "./routes/index.js"; +import movieRouter from './routes/index.js'; // import membersRouter from "./routes/members.js"; // 본 미션 참고를 위한 코드이며 사전 미션에서는 사용하지 않습니다. const app = express(); @@ -12,12 +12,12 @@ const PORT = 3000; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -app.use("/assets", express.static(path.join(__dirname, "../public"))); +app.use('/assets', express.static(path.join(__dirname, '../public'))); -app.use("/", movieRouter); +app.use('/', movieRouter); // app.use("/members", membersRouter); // 본 미션 참고를 위한 코드이며 사전 미션에서는 사용하지 않습니다. // Start server app.listen(PORT, () => { - console.log(`Server is running on http://localhost:${PORT}`); + console.log(`Server is running on http://localhost:${PORT}`); }); diff --git a/ssr/server/routes/index.js b/ssr/server/routes/index.js index 84d32f2..5ce1207 100644 --- a/ssr/server/routes/index.js +++ b/ssr/server/routes/index.js @@ -1,21 +1,15 @@ -import { Router } from "express"; -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; +import { Router } from 'express'; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import renderMovieItemPage from '../../utils/renderMovieItemPage.js'; +import renderModal from '../../utils/renderModal.js'; const router = Router(); -router.get("/", (_, res) => { - const templatePath = path.join(__dirname, "../../views", "index.html"); - const moviesHTML = "

들어갈 본문 작성

"; +router.get(['/', '/now-playing'], (_, res) => renderMovieItemPage(res, 'NOW_PLAYING')); +router.get('/popular', (_, res) => renderMovieItemPage(res, 'POPULAR')); +router.get('/top-rated', (_, res) => renderMovieItemPage(res, 'TOP_RATED')); +router.get('/upcoming', (_, res) => renderMovieItemPage(res, 'UPCOMING')); - const template = fs.readFileSync(templatePath, "utf-8"); - const renderedHTML = template.replace("", moviesHTML); - - res.send(renderedHTML); -}); +router.get('/detail/:id', (req, res) => renderModal(res, req.params.id)); export default router; diff --git a/ssr/utils/renderModal.js b/ssr/utils/renderModal.js new file mode 100644 index 0000000..0004fba --- /dev/null +++ b/ssr/utils/renderModal.js @@ -0,0 +1,56 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +import { fetchMovieDetail } from '../apis/movies.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const renderModal = async (res, movieId) => { + const templatePath = path.join(__dirname, '../views', 'index.html'); + const movieDetail = await fetchMovieDetail(movieId); + + let template = fs.readFileSync(templatePath, 'utf-8'); + + template = template.replace( + '', + /*html*/ ` + + + + ` + ); + + res.send(template); +}; + +export default renderModal; diff --git a/ssr/utils/renderMovieItemPage.js b/ssr/utils/renderMovieItemPage.js new file mode 100644 index 0000000..e877e46 --- /dev/null +++ b/ssr/utils/renderMovieItemPage.js @@ -0,0 +1,40 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +import { fetchMovies } from '../apis/movies.js'; +import { renderMovieItems } from './renderMovieItems.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const TITLE_BY_MOVIE_LIST = { + POPULAR: '지금 인기 있는 영화', + NOW_PLAYING: '지금 상영중인 영화', + TOP_RATED: '평점 높은 영화', + UPCOMING: '상영 예정인 영화', +}; + +const renderMovieItemPage = async (res, category) => { + const templatePath = path.join(__dirname, '../views', 'index.html'); + const movieItems = await fetchMovies(category); + const bestMovieItem = movieItems.results[0]; + + const moviesHTML = renderMovieItems(movieItems.results).join(''); + + let template = fs.readFileSync(templatePath, 'utf-8'); + + template = template.replace( + '${background-container}', + 'https://image.tmdb.org/t/p/w1920_and_h800_multi_faces' + bestMovieItem.backdrop_path + ); + template = template.replace('${bestMovie.rate}', bestMovieItem.vote_average); + template = template.replace('${bestMovie.title}', bestMovieItem.title); + + template = template.replace('', TITLE_BY_MOVIE_LIST[category]); + template = template.replace('', moviesHTML); + + res.send(template); +}; + +export default renderMovieItemPage; diff --git a/ssr/utils/renderMovieItems.js b/ssr/utils/renderMovieItems.js new file mode 100644 index 0000000..74d6861 --- /dev/null +++ b/ssr/utils/renderMovieItems.js @@ -0,0 +1,21 @@ +export const renderMovieItems = (movieItems = []) => + movieItems.map( + ({ id, title, poster_path, vote_average }) => /*html*/ ` +
  • + +
    + ${title} +
    + +

    ${vote_average}

    + ${title} +
    +
    +
    +
  • + ` + ); diff --git a/ssr/views/index.html b/ssr/views/index.html index a052396..83763e5 100644 --- a/ssr/views/index.html +++ b/ssr/views/index.html @@ -1,80 +1,81 @@ - - - - - - - - - - 영화 리뷰 - - -
    -
    -
    - -
    -

    MovieList

    -
    -
    - - ${bestMovie.rate} -
    -
    ${bestMovie.title}
    - -
    -
    -
    -
    -
    - -
    -
    -

    지금 인기 있는 영화

    -
      - -
    -
    -
    -
    + + + + + + + + + + 영화 리뷰 + + +
    +
    +
    + +
    +

    MovieList

    +
    +
    + + ${bestMovie.rate} +
    +
    ${bestMovie.title}
    + +
    +
    +
    +
    +
    + +
    +
    + +

    +
      + +
    +
    +
    +
    -
    -

    © 우아한테크코스 All Rights Reserved.

    -

    -
    -
    - - +
    +

    © 우아한테크코스 All Rights Reserved.

    +

    +
    +
    + +