본문 바로가기
Tutorial/youtube

22. 나만의 유튜브 사이트 만들기 : 버그 고치기

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

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

by @webs 2023. 09. 01.
22
나만의 유튜브 사이트 만들기 : 버그 고치기
난이도 중간

소개

안녕하세요! 웹스토리보이입니다. 이 강의는 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. 추천 영상 페이지 작업
    • 17_8. scrollTo 만들기
  • 18. 검색 및 유튜브 API 설정하기
    • 18_1. 검색 영역 설정하기
    • 18_2. 유튜브 API 설정하기
    • 18_3. 유튜브 API 데이터 가져오기
  • 19. Rapid API 및 더보기 설정하기
    • 19_1. Rapid API 설정하기
    • 19_2. Rapid API 데이터 가져오기
    • 19_3. 검색 데이터 더보기 기능 설정하기
    • 19_4. Loading 소스 설정하기
  • 20. 비디오 상세 페이지 만들기
    • 20_1. 비디오 데이터 불러오기
    • 20_2. 비디오 페이지 반응형 작업
  • 21. 채널 상세 페이지 만들기
    • 21_1. 채널 데이터 불러오기
    • 21_2. 채널 페이지 반응형 작업
    • 21_3. 로딩 기능 추가하기
    • 21_4. 채널 영상 추가하기
    • 21_5. 채널 영상 더보기 구현하기
  • 22. 버그 고치기
    • 22_1. scrollTo 작업하기
    • 22_2. undefined 문제 해결하기
    • 22_3. 모바일 햄버거 메뉴 만들기

22. 버그 고치기

22_1. scrollTo 작업하기

사이트를 보다보면 다음 페이지로 넘어갈 때 사이트가 중간에서 바뀔 때가 있습니다. 새로운 페이지가 열리면 제일 위부터 보여야 하는데 이런 부분이 미흡합니다. 그래서 다음 부분을 추가하겠습니다.

utils > scrollTo.js 파일을 만들겠습니다.

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

const ScrollTo = () => {
    const { pathname } = useLocation();

    useEffect(() => {
        window.scrollTo(0, 0);
    }, [pathname]);

    return null;
};

export default ScrollTo;

components > section > Main.jsx 에 추가합니다.

import React from 'react'
import { Helmet, HelmetProvider } from 'react-helmet-async'

import Header from './Header'
import Footer from './Footer'
import Search from './Search'  
import ScrollTo from '../../utils/scrollTo' // 추가

const Main = ( props ) => {
    return (
        <HelmetProvider>
            <ScrollTo /> // 추가
            <Helmet 
                titleTemplate="%s | Webs Youtube" 
                defaultTitle="Webs Youtube" 
                defer={false}
            >
                {props.title && <title>{props.title}</title>}
                <meta name="description" content={props.description} />
            </Helmet>

            <Header />
            <main id="main" role="main">
                <Search />   
                {props.children}
            </main>
            <Footer />
        </HelmetProvider>
    )
}

export default Main

이 코드는 React 애플리케이션에서 라우팅 변경 시 페이지가 맨 위로 스크롤되도록 하는 React 컴포넌트를 구현한 것입니다. 이 코드는 React와 React Router를 사용하여 작성되었으며, 페이지 경로가 변경될 때마다 useEffect를 사용하여 스크롤 위치를 맨 위로 이동시킵니다

  • import 문 : 코드 상단에 React의 useEffect와 useLocation 훅을, 그리고 React Router의 useLocation 훅을 가져옵니다.
  • ScrollTo 컴포넌트 : 함수형 컴포넌트로 선언되며, 페이지 내의 다른 곳에서 이 컴포넌트를 사용할 수 있습니다.
  • useLocation 훅을 사용하여 현재 페이지의 경로를 가져옵니다. 이 pathname 변수는 현재 페이지의 경로를 나타냅니다.
  • useEffect 훅 : 페이지의 컴포넌트가 렌더링될 때마다 실행되는 부수 효과 함수를 정의합니다. 이 부수 효과 함수는 pathname이 변경될 때마다 실행됩니다.
  • window.scrollTo(0, 0) : useEffect 함수 내에서, window.scrollTo 함수를 호출하여 페이지의 스크롤 위치를 (0, 0)으로 이동시킵니다. 이렇게 하면 페이지의 맨 위로 스크롤이 이동합니다.
  • [pathname] 의존성 배열 : useEffect 함수가 pathname의 변경을 감지하고 그 때에만 실행되도록 하기 위해 의존성 배열에 pathname을 포함시킵니다.
  • return null; : 이 컴포넌트는 화면에 렌더링되는 것이 아니라 스크롤을 조작하는 용도로만 사용됩니다. 따라서 렌더링되는 내용이 없으므로 null을 반환합니다.

