From c4207daa3c533140d1a1867d0382f8bd2c347d02 Mon Sep 17 00:00:00 2001 From: Yoonkyoungme <100656920+Yoonkyoungme@users.noreply.github.com> Date: Thu, 3 Oct 2024 21:09:23 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=98=81=ED=99=94=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/package.json | 4 ++-- ssr/server/HTMLgenerator.js | 25 +++++++++++++++++++ ssr/server/apis/movies.js | 13 ++++++++++ ssr/server/constants.js | 22 +++++++++++++++++ ssr/server/routes/index.js | 48 +++++++++++++++++++++++++++++++++---- 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 ssr/server/HTMLgenerator.js create mode 100644 ssr/server/apis/movies.js create mode 100644 ssr/server/constants.js diff --git a/ssr/package.json b/ssr/package.json index db1a534..4d26357 100644 --- a/ssr/package.json +++ b/ssr/package.json @@ -4,8 +4,8 @@ "description": "SSR 렌더링으로 영화 목록 불러오기", "main": "server/index.js", "scripts": { - "start": "NODE_TLS_REJECT_UNAUTHORIZED=0 node server/index.js", - "dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 nodemon server/index.js --watch" + "start": "NODE_TLS_REJECT_UNAUTHORIZED=1 node server/index.js", + "dev": "NODE_TLS_REJECT_UNAUTHORIZED=1 nodemon server/index.js --watch" }, "type": "module", "dependencies": { diff --git a/ssr/server/HTMLgenerator.js b/ssr/server/HTMLgenerator.js new file mode 100644 index 0000000..1046a25 --- /dev/null +++ b/ssr/server/HTMLgenerator.js @@ -0,0 +1,25 @@ +import { TMDB_THUMBNAIL_URL } from "./constants.js"; + +export const generateMovieItems = (movies = []) => { + return movies + .map(({ id, title, vote_average, poster_path }) => { + /*html*/ + return ` +
  • + +
    + ${title} +
    +

    + + ${vote_average.toFixed(1)} +

    + ${title} +
    +
    +
    +
  • + `; + }) + .join(""); +}; diff --git a/ssr/server/apis/movies.js b/ssr/server/apis/movies.js new file mode 100644 index 0000000..3cf00c6 --- /dev/null +++ b/ssr/server/apis/movies.js @@ -0,0 +1,13 @@ +import { + TMDB_MOVIE_LISTS, + FETCH_OPTIONS, + TMDB_MOVIE_DETAIL_URL, +} from "../constants.js"; + +export const fetchMovieItems = async (category = "nowPlaying") => { + const url = TMDB_MOVIE_LISTS[category]; + const response = await fetch(url, FETCH_OPTIONS); + const data = await response.json(); + + return data.results; +}; diff --git a/ssr/server/constants.js b/ssr/server/constants.js new file mode 100644 index 0000000..c62d0e5 --- /dev/null +++ b/ssr/server/constants.js @@ -0,0 +1,22 @@ +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", + nowPlaying: BASE_URL + "/now_playing?language=ko-KR&page=1", + topRated: 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.VITE_TMDB_TOKEN, + }, +}; diff --git a/ssr/server/routes/index.js b/ssr/server/routes/index.js index 84d32f2..664e6f9 100644 --- a/ssr/server/routes/index.js +++ b/ssr/server/routes/index.js @@ -2,20 +2,58 @@ import { Router } from "express"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; +import { generateMovieItems } from "../HTMLgenerator.js"; +import { fetchMovieItems } from "../apis/movies.js"; +import { TMDB_BANNER_URL } from "../constants.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const router = Router(); -router.get("/", (_, res) => { +const renderMovieItemsHTML = (movies) => { const templatePath = path.join(__dirname, "../../views", "index.html"); - const moviesHTML = "

    들어갈 본문 작성

    "; - const template = fs.readFileSync(templatePath, "utf-8"); - const renderedHTML = template.replace("", moviesHTML); - res.send(renderedHTML); + const movieItemsHTML = generateMovieItems(movies); + return template + .replace("", movieItemsHTML) + .replace("${bestMovie.title}", movies[0].title) + .replace("${bestMovie.rate}", movies[0].vote_average.toFixed(1)) + .replace( + "${background-container}", + `${TMDB_BANNER_URL}/${movies[0].backdrop_path}` + ); +}; + +router.get("/", async (_, res) => { + const movies = await fetchMovieItems(); + + res.send(renderMovieItemsHTML(movies)); +}); + +router.get("/now-playing", async (_, res) => { + const movies = await fetchMovieItems("nowPlaying"); + + res.send(renderMovieItemsHTML(movies)); +}); + +router.get("/popular", async (_, res) => { + const movies = await fetchMovieItems("popular"); + + res.send(renderMovieItemsHTML(movies)); +}); + +router.get("/top-rated", async (_, res) => { + const movies = await fetchMovieItems("topRated"); + + res.send(renderMovieItemsHTML(movies)); +}); + +router.get("/upcoming", async (_, res) => { + const movies = await fetchMovieItems("upcoming"); + + res.send(renderMovieItemsHTML(movies)); }); export default router; From 3357632161aa058a873a168539bcd0c35d57127b Mon Sep 17 00:00:00 2001 From: Yoonkyoungme <100656920+Yoonkyoungme@users.noreply.github.com> Date: Thu, 3 Oct 2024 21:46:24 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=83=81=EC=84=B8=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=AA=A8=EB=8B=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/server/HTMLgenerator.js | 40 ++++++++++++++++++++++++++++++++++++- ssr/server/apis/movies.js | 8 ++++++++ ssr/server/routes/index.js | 19 ++++++++++++++++-- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/ssr/server/HTMLgenerator.js b/ssr/server/HTMLgenerator.js index 1046a25..19cd399 100644 --- a/ssr/server/HTMLgenerator.js +++ b/ssr/server/HTMLgenerator.js @@ -11,7 +11,7 @@ export const generateMovieItems = (movies = []) => { ${title}

    - + ${vote_average.toFixed(1)}

    ${title} @@ -23,3 +23,41 @@ export const generateMovieItems = (movies = []) => { }) .join(""); }; + +export const generateMovieModal = (movieInfo = {}) => { + const { + title, + poster_path, + genres = [], + vote_average = 0, + overview, + } = movieInfo; + + /*html*/ + return ` + + `; +}; diff --git a/ssr/server/apis/movies.js b/ssr/server/apis/movies.js index 3cf00c6..0a33f77 100644 --- a/ssr/server/apis/movies.js +++ b/ssr/server/apis/movies.js @@ -11,3 +11,11 @@ export const fetchMovieItems = async (category = "nowPlaying") => { return data.results; }; + +export const fetchMovieDetail = async (id) => { + const url = `${TMDB_MOVIE_DETAIL_URL}${id}?language=ko-KR`; + const response = await fetch(url, FETCH_OPTIONS); + const data = await response.json(); + + return data; +}; diff --git a/ssr/server/routes/index.js b/ssr/server/routes/index.js index 664e6f9..da02d90 100644 --- a/ssr/server/routes/index.js +++ b/ssr/server/routes/index.js @@ -2,8 +2,8 @@ import { Router } from "express"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; -import { generateMovieItems } from "../HTMLgenerator.js"; -import { fetchMovieItems } from "../apis/movies.js"; +import { generateMovieItems, generateMovieModal } from "../HTMLgenerator.js"; +import { fetchMovieDetail, fetchMovieItems } from "../apis/movies.js"; import { TMDB_BANNER_URL } from "../constants.js"; const __filename = fileURLToPath(import.meta.url); @@ -26,6 +26,14 @@ const renderMovieItemsHTML = (movies) => { ); }; +const renderMovieModalDetailHTML = (movie) => { + const templatePath = path.join(__dirname, "../../views", "index.html"); + const template = fs.readFileSync(templatePath, "utf-8"); + + const movieModalDetailHTML = generateMovieModal(movie); + return template.replace("", movieModalDetailHTML); +}; + router.get("/", async (_, res) => { const movies = await fetchMovieItems(); @@ -56,4 +64,11 @@ router.get("/upcoming", async (_, res) => { res.send(renderMovieItemsHTML(movies)); }); +router.get("/detail/:id", async (req, res) => { + const movieId = req.params.id; + const movieDetail = await fetchMovieDetail(movieId); + + res.send(renderMovieModalDetailHTML(movieDetail)); +}); + export default router;