본문 바로가기
Tutorial/youtube2023

07. 나만의 유튜브 사이트 만들기 : 추천 개발자 콘텐츠 만들기

by @webstoryboy 2023. 9. 4.
Tutorial/Portfolio

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

by @webs 2023. 09. 01.
07
나만의 유튜브 사이트 만들기 : 추천 개발자 콘텐츠 만들기
난이도 중간

소개

안녕하세요! 웹스토리보이입니다. 이번에는 메인페이지의 메인 컨텐츠를 만들어 보겠습니다. 메인에는 오늘의 추천영상, 개발자 소개 및 영상 소개를 보여주는 부분입니다. 그럼 한번 시작해보겠습니다.😝

인덱스

  • 1. 셋팅하기
    • 1_1. Node.js 설치
    • 1_2. Vscode 설치
    • 1_3. React.js 설치
    • 1_4. 폴더 정리하기
    • 1_5. 필요한 파일 설치하기
  • 2. CSS 셋팅하기
    • 2_1. SCSS 설정하기
    • 2_2. style.scss 설정하기
    • 2_3. fonts.scss 설정하기
    • 2_4. vars.scss 설정하기
    • 2_5. reset.scss 설정하기
    • 2_6. mixin.scss 설정하기
    • 2_7. common.scss 설정하기
  • 3. 페이지 및 컴퍼넌트 만들기
    • 3_1. 페이지 만들기
    • 3_2. 컴퍼넌트 만들기
  • 4. 섹션 컴퍼넌트 만들기
    • 4_1. Main 컨퍼넌트 만들기
    • 4_2. Header 컨퍼넌트 만들기
    • 4_3. Header 컨퍼넌트 데이터화 하기
    • 4_4. Footer 컨퍼넌트 만들기
  • 5. 페이지 SEO 작업
    • 5_1. App.js 재구성
    • 5_2. main 컴퍼넌트 재구성
    • 5_3. 모든 페이지 재구성
  • 6. 메인 콘텐츠 만들기
    • 6_1. 검색 컴퍼넌트 작업
    • 6_2. 오늘의 영상 컴퍼넌트 작업
    • 6_3. 오늘의 영상 페이지 작업
  • 7. 추천 개발자 콘텐츠 만들기
    • 7_1. 메인 추천 개발자 섹션 작업
    • 7_2. 추천 개발자 페이지 작업
    • 7_3. 추천 개발자 섹션 슬라이드 작업

7. 추천 개발자 콘텐츠 만들기

7_1. 메인 추천 개발자 섹션 작업

Home.jsx 페이지에서 Developer 컴퍼넌트를 추가하겠습니다.

import React from 'react'
import Main from '../components/section/Main'

import Today from '../components/contents/Today'
import Developer from '../components/contents/Developer'

const Home = () => {
    return (
        <Main 
            title = '웹스토리보이 유튜브'
            description='웹스토리보이 유튜버에 오신 것을 환영합니다.'>
            
            <Today />
            <Developer />
        </Main>
    )
}

export default Home

components 폴더 contents 폴더에 Developer 컴퍼넌트를 만들겠습니다.

import React from 'react'

import { developerText } from '../../data/developer';
import { Link } from 'react-router-dom';

const Developer = () => {
    return (
        <section id='developer'>
            <h2>😪 추천 개발자를 소개합니다.</h2>
            <div className="develpoer__inner overflow">
                {developerText.map((developer, key) => (
                    <div className="develpoer" key={key}>
                        <div className="develpoer__img play__icon">
                            <Link to={`/channel/${developer.channelId}`}>
                                <img src={developer.img} alt={developer.name} />
                            </Link>
                        </div>
                        <div className="develpoer__info">
                            <Link to={`/channel/${developer.channelId}`}>
                                {developer.name}
                            </Link>
                        </div>
                    </div>
                ))}
            </div>
        </section>
    )
}

export default Developer

data 폴더에 developer.js 파일을 만들겠습니다.

