본문 바로가기
Tutorial/youtube

18. 나만의 유튜브 사이트 만들기 : 검색 및 유튜브 API 설정하기

by @webstoryboy 2023. 10. 15.
Tutorial/Portfolio

나만의 유튜브 사이트 만들기

by @webs 2023. 09. 01.
18
나만의 유튜브 사이트 만들기 : 검색 및 유튜브 API 설정하기
난이도 중간

소개

안녕하세요! 웹스토리보이입니다. 이 강의는 React 프레임워크와 YouTube API를 이용하여 자신만의 간단한 영상 사이트를 만들어보겠습니다. React의 기본 개념을 이해하고, 컴포넌트를 구조화하고 상태를 관리하는 방법을 학습하게 될 것입니다. 또한 YouTube Data API를 활용하여 외부 데이터를 가져오는 방법을 익히고, API 응답을 처리하여 사용자에게 의미 있는 정보를 제공하는 방법을 이해하게 됩니다. 이로써 자신만의 유튜브 사이트를 만들고, 활용해보는 것을 목표로 합니다. 그럼 한번 시작해볼까요? 🥳

인덱스

  • 1. 셋팅하기
    • 1_1. Node.js 설치
    • 1_2. Vscode 설치
    • 1_3. React.js 설치
  • 2. 라이브러리 설치하기
    • 2_1. 폴더 정리하기
    • 2_2. 라이브러리 설치하기
  • 3. Git 연동하기
    • 3_1. 저장소 만들기
    • 3_2. 모든 파일 올리기
    • 3_3. 깃 상태 확인하기
  • 4. SCSS 셋팅하기
    • 4_1. SCSS 설정하기
    • 4_2. style.scss 설정하기
    • 4_3. fonts.scss 설정하기
    • 4_4. vars.scss 설정하기
    • 4_5. reset.scss 설정하기
    • 4_6. mixin.scss 설정하기
    • 4_7. common.scss 설정하기
  • 5. 페이지 만들기
    • 5_1. 페이지 만들기
    • 5_2. 페이지 컴퍼넌트 만들기
  • 6. 섹션 컴퍼넌트 구조화하기
    • 6_1. 전체 레이아웃 만들기
    • 6_2. 섹션 컴퍼넌트 만들기
  • 7. 헤더 영역 완성하기
    • 7_1. 헤더 영역 구조 잡기
    • 7_2. 헤더 영역 디자인 작업
  • 8. 헤더 영역 데이터 작업
    • 8_1. 헤더 영역 데이터 작업
    • 8_2. 반복문과 map()
    • 8_3. 메뉴 활성화하기
    • 8_4. 컴퍼넌트 세부화 시키기
  • 9. 컴퍼넌트 비동기 작업
    • 8_1. 컴퍼넌트 props 사용하기
    • 8_2. React.Suspense 사용하기
  • 10. 페이지 SEO 작업
    • 10_1. 메인 페이지 SEO 설정하기
    • 10_2. 모든 페이지 SEO 설정하기
  • 11. 메인 콘텐츠 작업
    • 11_1. 검색 컴퍼넌트 작업하기
    • 11_2. 메인 컴퍼넌트 작업하기
  • 12. 추천 영상 작업
    • 12_1. 메인 추천 영상 작업
    • 12_2. 추천 영상 반응형 작업
    • 12_3. 추천 영상 페이지 작업
  • 13. 추천 개발자 작업
    • 13_1. 메인 추천 개발자 작업
    • 13_2. 추천 개발자 페이지 작업
  • 14. 메인 섹션 나머지 콘텐츠 작업
    • 14_1. 웹디자인 기능사 컴퍼넌트 작업
    • 14_2. 웹표준 사이트 컴퍼넌트 작업
    • 14_3. GSAP 사이트 컴퍼넌트 작업
    • 14_4. 포트폴리오 사이트 컴퍼넌트 작업
    • 14_5. 유튜브 사이트 컴퍼넌트 작업
  • 15. 비디오 컴퍼넌트 통합 작업
    • 15_1. 공통 요소 컴퍼넌트 만들기
    • 15_2. Swiper 슬라이드 만들기
    • 15_3. 로딩 효과 넣기
  • 16. Swiper 이미지 슬라이드 작업
    • 16_1. 추천 개발자 이미지 슬라이드 작업
    • 16_2. 추천 개발자 로딩 효과 넣기
    • 16_3. 추천 영상 로딩 및 데이터 작업
  • 17. 나머지 페이지 작업
    • 17_1. 웹디자인 기능사 페이지 작업
    • 17_2. 웹표준 사이트 페이지 작업
    • 17_3. GSAP 페이지 작업
    • 17_4. 포트폴리오 페이지 작업
    • 17_5. 유튜브 페이지 작업
    • 17_6. 추천 개발자 페이지 작업
    • 17_7. 추천 영상 페이지 작업
  • 18. 검색 및 유튜브 API 설정하기
    • 18_1. 검색 영역 설정하기
    • 18_2. 유튜브 API 설정하기
    • 18_3. 유튜브 API 데이터 가져오기