22_2. undefined 문제 해결하기

서치를 통해 유튜브 영상을 카드 형식으로 보면 채널 소개가 나오면서 비디오 페이지가 없는 undefined 주소가 나오게 됩니다. 그러면 없는 페이지로 이동하게됩니다. 이부부은 데이터를 불러올 때 채널 페이지를 불러오지 않게 하면 됩니다.

pages > Search.jsx 파일에 수정하겠습니다. 데이터 불러올 때 type=video를 추가해서 해결했습니다.

const fetchVideos = (query, pageToken = '') => {
fetchFromAPI(`search?part=snippet&type=video&q=${query}&pageToken=${pageToken}`)
    .then((data) => {
        setNextPageToken(data.nextPageToken);
        setVideos((prevVideos) => [...prevVideos, ...data.items]);
        setLoading(false);
    })
    .catch((error) => {
        console.error('Error fetching data:', error);
        setLoading(false); 
    });
};

22_3. 모바일 햄버거 메뉴 만들기

반응형을 구현하기 위해서 토글 메뉴를 만들어보겠습니다.

components > section > Header.jsx를 수정하겠습니다.

import React, { useState } from 'react'

import Logo from '../header/Logo';
import Menu from '../header/Menu';
import Sns from '../header/Sns';

const Header = () => {
    const [ isMenuActive, setIsMenuActive ] = useState(false);

    const toggleMenu = () => {
        setIsMenuActive(!isMenuActive);
    }

    return (
        <header id='header' role='banner' className={isMenuActive ? 'active' : ''}>
            <Logo toggleMenu={toggleMenu} />
            <Menu />
            <Sns />
        </header>
    )
}

export default Header

header > Logo.jsx 는 다음과 같이 수정합니다.

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

const Logo = ({ toggleMenu }) => {
    return (
        <h1 className='header__logo'>
            <Link to='/'>
                <em aria-hidden='true' onClick={toggleMenu}></em>
                <span>webs<br />youtube</span>
            </Link>
        </h1>
    )
}

export default Logo

assets > scss > _layout.scss를 수정합니다.

@media (max-width: 800px){
    #header {
        left: -260px;
        background-color: var(--black);
        transition: left 0.3s;

        h1 {
            position: fixed;
            left: 0;
            top: 0;
        }
        .header__menu {
            margin-top: 90px;
        };
        &.active {
            left: 0;
        }
    }
    #main {
        padding-left: 0;
    }
    #footer {
        width: 100%;
        margin-left: 0;
    }
}

마무리

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 ..." to unstage)
        modified:   src/assets/scss/section/_video.scss
        modified:   src/pages/Video.jsx

webstoryboyhwang@Webstoryboyui-MacBookPro webs-youtube % git commit -m "비디오 상세 페이지 만들기"
[main 0c967e9] 비디오 상세 페이지 만들기
    2 files changed, 108 insertions(+), 3 deletions(-)
webstoryboyhwang@Webstoryboyui-MacBookPro webs-youtube % git push -u origin main
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Delta compression using up to 10 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 1.90 KiB | 1.90 MiB/s, done.
Total 9 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (6/6), completed with 6 local objects.
To https://github.com/webstoryboy/webs-youtube.git
    f818a8a..0c967e9  main -> main
branch 'main' set up to track 'origin/main'.

비디오 상세 페이지에는 이 데이터 뿐만 아니라 댓글이나 연관 영상들도 만들 수 있습니다. 같이 해보지는 않겠지만 혼자서 도전하는 습관도 중요합니다. 한번 도전해보세요! 오늘도 수고하셨습니다. 😘


예제 목록

댓글