export const developerText = [
    {
        img: "https://yt3.googleusercontent.com/JU6k565OVstxx_h_7TbzE1aNXKzcxKl33zjPV4p649pqsgS7E3vb0meX9DB1_D_KviDoc4xM=s176-c-k-c0x00ffffff-no-rj",
        name: "webstoryboy",
        channelAddress: "https://www.youtube.com/@webstoryboy",
        channelId: "UCsvQSv7EeCMHyYb9ENKAJZw"
    },
    {
        img: "https://yt3.googleusercontent.com/JuRcVt9OFQgqh7UL1LjihpVLEbjdNXt3tGq-IQfqRMT8wVXgWg_tzyz0S_GVsgqkB3ucBC5fqeY=s176-c-k-c0x00ffffff-no-rj",
        name: "조코딩 JoCoding",
        channelAddress: "https://www.youtube.com/@jocoding",
        channelId: "UCQNE2JmbasNYbjGAcuBiRRg"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaSNRWU5nI-gDyzEdtbhpLqWg8wXNs-FQHf35iMCOw=s176-c-k-c0x00ffffff-no-rj",
        name: "생활코딩",
        channelAddress: "https://www.youtube.com/@coohde",
        channelId: "UCvc8kv-i5fvFTJBFAk6n1SA"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaSn88PvVXWN_Wy5vSr-5Eo_NGDdw_apL6bM7QKfCw=s176-c-k-c0x00ffffff-no-rj",
        name: "노마드 코더 Nomad Coders",
        channelAddress: "https://www.youtube.com/@nomadcoders",
        channelId: "UCUpJs89fSBXNolQGOYKn0YQ"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaSeGpiSPyozdunhf74J4oa2XWHPObm8bKTcbEU=s176-c-k-c0x00ffffff-no-rj",
        name: "코딩하는거니",
        channelAddress: "https://www.youtube.com/@gunnycoding",
        channelId: "UCO7g158NWgLyn98z8v3zduA"
    },
    {
        img: "https://yt3.googleusercontent.com/iofg4f6THo3jyeap1GC23g5qsKD-w62Lu4U9EJBmZe8YtM1NhbNWz4WiyICAXXmwrgbnUh-FNQ=s176-c-k-c0x00ffffff-no-rj",
        name: "워니코딩",
        channelAddress: "https://www.youtube.com/@WonieSong",
        channelId: "UC0uDM1xZMNBAoW2xnzhAQ7g"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaRCkXnBnWEMfpo5c_TXB-tF0FxqiCfv5KoP_9IBC6A=s176-c-k-c0x00ffffff-no-rj",
        name: "얄팍한 코딩사전",
        channelAddress: "https://www.youtube.com/@yalco-coding",
        channelId: "UC2nkWbaJt1KQDi2r2XclzTQ"
    },
    {
        img: "https://yt3.googleusercontent.com/oLi5jJ2AKs_aYpR9UpUpu052M84WIE2j9cpnNb1VnpBHZMHVrTRPwrUIncJGu6--PVR-x-22=s176-c-k-c0x00ffffff-no-rj",
        name: "개발하는 정대리",
        channelAddress: "https://www.youtube.com/@dev_jeongdaeri",
        channelId: "UCutO2H_AVmWHbzvE92rpxjA"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaTw2ZRRi6UzhNeunJh03HOeAnKScgRJygpN7_MsVQ=s176-c-k-c0x00ffffff-no-rj",
        name: "코딩애플",
        channelAddress: "https://www.youtube.com/@codingapple",
        channelId: "UCSLrpBAzr-ROVGHQ5EmxnUg"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaRfTsQsimyyMrWugbbogh_EdsCWWQsKVqh5Fdvq=s176-c-k-c0x00ffffff-no-rj",
        name: "김왼손의 왼손코딩",
        channelAddress: "https://www.youtube.com/@leftykhim",
        channelId: "UC0h8NzL2vllvp3PjdoYSK4g"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaSXgyXVlJGDyr1IaQgHJlGvc4wcFcZJ4S35NATdrYA=s176-c-k-c0x00ffffff-no-rj",
        name: "제주코딩베이스캠프",
        channelAddress: "https://www.youtube.com/@jejucodingcamp",
        channelId: "UC4GnvNKtuJ4cqWsYjxNxAEQ"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaQyV-QwNnxxLKCnfHZrfsGNx7fqFD9YSQ_lweIx6w=s176-c-k-c0x00ffffff-no-rj",
        name: "나도코딩",
        channelAddress: "https://www.youtube.com/@nadocoding",
        channelId: "UC7iAOLiALt2rtMVAWWl4pnw"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaTiHU0ol325VdijS5AX4DQomGs6zlD_y_v0I0A6=s176-c-k-c0x00ffffff-no-rj",
        name: "라매개발자",
        channelAddress: "https://www.youtube.com/@lamedev",
        channelId: "UCr3lkp7TJiJTCY4ffRQ1m2A"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaSnppVkSh38WlQrn-7FzBAqlJpMLdGq4jS2GGHzgQ=s176-c-k-c0x00ffffff-no-rj",
        name: "드림코딩",
        channelAddress: "https://www.youtube.com/@dream-coding",
        channelId: "UC_4u-bXaba7yrRz_6x6kb_w"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaTyIgb-N-SeFznHEn_RkJkF9IirgzvXtEoWOnNt=s176-c-k-c0x00ffffff-no-rj",
        name: "ZeroCho TV",
        channelAddress: "https://www.youtube.com/@ZeroChoTV",
        channelId: "UCp-vBtwvBmDiGqjvLjChaJw"
    },
    {
        img: "https://yt3.googleusercontent.com/x5DWPPquVbSkeJ-UCVuPfnd6nzbkSCkSaXuxRUnD1yGYWixNPErHqMQP4bhP6M86oQcH7pcm=s176-c-k-c0x00ffffff-no-rj",
        name: "짐코딩 GYM CODING",
        channelAddress: "https://www.youtube.com/@gymcoding",
        channelId: "UCZ30aWiMw5C8mGcESlAGQbA"
    },
    {
        img: "https://yt3.googleusercontent.com/PVbwh8OLmp3dTofJ7vmv6zfoRKiFgIvL9SsTYaermGxW3Ga6vONSfC7ymrgpO6gUCd9nKcZp0Sc=s176-c-k-c0x00ffffff-no-rj",
        name: "프롱트",
        channelAddress: "https://www.youtube.com/@frongt",
        channelId: "UCku8mOp8y05Cm6sb9Rp0jMQ"
    },
    {
        img: "https://yt3.googleusercontent.com/1gLFRSPxZUYjlGG-Ap7B2bymZkdp4fFuSTAntouex6mdUQUZ2lA8kWMrzKOLHAdfkzjopcntU7E=s176-c-k-c0x00ffffff-no-rj",
        name: "프로그래머 김플 스튜디오",
        channelAddress: "https://www.youtube.com/@kimfl",
        channelId: "UCdNSo3yB5-FRTFGbUNKNnwQ"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaToAOoB7zZaRe9kVmXGi6QWBBPrESpK8pcaWnBL=s176-c-k-c0x00ffffff-no-rj",
        name: "Lama Dev",
        channelAddress: "https://www.youtube.com/@LamaDev",
        channelId: "UCOxWrX5MIdXIeRNaXC3sqIg"
    },
    {
        img: "https://yt3.googleusercontent.com/4RM7sEvMAp5QokwqBbcQh9_XD53E2PGrfwCClaqT_IAL2FnIzWqxyBN3JuPKMas-dL0do9t-=s176-c-k-c0x00ffffff-no-rj",
        name: "JS Dev Hindi",
        channelAddress: "https://www.youtube.com/@jsdevhindi",
        channelId: "UCRJz8FP29yq_vA5h08dXMPw"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaQneLC0nfXjK4QaNPSG1lZXCUZtuhoFdBtYz1hH=s176-c-k-c0x00ffffff-no-rj",
        name: "코딩알려주는누나",
        channelAddress: "https://www.youtube.com/@user-yu8so2ck1z",
        channelId: "UCfBvs0ZJdTA43NQrnI9imGA"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaQxJlRUxIrCv4zw_kfUsqKHAm1rN32SHAU8Iwla=s176-c-k-c0x00ffffff-no-rj",
        name: "동빈나",
        channelAddress: "https://www.youtube.com/@dongbinna",
        channelId: "UChflhu32f5EUHlY7_SetNWw"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaQZENEAuTWosc8r89GoegTvvjKzdEgBXMv7C4i4=s176-c-k-c0x00ffffff-no-rj",
        name: "EdRoh",
        channelAddress: "https://www.youtube.com/@EdRohDev",
        channelId: "UCMoEx7gz7IbJHv733yEi2aA"
    },
    {
        img: "https://yt3.googleusercontent.com/wg1TITEoPfxvBGfzuqWyt3bqm_qu35ZhMswUv3feetU3xNX_6wsAXZF40OlPIgY4TmqbqCmAZ1U=s176-c-k-c0x00ffffff-no-rj",
        name: "JavaScript Mastery",
        channelAddress: "https://www.youtube.com/@javascriptmastery",
        channelId: "UCmXmlB4-HJytD7wek0Uo97A"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaTs1IEit9EUooQAJkWS4SkpUE7oMDXYrjIgnOk1Kw=s176-c-k-c0x00ffffff-no-rj",
        name: "freeCodeCamp.org",
        channelAddress: "https://www.youtube.com/@freecodecamp",
        channelId: "UC8butISFwT-Wl7EV0hUK0BQ"
    },
    {
        img: "https://yt3.googleusercontent.com/kVYpCZYEfX0_b2_Y7SROJsLahriQfOf6rW4egbSxDGWHDLiqhFcPM8eL56EKYfgjzetQQRx7fA=s176-c-k-c0x00ffffff-no-rj",
        name: "How to Become a Developer",
        channelAddress: "https://www.youtube.com/@howtobecomeadeveloper",
        channelId: "UCkXqOdpo5ul8BosGBFlDgmw"
    },
    {
        img: "https://yt3.googleusercontent.com/O8iON5EAVx6HVKyOV5UMreLFI_0D3mJX373vTEGoNcVRpNP7Lq8swha7BSLWTiEWlZaF7a4ENW8=s176-c-k-c0x00ffffff-no-rj",
        name: "Code With Antonio",
        channelAddress: "https://www.youtube.com/@codewithantonio",
        channelId: "UCW_4e6sUTMWHxlF06aErH9w"
    },
    {
        img: "https://yt3.googleusercontent.com/nwyG0ql8sxARogaFb3sgpjoNd86v7hL9W2eeEysP2LryigBtYtX-J2Mw9H1lpcB9D4sw0aCx9w=s176-c-k-c0x00ffffff-no-rj",
        name: "EGATOR",
        channelAddress: "https://www.youtube.com/@EGATORTUTORIALS",
        channelId: "UCL8l_VxCAN0jOpaLaRAm8sQ"
    },
    {
        img: "https://yt3.googleusercontent.com/a3vK_ZCS_QUX19CV2Xx1RY-CgR7DQzpeWk14UFbKdDv0Ryjc_FPf6Uo4-8NPi34deUay87eusQ=s176-c-k-c0x00ffffff-no-rj",
        name: "빔캠프 CSS",
        channelAddress: "https://www.youtube.com/@veamcamp",
        channelId: "UCvx57s_ZBt5VG4fvlStiq2g"
    },
    {
        img: "https://yt3.googleusercontent.com/wr8dNnJ8dSHjBsHKag3O6ZCKmxJvnxqhpPi-E6sWf83JYKxnevU2iSt3FzLxjzrZOCTRpbi53mg=s176-c-k-c0x00ffffff-no-rj",
        name: "코딩카페1",
        channelAddress: "https://www.youtube.com/@CodingCafe1",
        channelId: "UCt76J5CYnXL-uoJmQPG2Azw"
    },
    {
        img: "https://yt3.googleusercontent.com/AVa5OPep1y0E8bZMIyLDyzg1jTwApHaSCi2RUG0epuLFZe0e80yvYo7MNHd-ApnvOtDgT3A3=s176-c-k-c0x00ffffff-no-rj",
        name: "Codegrid",
        channelAddress: "https://www.youtube.com/@codegrid",
        channelId: "UC7pVho4O31FyfQsZdXWejEw"
    },
    {
        img: "https://yt3.googleusercontent.com/wgnEbc2Ec2JYkeyzUbiHzDlAFObI2Btwo2YRCEF1aCMBiRc5E_zWy8-URBQS3EMQ1yzzaGFR=s176-c-k-c0x00ffffff-no-rj",
        name: "Kishan Sheth",
        channelAddress: "https://www.youtube.com/@KishanSheth21",
        channelId: "UCDT8sIFy3pW8LT6SAbe8xtQ"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaTc-hNjbGDnft48nMktaKF87D8EmpZ9Oacc4XeTew=s176-c-k-c0x00ffffff-no-rj",
        name: "Yuri Artiukh",
        channelAddress: "https://www.youtube.com/@akella_",
        channelId: "UCDo7RTzizoOdPjY8A-xDR7g"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaQOeqOOHYrdr9qaOxYqujnMoTvladljn12PeOdeVA=s176-c-k-c0x00ffffff-no-rj",
        name: "디자인베이스",
        channelAddress: "https://www.youtube.com/@designbase",
        channelId: "UCvYnDMeL-PFZhfIz6oc_U-Q"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaRq6HIiAsf1pv1CHAlIIM6MdbnaX0jqpTCOyIM5TA=s176-c-k-c0x00ffffff-no-rj",
        name: "야무",
        channelAddress: "https://www.youtube.com/@yamoo9",
        channelId: "UCTZRL_OwTjiXYoTjwWg4bww"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaTtbptu4ao5lFu3ElFN61tMr1K0pvo8zd7qw7HeFw=s176-c-k-c0x00ffffff-no-rj",
        name: "DesignCourse",
        channelAddress: "https://www.youtube.com/@DesignCourse",
        channelId: "UCVyRiMvfUNMA1UPlDPzG5Ow"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaR892c9LcaLOEfzAp80Nna198A4lte69Z80LV-2ug=s176-c-k-c0x00ffffff-no-rj",
        name: "Code with Ania Kubów",
        channelAddress: "https://www.youtube.com/@AniaKubow",
        channelId: "UC5DNytAJ6_FISueUfzZCVsw"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaR0SDrl59HyNkJotnB41HBsVLXDUaRMbKFRJIIoJQ=s176-c-k-c0x00ffffff-no-rj",
        name: "Coding Artist",
        channelAddress: "https://www.youtube.com/@CodingArtist",
        channelId: "UC15exV5s79D_aYGADudlwpQ"
    },
    {
        img: "https://yt3.googleusercontent.com/ytc/AOPolaRbhQtG_1StOoOn0z0pfDfAFoe86Gk_kkR1OPhYVg=s176-c-k-c0x00ffffff-no-rj",
        name: "Rock's Easyweb",
        channelAddress: "https://www.youtube.com/@Ezweb",
        channelId: "UCax1DP6hqZowNWF2lquKk0w"
    }
]