18. 검색 및 유튜브 API 설정하기

18_1. 검색 영역 설정하기

App.js에 검색 페이지를 설정한 적이 있습니다. search 키워드 뒤에 문자열이 오면 ID로 인식합니다. 우선 검색 input 박스부터 설정을 하겠습니다.

우선 components > contents > section > Search.jsx 파일을 수정하겠습니다. 키워드를 입력하고 엔터를 치면 주소에 변경되는 것을 확인할 수 있습니다.

import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'

const Search = () => {
    const [searchKeyword, setSearchKeyword] = useState('');
    const navigate = useNavigate();

    const handleSearch = () => {
        console.log(searchKeyword)
        if (searchKeyword) {
            navigate(`/search/${searchKeyword}`);
            setSearchKeyword('');
        }
    };

    return (
        <div id='search'>
            <div className='search__inner'>
                <label htmlFor='searchInput'>
                    <span className='ir'>검색</span>
                </label>
                <input 
                    type='search' 
                    id='searchInput' 
                    placeholder='검색어를 입력해주세요' 
                    autoComplete='off' 
                    className='search__input' 
                    onChange={e => setSearchKeyword(e.target.value)}
                    onKeyDown={e => {
                        if (e.key === 'Enter') {
                            handleSearch();
                        }
                    }}
                />
            </div>
        </div>
    )
}

export default Search

이 컴포넌트의 목적은 검색 입력 필드를 제공하여 사용자가 입력하고 Enter 키를 누르면 URL의 일부로 검색 키워드를 포함하는 새로운 URL로 이동하는 것입니다. react-router-dom 라이브러리는 클라이언트 사이드 라우팅을 위해 사용되며, 페이지 전체 새로고침 없이 동적으로 URL을 변경할 수 있게 해줍니다

  • useState를 사용하여 searchKeyword라는 상태 변수를 생성하고 초기값을 빈 문자열로 설정합니다. 이 변수는 사용자가 입력한 검색어를 저장합니다.
  • useNavigate 훅을 사용하여 navigate 함수를 가져옵니다. 이 함수는 React Router의 내비게이션을 처리하는데 사용됩니다.
  • handleSearch 함수는 검색 버튼을 클릭하거나 Enter 키를 눌렀을 때 호출됩니다. 먼저, 현재 검색어를 콘솔에 출력합니다(console.log(searchKeyword)). 그런 다음, 검색어가 비어 있지 않은 경우에만 내비게이션을 수행하고 검색어를 초기화합니다.
  • JSX에서는 검색 UI를 렌더링합니다. <input> 엘리먼트를 통해 검색어를 입력할 수 있으며, onChange 이벤트 핸들러를 사용하여 입력된 검색어를 searchKeyword 상태에 업데이트합니다. 또한, Enter 키를 눌렀을 때 검색을 실행하도록 onKeyDown 이벤트 핸들러를 설정합니다.
  • label 엘리먼트는 스크린 리더 사용자를 위한 접근성을 향상시키기 위해 사용되며, 레이블에는 "검색" 아이콘이 포함됩니다.
  • 검색 버튼을 클릭하거나 Enter 키를 누르면 handleSearch 함수가 호출되어 검색을 수행하고, 검색어는 초기화됩니다.

