{"id":82,"date":"2026-06-26T13:32:24","date_gmt":"2026-06-26T13:32:24","guid":{"rendered":"https:\/\/aabbee.cafe24.com\/?p=82"},"modified":"2026-06-26T14:02:47","modified_gmt":"2026-06-26T14:02:47","slug":"movie-detail","status":"publish","type":"post","link":"https:\/\/coalacoding.com\/?p=82","title":{"rendered":"MovieDetail \u2014 \uc601\ud654 \uc0c1\uc138 \ud398\uc774\uc9c0 \ub9cc\ub4e4\uae30"},"content":{"rendered":"<blockquote>\n<p><strong>Tip<\/strong>: <strong>Gemini CLI\ub85c \uad6c\ud604\ud558\uae30 \u2014 \uc601\ud654 \uc0c1\uc138 \ud398\uc774\uc9c0<\/strong><\/p>\n<ul>\n<li><strong>\ud504\ub86c\ud504\ud2b8:<\/strong> <code>gemini &quot;src\/components\/MovieDetail.jsx\ub97c \uc791\uc131\ud574\uc918. useParams\ub85c \uc601\ud654 ID\ub97c \ubc1b\uc544\uc11c TMDB API movie\/[id]?append_to_response=videos\ub85c \uc0c1\uc138\uc815\ubcf4\uc640 \uc608\uace0\ud3b8\uc744 \ud55c \ubc88\uc5d0 \uac00\uc838\uc640\uc57c \ud574. \ud3ec\uc2a4\ud130, \uc6d0\uc81c, \uac1c\ubd09\uc77c, \ub7ec\ub2dd\ud0c0\uc784, \uc7a5\ub974 \ubc30\uc9c0, \uc904\uac70\ub9ac\ub97c \ud45c\uc2dc\ud558\uace0, YouTube Trailer\uac00 \uc788\uc73c\uba74 Modal \ud31d\uc5c5\uc73c\ub85c \uc7ac\uc0dd\ud574\uc918. useNavigate\ub85c \ub4a4\ub85c\uac00\uae30 \ubc84\ud2bc\ub3c4 \ub9cc\ub4e4\uc5b4\uc918. axios \uc778\uc2a4\ud134\uc2a4\ub294 [axios \uacbd\ub85c]\uc5d0\uc11c \uac00\uc838\uc640\uc918.&quot;<\/code>\n<ul>\n<li><strong>\uc0ac\uc6a9 \uac00\uc774\ub4dc:<\/strong> <code>[axios \uacbd\ub85c]<\/code>\ub97c <code>..\/api\/axios<\/code>\ub85c \ubc14\uafbc\ub2e4. \uc608\uace0\ud3b8 \uc790\ub3d9 \uc7ac\uc0dd\uc744 \uc6d0\ud558\uc9c0 \uc54a\uc73c\uba74 \ud504\ub86c\ud504\ud2b8\uc5d0 &quot;autoplay \uc5c6\uc774&quot;\ub97c \ucd94\uac00\ud55c\ub2e4.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/blockquote>\n<h2>1. \uc0c1\uc138 \ud398\uc774\uc9c0\uc758 \uae30\ub2a5<\/h2>\n<p>\uc774\uc804 \uad50\uc548\uacfc \ub2ec\ub9ac, \uc0c8 \uc0c1\uc138 \ud398\uc774\uc9c0\ub294 \ud6e8\uc52c \ud48d\ubd80\ud55c \uae30\ub2a5\uc744 \uac00\uc9c4\ub2e4.<\/p>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uae30\ub2a5<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">\ud3ec\uc2a4\ud130 + \uae30\ubcf8 \uc815\ubcf4<\/td>\n<td align=\"left\">\uc81c\ubaa9, \uc6d0\uc81c, \uac1c\ubd09\uc77c, \ub7ec\ub2dd\ud0c0\uc784<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\uc7a5\ub974 \ud0dc\uadf8<\/td>\n<td align=\"left\">\ub178\ub780\uc0c9 \ubc30\uc9c0\ub85c \uc7a5\ub974 \ud45c\uc2dc<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\ud3c9\uc810 + \ud22c\ud45c\uc218<\/td>\n<td align=\"left\">\u2605 8.4 (1,234\uba85 \ud3c9\uac00)<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\uc904\uac70\ub9ac<\/td>\n<td align=\"left\">\ud55c\uad6d\uc5b4 \uc904\uac70\ub9ac \ud45c\uc2dc<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\uc608\uace0\ud3b8 \ubcf4\uae30<\/td>\n<td align=\"left\">YouTube \uc608\uace0\ud3b8\uc744 Modal \ud31d\uc5c5\uc73c\ub85c \uc7ac\uc0dd<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\ub4a4\ub85c\uac00\uae30<\/td>\n<td align=\"left\">\uc774\uc804 \ud398\uc774\uc9c0\ub85c \ub3cc\uc544\uac00\ub294 \ubc84\ud2bc<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\ub124 \ub2e8\uacc4\ub85c \ub098\ub204\uc5b4 \uc791\uc5c5\ud55c\ub2e4.<\/p>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc21c\uc11c<\/th>\n<th align=\"left\">\ub9cc\ub4e4 \uae30\ub2a5<\/th>\n<th align=\"left\">\ud575\uc2ec \uac1c\ub150<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">1\ub2e8\uacc4<\/td>\n<td align=\"left\">import + API \ud638\ucd9c<\/td>\n<td align=\"left\"><code>useParams<\/code>, <code>append_to_response<\/code><\/td>\n<\/tr>\n<tr>\n<td align=\"left\">2\ub2e8\uacc4<\/td>\n<td align=\"left\">\ub85c\ub529\/\uc5d0\ub7ec \ucc98\ub9ac<\/td>\n<td align=\"left\">\uc870\uac74\ubd80 \ub80c\ub354\ub9c1<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">3\ub2e8\uacc4<\/td>\n<td align=\"left\">\uc601\ud654 \uc815\ubcf4 \ub808\uc774\uc544\uc6c3<\/td>\n<td align=\"left\">\uc7a5\ub974 \ubc30\uc9c0, \ud3c9\uc810 \ud3ec\ub9f7<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">4\ub2e8\uacc4<\/td>\n<td align=\"left\">\uc608\uace0\ud3b8 \ud31d\uc5c5<\/td>\n<td align=\"left\"><code>Modal<\/code>, YouTube iframe<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>2. 1\ub2e8\uacc4 \u2014 import + API \ud638\ucd9c<\/h2>\n<p><code>src\/components\/MovieDetail.jsx<\/code> \ud30c\uc77c\uc744 \uc5f4\uace0 \uc784\uc2dc \ucf54\ub4dc\ub97c <strong>\ubaa8\ub450 \uc9c0\uc6b4 \ub4a4<\/strong> \uc791\uc131\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">import { useState, useEffect } from &quot;react&quot;;\nimport { useParams, useNavigate } from &quot;react-router&quot;;\nimport { FontAwesomeIcon } from &quot;@fortawesome\/react-fontawesome&quot;;\nimport { faArrowLeft, faPlay } from &quot;@fortawesome\/free-solid-svg-icons&quot;;\nimport api from &quot;..\/api\/axios&quot;;\nimport { Spinner, Modal, Button } from &quot;.\/UI.jsx&quot;;\n\nexport function MovieDetail() {\n  const { id } = useParams();\n  const navigate = useNavigate();\n\n  const [movie, setMovie] = useState(null);\n  const [loading, setLoading] = useState(true);\n  const [showTrailer, setShowTrailer] = useState(false);\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc904<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">2<\/td>\n<td align=\"left\"><code>useNavigate<\/code> \u2014 &quot;\ub4a4\ub85c\uac00\uae30&quot; \ubc84\ud2bc\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4. <code>navigate(-1)<\/code>\uc73c\ub85c \uc774\uc804 \ud398\uc774\uc9c0\ub85c \ub3cc\uc544\uac04\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">4<\/td>\n<td align=\"left\">\uc67c\ucabd \ud654\uc0b4\ud45c(<code>faArrowLeft<\/code>)\uc640 \uc7ac\uc0dd(<code>faPlay<\/code>) \uc544\uc774\ucf58\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">6<\/td>\n<td align=\"left\">4\ud3b8\uc5d0\uc11c \ub9cc\ub4e0 <code>Spinner<\/code>, <code>Modal<\/code>, <code>Button<\/code>\uc744 \ubaa8\ub450 \uc0ac\uc6a9\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">9<\/td>\n<td align=\"left\">URL\uc5d0\uc11c \uc601\ud654 ID\ub97c \uaebc\ub0b8\ub2e4. <code>\/movie\/550<\/code>\uc774\uba74 <code>id<\/code>\ub294 <code>&quot;550&quot;<\/code>\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">12<\/td>\n<td align=\"left\"><code>movie<\/code> \u2014 \uc601\ud654 \uc0c1\uc138 \ub370\uc774\ud130. \ucd08\uae30\uac12 <code>null<\/code>\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">13<\/td>\n<td align=\"left\"><code>loading<\/code> \u2014 \ucd08\uae30\uac12 <code>true<\/code>\ub85c \uc2dc\uc791\ud55c\ub2e4. API \uc751\ub2f5\uc774 \uc624\uba74 <code>false<\/code>\ub85c \ubc14\uafbc\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">14<\/td>\n<td align=\"left\"><code>showTrailer<\/code> \u2014 \uc608\uace0\ud3b8 \ud31d\uc5c5\uc758 \uc5f4\ub9bc\/\ub2eb\ud798 \uc0c1\ud0dc\uc774\ub2e4.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\uac19\uc740 <code>MovieDetail.jsx<\/code> \ud30c\uc77c\uc5d0\uc11c, <code>const [showTrailer, ...<\/code> \uc904 \ubc14\ub85c \uc544\ub798\uc5d0 \uc774\uc5b4\uc11c \uc791\uc131\ud55c\ub2e4. \uc774 \ucf54\ub4dc\ub294 URL\uc5d0\uc11c \uaebc\ub0b8 \uc601\ud654 ID\ub85c TMDB\uc5d0 &quot;\uc774 \uc601\ud654\uc758 \uc0c1\uc138 \uc815\ubcf4\uc640 \uc608\uace0\ud3b8 \uc601\uc0c1 \ubaa9\ub85d\uc744 \ud55c\uaebc\ubc88\uc5d0 \ubcf4\ub0b4\uc918&quot;\ub77c\uace0 \uc694\uccad\ud558\ub294 \ubd80\ubd84\uc774\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">  useEffect(() =&gt; {\n    api\n      .get(`movie\/${id}`, {\n        params: { append_to_response: &quot;videos&quot; },\n      })\n      .then((res) =&gt; {\n        setMovie(res.data);\n        setLoading(false);\n      })\n      .catch(() =&gt; {\n        setMovie(null);\n        setLoading(false);\n      });\n  }, [id]);\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc904<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">3-5<\/td>\n<td align=\"left\"><code>append_to_response: &quot;videos&quot;<\/code> \u2014 \uc601\ud654 \uae30\ubcf8 \uc815\ubcf4\uc640 \ud568\uaed8 <strong>\uc608\uace0\ud3b8 \uc601\uc0c1 \ubaa9\ub85d<\/strong>\ub3c4 \ud55c \ubc88\uc5d0 \uac00\uc838\uc628\ub2e4. TMDB API\uc758 \ud2b9\uc218 \uae30\ub2a5\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">6-8<\/td>\n<td align=\"left\">\uc131\uacf5\ud558\uba74 <code>movie<\/code>\uc5d0 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\uace0 <code>loading<\/code>\uc744 \ub048\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">10-12<\/td>\n<td align=\"left\">\uc2e4\ud328\ud558\uba74 <code>movie<\/code>\ub97c <code>null<\/code>\ub85c \uc124\uc815\ud558\uace0 <code>loading<\/code>\uc744 \ub048\ub2e4. \uc5d0\ub7ec \ud654\uba74\uc744 \ud45c\uc2dc\ud558\uae30 \uc704\ud574\uc11c\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">14<\/td>\n<td align=\"left\"><code>[id]<\/code> \u2014 <code>id<\/code>\uac00 \ubc14\ub00c\uba74 API\ub97c \ub2e4\uc2dc \ud638\ucd9c\ud55c\ub2e4.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><Accordion title=\"append_to_response\ub780?\"><br \/>\nTMDB API\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \uc601\ud654 \uc815\ubcf4\ub9cc \ubc18\ud658\ud55c\ub2e4. `append_to_response`\ub97c \uc0ac\uc6a9\ud558\uba74 \ud55c \ubc88\uc758 \uc694\uccad\uc73c\ub85c <strong>\ucd94\uac00 \ub370\uc774\ud130<\/strong>\ub97c \ud568\uaed8 \ubc1b\uc744 \uc218 \uc788\ub2e4.<\/p>\n<pre><code>GET \/movie\/550?append_to_response=videos\n<\/code><\/pre>\n<p>\uc774\ub807\uac8c \ud558\uba74 \uc751\ub2f5\uc5d0 <code>movie.videos.results<\/code> \ubc30\uc5f4\uc774 \ucd94\uac00\ub418\uc5b4, \uc608\uace0\ud3b8 \uc601\uc0c1 \uc815\ubcf4\ub97c \ubcc4\ub3c4 API \ud638\ucd9c \uc5c6\uc774 \ubc14\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.<br \/>\n<\/Accordion><\/p>\n<hr>\n<h2>3. 2\ub2e8\uacc4 \u2014 \ub85c\ub529\/\uc5d0\ub7ec \ucc98\ub9ac<\/h2>\n<p>\uac19\uc740 <code>MovieDetail.jsx<\/code> \ud30c\uc77c\uc5d0\uc11c, <code>useEffect<\/code> \ube14\ub85d \ubc14\ub85c \uc544\ub798\uc5d0 \uc774\uc5b4\uc11c \uc791\uc131\ud55c\ub2e4. \uc774 \ubd80\ubd84\uc740 <strong>\ubb38\uc9c0\uae30<\/strong> \uc5ed\ud560\uc774\ub2e4. \ub370\uc774\ud130\uac00 \uc544\uc9c1 \ub3c4\ucc29\ud558\uc9c0 \uc54a\uc558\uc73c\uba74 \ub85c\ub529 \ud654\uba74\uc744 \ubcf4\uc5ec\uc8fc\uace0, \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc73c\uba74 \uc5d0\ub7ec \uba54\uc2dc\uc9c0\ub97c \ubcf4\uc5ec\uc8fc\uace0, \uc815\uc0c1\uc774\uba74 \uadf8 \uc544\ub798 \ucf54\ub4dc\ub85c \ub118\uaca8\ubcf4\ub0b4 \uc900\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">  if (loading) return &lt;Spinner full \/&gt;;\n\n  if (!movie) {\n    return (\n      &lt;div className=&quot;bg-black min-h-screen flex items-center justify-center&quot;&gt;\n        &lt;p className=&quot;text-red-400 text-2xl&quot;&gt;\uc601\ud654 \uc815\ubcf4\ub97c \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\n      &lt;\/div&gt;\n    );\n  }\n\n  const poster = `https:\/\/image.tmdb.org\/t\/p\/w500\/${movie.poster_path}`;\n  const videoList = movie.videos ? movie.videos.results : [];\n  const trailer = videoList.find((v) =&gt; v.type === &quot;Trailer&quot; &amp;&amp; v.site === &quot;YouTube&quot;);\n  const genres = movie.genres || [];\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc904<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">1<\/td>\n<td align=\"left\"><code>loading<\/code>\uc774 <code>true<\/code>\uc774\uba74 \uc804\uccb4 \ud654\uba74 \uc2a4\ud53c\ub108\ub97c \ud45c\uc2dc\ud558\uace0 \uc885\ub8cc\ud55c\ub2e4. JSX\uc5d0\uc11c <code>&lt;Spinner full \/&gt;<\/code>\ucc98\ub7fc \uac12 \uc5c6\uc774 prop \uc774\ub984\ub9cc \uc4f0\uba74 <code>full={true}<\/code>\uc640 \ub3d9\uc77c\ud558\ub2e4. <code>Spinner<\/code> \ucef4\ud3ec\ub10c\ud2b8 \ub0b4\ubd80\uc5d0\uc11c <code>full<\/code>\uc774 <code>true<\/code>\uc774\uba74 \ud654\uba74 \uc804\uccb4\ub97c \ucc44\uc6b4\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">3-8<\/td>\n<td align=\"left\"><code>movie<\/code>\uac00 <code>null<\/code>\uc774\uba74 \uc5d0\ub7ec \uba54\uc2dc\uc9c0\ub97c \ud45c\uc2dc\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">11<\/td>\n<td align=\"left\">\ud3ec\uc2a4\ud130 \uc774\ubbf8\uc9c0 URL\uc744 \uc870\ud569\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">12<\/td>\n<td align=\"left\">\uc608\uace0\ud3b8 \uc601\uc0c1 \ubaa9\ub85d\uc744 \uaebc\ub0b8\ub2e4. <code>movie.videos<\/code>\uac00 \uc5c6\uc73c\uba74 \ube48 \ubc30\uc5f4\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">13<\/td>\n<td align=\"left\"><code>.find()<\/code>\ub85c YouTube \uc608\uace0\ud3b8\uc744 \ucc3e\ub294\ub2e4. \uc5c6\uc73c\uba74 <code>undefined<\/code>\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">14<\/td>\n<td align=\"left\">\uc7a5\ub974 \ubc30\uc5f4\uc744 \uaebc\ub0b8\ub2e4.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><Accordion title=\".find() \uba54\uc11c\ub4dc\ub780?\"><br \/>\n\ubc30\uc5f4\uc5d0\uc11c \uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 <strong>\uccab \ubc88\uc9f8 \uc694\uc18c \ud558\ub098<\/strong>\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\uc774\ub2e4. \uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 \uc694\uc18c\uac00 \uc5c6\uc73c\uba74 `undefined`\ub97c \ubc18\ud658\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-javascript\">\ubc30\uc5f4.find((\uc694\uc18c) =&gt; \uc870\uac74\uc2dd)\n<\/code><\/pre>\n<p>\ucf5c\ubc31 \ud568\uc218\ub294 \ubc30\uc5f4\uc758 \uc694\uc18c\ub97c \ud558\ub098\uc529 \ubc1b\uc544 \uc870\uac74\uc744 \uac80\uc0ac\ud55c\ub2e4. \uc870\uac74\uc774 <code>true<\/code>\uc778 \uccab \ubc88\uc9f8 \uc694\uc18c\ub97c \ub9cc\ub098\ub294 \uc21c\uac04 \ubc14\ub85c \ubc18\ud658\ud558\uace0 \ud0d0\uc0c9\uc744 \uc911\ub2e8\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-javascript\">const arr = [\n  { type: &quot;Teaser&quot;, site: &quot;YouTube&quot; },\n  { type: &quot;Trailer&quot;, site: &quot;YouTube&quot; },  \/\/ \u2190 \uc774 \uc694\uc18c\uc5d0\uc11c \uc870\uac74 \uc77c\uce58, \ud0d0\uc0c9 \uc911\ub2e8\n  { type: &quot;Trailer&quot;, site: &quot;Vimeo&quot; },    \/\/ \u2190 \uc5ec\uae30\uae4c\uc9c0 \uc624\uc9c0 \uc54a\ub294\ub2e4\n];\n\n\/\/ type\uc774 &quot;Trailer&quot;\uc774\uace0 site\uac00 &quot;YouTube&quot;\uc778 \uccab \ubc88\uc9f8 \uc694\uc18c\ub97c \ubc18\ud658\narr.find((v) =&gt; v.type === &quot;Trailer&quot; &amp;&amp; v.site === &quot;YouTube&quot;);\n\/\/ \uacb0\uacfc: { type: &quot;Trailer&quot;, site: &quot;YouTube&quot; }\n\n\/\/ \uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 \uc694\uc18c\uac00 \uc5c6\uc73c\uba74 undefined \ubc18\ud658\narr.find((v) =&gt; v.site === &quot;Netflix&quot;);\n\/\/ \uacb0\uacfc: undefined\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uba54\uc11c\ub4dc<\/th>\n<th align=\"left\">\ubc18\ud658\uac12<\/th>\n<th align=\"left\">\uc0ac\uc6a9 \ubaa9\uc801<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\"><code>.find()<\/code><\/td>\n<td align=\"left\">\uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 <strong>\uccab \ubc88\uc9f8 \uc694\uc18c<\/strong> (\uc5c6\uc73c\uba74 <code>undefined<\/code>)<\/td>\n<td align=\"left\">\ud2b9\uc815 \uc694\uc18c \ud558\ub098\ub97c \uaebc\ub0bc \ub54c<\/td>\n<\/tr>\n<tr>\n<td align=\"left\"><code>.filter()<\/code><\/td>\n<td align=\"left\">\uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 <strong>\ubaa8\ub4e0 \uc694\uc18c\uc758 \ubc30\uc5f4<\/strong> (\uc5c6\uc73c\uba74 \ube48 \ubc30\uc5f4 <code>[]<\/code>)<\/td>\n<td align=\"left\">\uc870\uac74\uc5d0 \ub9de\ub294 \uc5ec\ub7ec \uc694\uc18c\ub97c \ubaa8\uc744 \ub54c<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\uc774 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc608\uace0\ud3b8 \uc601\uc0c1\uc774 \uc5ec\ub7ec \uac1c \uc788\uc5b4\ub3c4 \uccab \ubc88\uc9f8 YouTube Trailer \ud558\ub098\ub9cc \uc788\uc73c\uba74 \ucda9\ubd84\ud558\ubbc0\ub85c <code>.find()<\/code>\ub97c \uc0ac\uc6a9\ud55c\ub2e4.<br \/>\n<\/Accordion><\/p>\n<hr>\n<h2>4. 3\ub2e8\uacc4 \u2014 \uc601\ud654 \uc815\ubcf4 \ub808\uc774\uc544\uc6c3<\/h2>\n<p>\uac19\uc740 <code>MovieDetail.jsx<\/code> \ud30c\uc77c\uc5d0\uc11c, <code>const genres = ...<\/code> \uc904 \uc544\ub798\uc5d0 <code>return<\/code> \ubb38\uc744 \uc791\uc131\ud55c\ub2e4. \ucf54\ub4dc\uac00 \uae38\uae30 \ub54c\ubb38\uc5d0 \uc138 \ubd80\ubd84\uc73c\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud55c\ub2e4. \ud0ed\uc744 \ub20c\ub7ec \uac01 \ubd80\ubd84\uc744 \ud655\uc778\ud558\uba74\uc11c <strong>\uc21c\uc11c\ub300\ub85c \uc774\uc5b4 \ubd99\uc778\ub2e4<\/strong>.<\/p>\n<h4>\ub4a4\ub85c\uac00\uae30 + \ud3ec\uc2a4\ud130<\/h4>\n<pre><code class=\"language-jsx\">  return (\n    &lt;div className=&quot;bg-black min-h-screen relative&quot;&gt;\n      &lt;div className=&quot;relative pt-24 pb-16&quot;&gt;\n        &lt;div className=&quot;container mx-auto px-6&quot;&gt;\n          &lt;Button variant=&quot;ghost&quot; onClick={() =&gt; navigate(-1)} className=&quot;mb-6 inline-flex items-center gap-2&quot;&gt;\n            &lt;FontAwesomeIcon icon={faArrowLeft} \/&gt;\n            &lt;span&gt;\ub4a4\ub85c\uac00\uae30&lt;\/span&gt;\n          &lt;\/Button&gt;\n\n          &lt;div className=&quot;flex flex-col md:flex-row gap-10&quot;&gt;\n            &lt;img\n              src={poster}\n              alt={movie.title}\n              className=&quot;w-full md:w-72 rounded-lg object-cover shadow-2xl&quot;\n            \/&gt;\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc904<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">5<\/td>\n<td align=\"left\"><code>navigate(-1)<\/code> \u2014 \ube0c\ub77c\uc6b0\uc800 \ud788\uc2a4\ud1a0\ub9ac\uc5d0\uc11c \ud55c \ub2e8\uacc4 \ub4a4\ub85c \uac04\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">10<\/td>\n<td align=\"left\">\ubaa8\ubc14\uc77c\uc740 \uc138\ub85c(<code>flex-col<\/code>), PC\ub294 \uac00\ub85c(<code>md:flex-row<\/code>)\ub85c \ubc30\uce58\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">14<\/td>\n<td align=\"left\"><code>shadow-2xl<\/code>\ub85c \ud3ec\uc2a4\ud130\uc5d0 \ud070 \uadf8\ub9bc\uc790 \ud6a8\uacfc\ub97c \uc900\ub2e4.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>\uc81c\ubaa9 + \uc7a5\ub974<\/h4>\n<pre><code class=\"language-jsx\">            &lt;div className=&quot;flex flex-col gap-4 text-white&quot;&gt;\n              &lt;h1 className=&quot;text-4xl font-bold text-yellow-400&quot;&gt;{movie.title}&lt;\/h1&gt;\n              &lt;p className=&quot;text-gray-400 text-lg&quot;&gt;{movie.original_title}&lt;\/p&gt;\n\n              &lt;div className=&quot;flex gap-4 text-sm text-gray-300&quot;&gt;\n                &lt;span&gt;\uac1c\ubd09\uc77c: {movie.release_date || &quot;\ubbf8\uc815&quot;}&lt;\/span&gt;\n                &lt;span&gt;\ub7ec\ub2dd\ud0c0\uc784: {movie.runtime || 0}\ubd84&lt;\/span&gt;\n              &lt;\/div&gt;\n\n              &lt;div className=&quot;flex gap-2 flex-wrap&quot;&gt;\n                {genres.map((genre) =&gt; (\n                  &lt;span key={genre.id} className=&quot;bg-yellow-400 text-black px-3 py-1 rounded-full text-sm font-bold&quot;&gt;\n                    {genre.name}\n                  &lt;\/span&gt;\n                ))}\n              &lt;\/div&gt;\n\n\n              &lt;p className=&quot;text-gray-300 leading-relaxed max-w-xl&quot;&gt;\n                {movie.overview || &quot;\uc904\uac70\ub9ac \uc815\ubcf4\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.&quot;}\n              &lt;\/p&gt;\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc904<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">3<\/td>\n<td align=\"left\"><code>original_title<\/code> \u2014 \uc601\ud654\uc758 \uc6d0\uc5b4 \uc81c\ubaa9\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">6<\/td>\n<td align=\"left\">`movie.release_date<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">11-15<\/td>\n<td align=\"left\"><code>genres.map()<\/code>\uc73c\ub85c \uc7a5\ub974 \ubc30\uc5f4\uc744 \uc21c\ud68c\ud558\uba70 \ub178\ub780\uc0c9 \ubc30\uc9c0\ub97c \ub9cc\ub4e0\ub2e4. <code>rounded-full<\/code>\uc740 \uc644\uc804\ud55c \ub465\uadfc \ubaa8\uc11c\ub9ac\uc774\ub2e4.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>\uc608\uace0\ud3b8 \ubc84\ud2bc + \ub2eb\uae30<\/h4>\n<pre><code class=\"language-jsx\">              {trailer &amp;&amp; (\n                &lt;Button variant=&quot;danger&quot; onClick={() =&gt; setShowTrailer(true)} className=&quot;mt-2 px-6 py-3 rounded-lg inline-flex items-center gap-2 w-fit transition-colors&quot;&gt;\n                  &lt;FontAwesomeIcon icon={faPlay} \/&gt;\n                  \uc608\uace0\ud3b8 \ubcf4\uae30\n                &lt;\/Button&gt;\n              )}\n            &lt;\/div&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n\n      {showTrailer &amp;&amp; trailer &amp;&amp; (\n        &lt;Modal onClose={() =&gt; setShowTrailer(false)}&gt;\n          &lt;div className=&quot;w-full max-w-4xl aspect-video&quot;&gt;\n            &lt;iframe\n              className=&quot;w-full h-full rounded-lg&quot;\n              src={`https:\/\/www.youtube.com\/embed\/${trailer.key}?autoplay=1`}\n              title=&quot;Trailer&quot;\n              allow=&quot;autoplay; encrypted-media&quot;\n              allowFullScreen\n            \/&gt;\n          &lt;\/div&gt;\n        &lt;\/Modal&gt;\n      )}\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc904<\/th>\n<th align=\"left\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">1<\/td>\n<td align=\"left\"><code>trailer<\/code>\uac00 \uc788\uc744 \ub54c\ub9cc &quot;\uc608\uace0\ud3b8 \ubcf4\uae30&quot; \ubc84\ud2bc\uc744 \ud45c\uc2dc\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">2<\/td>\n<td align=\"left\"><code>variant=&quot;danger&quot;<\/code> \u2014 \ube68\uac04\uc0c9 \ubc84\ud2bc\uc774\ub2e4. <code>w-fit<\/code>\uc740 \ub0b4\uc6a9\ubb3c \ud06c\uae30\uc5d0 \ub9de\ucd94\ub294 \ub108\ube44\uc774\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">12-24<\/td>\n<td align=\"left\"><code>showTrailer<\/code>\uac00 <code>true<\/code>\uc774\uba74 4\ud3b8\uc5d0\uc11c \ub9cc\ub4e0 <code>Modal<\/code> \ucef4\ud3ec\ub10c\ud2b8 \uc548\uc5d0 YouTube iframe\uc744 \ud45c\uc2dc\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">17<\/td>\n<td align=\"left\"><code>trailer.key<\/code>\ub294 YouTube \uc601\uc0c1 ID\uc774\ub2e4. <code>autoplay=1<\/code>\ub85c \uc790\ub3d9 \uc7ac\uc0dd\ud55c\ub2e4.<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">14<\/td>\n<td align=\"left\"><code>aspect-video<\/code>\ub294 16:9 \ube44\uc728\uc744 \uc720\uc9c0\ud558\ub294 Tailwind \ud074\ub798\uc2a4\uc774\ub2e4.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>5. \ub3d9\uc791 \ud655\uc778<\/h2>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\ud655\uc778 \ud56d\ubaa9<\/th>\n<th align=\"left\">\uae30\ub300 \uacb0\uacfc<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">\uce74\ub4dc \ud074\ub9ad<\/td>\n<td align=\"left\">\uc0c1\uc138 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9, \ud3ec\uc2a4\ud130 + \uc815\ubcf4 \ud45c\uc2dc<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">&quot;\ub4a4\ub85c\uac00\uae30&quot; \ud074\ub9ad<\/td>\n<td align=\"left\">\uc774\uc804 \ud398\uc774\uc9c0\ub85c \ub3cc\uc544\uac10<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\uc7a5\ub974 \ud0dc\uadf8<\/td>\n<td align=\"left\">\ub178\ub780\uc0c9 \ub465\uadfc \ubc30\uc9c0\ub85c \ud45c\uc2dc<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">&quot;\uc608\uace0\ud3b8 \ubcf4\uae30&quot; \ud074\ub9ad<\/td>\n<td align=\"left\">\uac80\uc815 \ud31d\uc5c5\uc5d0\uc11c YouTube \uc601\uc0c1 \uc790\ub3d9 \uc7ac\uc0dd<\/td>\n<\/tr>\n<tr>\n<td align=\"left\">X \ubc84\ud2bc \ud074\ub9ad<\/td>\n<td align=\"left\">\ud31d\uc5c5 \ub2eb\ud798<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>6. \uc804\uccb4 \ucf54\ub4dc<\/h2>\n<pre><code class=\"language-jsx\">import { useState, useEffect } from &quot;react&quot;;\nimport { useParams, useNavigate } from &quot;react-router&quot;;\nimport { FontAwesomeIcon } from &quot;@fortawesome\/react-fontawesome&quot;;\nimport { faArrowLeft, faPlay } from &quot;@fortawesome\/free-solid-svg-icons&quot;;\nimport api from &quot;..\/api\/axios&quot;;\nimport { Spinner, Modal, Button } from &quot;.\/UI.jsx&quot;;\n\nexport function MovieDetail() {\n  const { id } = useParams();\n  const navigate = useNavigate();\n\n  const [movie, setMovie] = useState(null);\n  const [loading, setLoading] = useState(true);\n  const [showTrailer, setShowTrailer] = useState(false);\n\n  useEffect(() =&gt; {\n    api\n      .get(`movie\/${id}`, {\n        params: { append_to_response: &quot;videos&quot; },\n      })\n      .then((res) =&gt; {\n        setMovie(res.data);\n        setLoading(false);\n      })\n      .catch(() =&gt; {\n        setMovie(null);\n        setLoading(false);\n      });\n  }, [id]);\n\n  if (loading) return &lt;Spinner full \/&gt;;\n\n  if (!movie) {\n    return (\n      &lt;div className=&quot;bg-black min-h-screen flex items-center justify-center&quot;&gt;\n        &lt;p className=&quot;text-red-400 text-2xl&quot;&gt;\uc601\ud654 \uc815\ubcf4\ub97c \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\n      &lt;\/div&gt;\n    );\n  }\n\n  const poster = `https:\/\/image.tmdb.org\/t\/p\/w500\/${movie.poster_path}`;\n  const videoList = movie.videos ? movie.videos.results : [];\n  const trailer = videoList.find((v) =&gt; v.type === &quot;Trailer&quot; &amp;&amp; v.site === &quot;YouTube&quot;);\n  const genres = movie.genres || [];\n\n  return (\n    &lt;div className=&quot;bg-black min-h-screen relative&quot;&gt;\n      &lt;div className=&quot;relative pt-24 pb-16&quot;&gt;\n        &lt;div className=&quot;container mx-auto px-6&quot;&gt;\n          &lt;Button variant=&quot;ghost&quot; onClick={() =&gt; navigate(-1)} className=&quot;mb-6 inline-flex items-center gap-2&quot;&gt;\n            &lt;FontAwesomeIcon icon={faArrowLeft} \/&gt;\n            &lt;span&gt;\ub4a4\ub85c\uac00\uae30&lt;\/span&gt;\n          &lt;\/Button&gt;\n\n          &lt;div className=&quot;flex flex-col md:flex-row gap-10&quot;&gt;\n            &lt;img\n              src={poster}\n              alt={movie.title}\n              className=&quot;w-full md:w-72 rounded-lg object-cover shadow-2xl&quot;\n            \/&gt;\n\n            &lt;div className=&quot;flex flex-col gap-4 text-white&quot;&gt;\n              &lt;h1 className=&quot;text-4xl font-bold text-yellow-400&quot;&gt;{movie.title}&lt;\/h1&gt;\n              &lt;p className=&quot;text-gray-400 text-lg&quot;&gt;{movie.original_title}&lt;\/p&gt;\n\n              &lt;div className=&quot;flex gap-4 text-sm text-gray-300&quot;&gt;\n                &lt;span&gt;\uac1c\ubd09\uc77c: {movie.release_date || &quot;\ubbf8\uc815&quot;}&lt;\/span&gt;\n                &lt;span&gt;\ub7ec\ub2dd\ud0c0\uc784: {movie.runtime || 0}\ubd84&lt;\/span&gt;\n              &lt;\/div&gt;\n\n              &lt;div className=&quot;flex gap-2 flex-wrap&quot;&gt;\n                {genres.map((genre) =&gt; (\n                  &lt;span key={genre.id} className=&quot;bg-yellow-400 text-black px-3 py-1 rounded-full text-sm font-bold&quot;&gt;\n                    {genre.name}\n                  &lt;\/span&gt;\n                ))}\n              &lt;\/div&gt;\n\n\n              &lt;p className=&quot;text-gray-300 leading-relaxed max-w-xl&quot;&gt;\n                {movie.overview || &quot;\uc904\uac70\ub9ac \uc815\ubcf4\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.&quot;}\n              &lt;\/p&gt;\n\n              {trailer &amp;&amp; (\n                &lt;Button variant=&quot;danger&quot; onClick={() =&gt; setShowTrailer(true)} className=&quot;mt-2 px-6 py-3 rounded-lg inline-flex items-center gap-2 w-fit transition-colors&quot;&gt;\n                  &lt;FontAwesomeIcon icon={faPlay} \/&gt;\n                  \uc608\uace0\ud3b8 \ubcf4\uae30\n                &lt;\/Button&gt;\n              )}\n            &lt;\/div&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n\n      {showTrailer &amp;&amp; trailer &amp;&amp; (\n        &lt;Modal onClose={() =&gt; setShowTrailer(false)}&gt;\n          &lt;div className=&quot;w-full max-w-4xl aspect-video&quot;&gt;\n            &lt;iframe\n              className=&quot;w-full h-full rounded-lg&quot;\n              src={`https:\/\/www.youtube.com\/embed\/${trailer.key}?autoplay=1`}\n              title=&quot;Trailer&quot;\n              allow=&quot;autoplay; encrypted-media&quot;\n              allowFullScreen\n            \/&gt;\n          &lt;\/div&gt;\n        &lt;\/Modal&gt;\n      )}\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Tip: Gemini CLI\ub85c \uad6c\ud604\ud558\uae30 \u2014 \uc601\ud654 \uc0c1\uc138 \ud398\uc774\uc9c0 \ud504\ub86c\ud504\ud2b8: gemini &quot;src\/components\/MovieDetail.jsx\ub97c \uc791\uc131\ud574\uc918. useParams\ub85c \uc601\ud654 ID\ub97c \ubc1b\uc544\uc11c TMDB API movie\/[id]?append_to_response=videos\ub85c \uc0c1\uc138\uc815\ubcf4\uc640 \uc608\uace0\ud3b8\uc744 \ud55c \ubc88\uc5d0 \uac00\uc838\uc640\uc57c \ud574. \ud3ec\uc2a4\ud130, \uc6d0\uc81c, \uac1c\ubd09\uc77c, \ub7ec\ub2dd\ud0c0\uc784, \uc7a5\ub974 \ubc30\uc9c0, \uc904\uac70\ub9ac\ub97c \ud45c\uc2dc\ud558\uace0, YouTube Trailer\uac00 \uc788\uc73c\uba74 Modal \ud31d\uc5c5\uc73c\ub85c \uc7ac\uc0dd\ud574\uc918. useNavigate\ub85c \ub4a4\ub85c\uac00\uae30 \ubc84\ud2bc\ub3c4 \ub9cc\ub4e4\uc5b4\uc918. axios \uc778\uc2a4\ud134\uc2a4\ub294 [axios \uacbd\ub85c]\uc5d0\uc11c \uac00\uc838\uc640\uc918.&quot; \uc0ac\uc6a9 \uac00\uc774\ub4dc: [axios \uacbd\ub85c]\ub97c ..\/api\/axios\ub85c \ubc14\uafbc\ub2e4. \uc608\uace0\ud3b8 &#8230; <a title=\"MovieDetail \u2014 \uc601\ud654 \uc0c1\uc138 \ud398\uc774\uc9c0 \ub9cc\ub4e4\uae30\" class=\"read-more\" href=\"https:\/\/coalacoding.com\/?p=82\" aria-label=\"MovieDetail \u2014 \uc601\ud654 \uc0c1\uc138 \ud398\uc774\uc9c0 \ub9cc\ub4e4\uae30\uc5d0 \ub300\ud574 \ub354 \uc790\uc138\ud788 \uc54c\uc544\ubcf4\uc138\uc694\">\ub354 \uc77d\uae30<\/a><\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-82","post","type-post","status-publish","format-standard","hentry","category-react-movie-app"],"_links":{"self":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts\/82","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=82"}],"version-history":[{"count":1,"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts\/82\/revisions"}],"predecessor-version":[{"id":2254,"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts\/82\/revisions\/2254"}],"wp:attachment":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=82"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=82"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=82"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}