scss 폴더 section 폴더에 _developer.scss을 추가하고 작업하겠습니다.

.develpoer__inner {
    display: flex;
    color: #fff;
    flex-wrap: wrap;

    .develpoer {
        color: #fff;
        text-align: center;
        margin-right: 20px;

        .develpoer__img {
            display: block;
            width: 150px;
            height: 150px;
            border-radius: 50%;
            overflow: hidden;
            margin-bottom: 10px;
        }
        .develpoer__info {
            width: 150px;
            text-align: center;
            @include line-one;
            padding-bottom: 40px;
        }
    }
}

다음과 같이 개발자 섹션이 완성됩니다.

youtube2023

7_2. 추천 개발자 페이지 작업

이번에는 페이지에서 데이터를 불러오도록 하겠습니다. pages 폴더에 Developer.jsx를 다음과 같이 수정하겠습니다.

import React from 'react'
import Main from '../components/section/Main'

import { developerText } from '../data/developer'
import { Link } from 'react-router-dom'

const Developer = () => {
    return (
        <Main 
            title = "추천 개발자"
            description="오늘의 추천 개발자 유튜버입니다.">
            
            <section id='developerPage'>
                <h2>🥰 오늘의 추천 개발자입니다.</h2>
                <div className="develpoer__inner">
                    {developerText.map((developer, key) => (
                        <div className="develpoer" key={key}>
                            <div className="develpoer__img play__icon">
                                <Link to={`/channel/${developer.channelId}`}>
                                    <img src={developer.img} alt={developer.name} />
                                </Link>
                            </div>
                            <div className="develpoer__info">
                                <Link to={`/channel/${developer.channelId}`}>
                                    {developer.name}
                                </Link>
                            </div>
                        </div>
                    ))}
                </div>
            </section>
        </Main>
    )
}