18_2. 유튜브 API 설정하기

youtube api라고 검색을 하고 다음 페이지로 이동하겠습니다. https://developers.google.com/youtube/v3?hl=ko 여기로 이동합니다.

youtube2023

Developer Console에 클릭합니다.

youtube2023

API 및 서비스 사용 설정 버튼을 클릭합니다.

youtube2023

YOUTUBE Data API v3를 클릭합니다.

youtube2023

사용해보기를 누르고 API 키를 받으면 됩니다.

youtube2023

사용자 인증 정보 탭을 클릭하고 인증 정보 만들기 버튼을 클릭합니다. 이렇게 하면 API 키를 만들 수 있습니다.

youtube2023

.env 환경 변수 파일을 만듭니다. 여기에 API 키를 보관하겠습니다. 이 키는 중요하기 때문에 함부로 공유하시면 됩니다. 그렇기 때문에 깃에도 올라가면 안됩니다. .gitignore 파일에 .env 파일을 추가하여 올리는 것을 방지할 것입니다.

  • node_modules
  • public
  • src
  • .env
  • .gitignore
  • package-lock.josn
  • package.josn
  • README.md

.env 파일에는 다음과 같이 작업합니다.

REACT_APP_YOUTUBE_API_KEY=여기에 Youtube API 키를 넣습니다.

.gitignore 파일에는 .env을 추가합니다.

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

18_3. 유튜브 API 데이터 가져오기

유튜브 API를 통해 데이터를 불러오겠습니다. pages 폴더에 Search.jsx 파일을 수정하겠습니다.

import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import Main from '../components/section/Main'

import VideoSearch from '../components/videos/VideoSearch'

const Search = () => {
    const { searchId } = useParams();
    const [ videos, setVideos ] = useState([]);
    
    useEffect(() => {
        fetch(
            `https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=48&q=${searchId}&type=video&key=${process.env.REACT_APP_YOUTUBE_API_KEY}`,
        )
        .then(response => response.json())
        .then(result => {
            console.log(result);
            setVideos(result.items)
        })
        .catch(error => console.log(error));
        }, [searchId]);

    return (
        <Main 
            title = "유투브 검색"
            description="유튜브 검색 결과 페이지입니다.">
            
            <section id='searchPage'>
                <div className="video__inner search">
                    <VideoSearch videos={videos} />
                </div>
            </section>
        </Main>
    )
}

export default Search

이 컴포넌트는 검색 결과를 표시하는 페이지로, YouTube API를 사용하여 검색 결과를 가져와 표시합니다

  • useParams 훅을 사용하여 현재 경로에서 searchId 파라미터를 가져옵니다. 이 파라미터는 사용자가 입력한 검색어를 나타냅니다.
  • useState를 사용하여 videos라는 상태 변수를 생성하고 초기값을 빈 배열로 설정합니다. 이 변수는 검색 결과로 받아온 비디오 목록을 저장합니다.
  • useEffect 훅을 사용하여 컴포넌트가 마운트되거나 searchId가 변경될 때마다 유튜브 API를 호출하여 검색 결과를 가져옵니다. API 호출에는 fetch 함수를 사용하며, 검색어와 API 키를 쿼리 파라미터로 전달합니다. API 응답을 JSON으로 파싱하고, 결과를 setVideos 함수를 사용하여 videos 상태 변수에 저장합니다. API 호출 중에 발생할 수 있는 오류도 처리합니다.
  • JSX에서는 Main 컴포넌트를 사용하여 페이지의 제목과 설명을 설정합니다. 그리고 검색 결과를 표시하기 위해 VideoSearch 컴포넌트를 렌더링합니다. VideoSearch 컴포넌트에는 검색 결과로 받아온 비디오 목록이 전달됩니다.