export default Developer

7_3. 추천 개발자 섹션 슬라이드 작업

이번에는 Swiper를 이용하여 이미지 슬라이드를 구현하겠습니다. contents 폴더에 Developer.jsx 파일을 다음과 같이 변경하겠습니다.

import React from 'react'

import { developerText } from '../../data/developer';
import { Link } from 'react-router-dom';

import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/pagination';
import 'swiper/css/navigation';

import { Navigation, Autoplay } from 'swiper/modules';

const Developer = () => {
    return (
        <section id='developer'>
            <h2>😪 추천 개발자를 소개합니다.</h2>
            <div className='develpoer__inner'>
                <Swiper
                    slidesPerView={4}
                    spaceBetween={15}
                    navigation={true}
                    autoplay={{
                        delay: 5000,
                        disableOnInteraction: false,
                    }}
                    breakpoints={{
                        640: {
                            slidesPerView: 5,
                            spaceBetween: 15,
                        },
                        768: {
                            slidesPerView: 6,
                            spaceBetween: 15,
                        },
                        1024: {
                            slidesPerView: 7,
                            spaceBetween: 20,
                        },
                        1240: {
                            slidesPerView: 8,
                            spaceBetween: 20,
                        },
                        1640: {
                            slidesPerView: 9,
                            spaceBetween: 20,
                        },
                        2000: {
                            slidesPerView: 10,
                            spaceBetween: 20,
                        },
                    }}
                    modules={[Navigation, Autoplay]}
                    className='mySwiper'
                >
                    {developerText.map((developer, key) => (
                        <SwiperSlide key={key}>
                            <div className='develpoer' key={key}>
                                <div className='develpoer__img play__icon'>
                                    <Link to={`/channel/${developer.channelId}`}>
                                        <img src={developer.img} alt={developer.name} />
                                    </Link>
                                </div>
                                <div className='develpoer__info'>
                                    <Link to={`/channel/${developer.channelId}`}>
                                        {developer.name}
                                    </Link>
                                </div>
                            </div>
                        </SwiperSlide>
                    ))}
                </Swiper>
            </div>
        </section>
    )
}

export default Developer

마무리

swiper를 이용하여 자동 플레이도 설정하고 반응형도 완료하였습니다. 수고하셨습니다. 😲


예제 목록

댓글