VideoSearch.jsx 컴퍼넌트는 다음과 같이 작업합니다.

import React from 'react'
import { Link } from 'react-router-dom'

const VideoSearch = ({ videos }) => {
    return (
        <>
            {videos.map((video, index) => (
                <div className="video" key={index}>
                    <div className="video__thumb play__icon">
                        <Link 
                            to={`/video/${video.id.videoId}`} 
                            style={{ backgroundImage: `url(${video.snippet.thumbnails.high.url})` }}>
                        </Link>
                    </div>
                    <div className="video__info">
                        <div className="title">
                            <Link to={`/video/${video.id.videoId}`}>{video.snippet.title}</Link>
                        </div>
                        <div className="info">
                            <span className="author">
                                <Link to={`/channel/${video.snippet.channelId}`}>{video.snippet.channelTitle}</Link>
                            </span>
                        </div>
                    </div>
                </div>
            ))}
        </>
    )
}

export default VideoSearch

CSS도 추가하겠습니다. scss > section > _vidoe.scss 를 추가합니다.

.video__inner.search {
    min-height: 100vh;
    
    .video {
        margin-bottom: 40px;
        border-radius: 10px;
        background-color: #111;

        @media (max-width: 600px){
            margin-bottom: 10px;
        }

        .video__thumb {

            a {
                position: relative;
                display: block;
                cursor: pointer;
                width: 100%;
                padding-bottom: 56.25%;
                position: relative;
                background-size: cover;
                background-position: center;
            }
        }

        .video__info {
            padding: 10px 15px;
            color: #fff;
    
            .title {
                font-size: 1rem;
                @include line-two;
            }
            .info {
                display: flex;
                justify-content: space-between;
                align-items: flex-end;
                
                .author {
                    @include line-one;
                    color: #666;
                    transition: all 0.3s;
    
                    &:hover {
                        color: #fff;
                    }
                }
                .date {
                    font-size: 14px;
                    color: #666;
                }
            }
        }
    }
}

특별한 이상이 없다면 다음과 같이 화면이 구성되고 카테고리 밑에 키워드를 누르면 페이지가 검색 영역이 완성됩니다.

youtube2023

마무리

git 올리기

터미널에서 다음과 같이 작성하겠습니다. 새로운 페이지가 올라오는 것을 확인 할 수 있습니다.

webstoryboyhwang@Webstoryboyui-MacBookPro webs-youtube % git add .
webstoryboyhwang@Webstoryboyui-MacBookPro webs-youtube % git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
        modified:   .gitignore
        modified:   src/assets/scss/section/_video.scss
        modified:   src/components/section/Search.jsx
        new file:   src/components/videos/VideoSearch.jsx
        modified:   src/pages/Search.jsx

webstoryboyhwang@Webstoryboyui-MacBookPro webs-youtube % git commit -m "검색 및 유튜브 API 설정하기"
[main 787cb5e] 검색 및 유튜브 API 설정하기
    5 files changed, 135 insertions(+), 4 deletions(-)
    create mode 100644 src/components/videos/VideoSearch.jsx
webstoryboyhwang@Webstoryboyui-MacBookPro webs-youtube % git push -u origin main
Enumerating objects: 28, done.
Counting objects: 100% (28/28), done.
Delta compression using up to 10 threads
Compressing objects: 100% (15/15), done.
Writing objects: 100% (15/15), 2.98 KiB | 2.98 MiB/s, done.
Total 15 (delta 7), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (7/7), completed with 7 local objects.
To https://github.com/webstoryboy/webs-youtube.git
    c7b9e42..787cb5e  main -> main
branch 'main' set up to track 'origin/main'.

유튜브 API를 이용하여 작업해보았습니다. 유튜브 API는 트래픽이 제한적이기 때문에 다음에는 RapidApi를 이용해서 작업해보겠습니다. 오늘도 수고하셨습니다. 😘


예제 목록

댓글