웹(WEB)/자바스크립트(JS)

자바스크립트 Axios API 호출 async/await 비동기 작업 웹사이트 구현

마달랭 2024. 8. 7. 15:26
반응형

개요

async/await

  • Promise를 쉽게 사용하기위해 ES8에 도입
  • async는 함수 앞에 위치.
  • await는 async 함수 내부에 위치.
  • promise를 반환한다
  • 비동기 코드를 동기적으로 작성한다

사용 방법

  1. async 선언된 함수를 만든다.
  2. try/catch를 통해 예외 처리를 해준다. (선택)
  3. try 안에 실제로 호출할 비동기 함수(통신 등)을 넣는다.
  4. 비동기 함수 앞에 await를 넣어준다.
  5. 만든 함수를 호출한다.

 

예제

1. async/await를 사용하여 데이터 받아오기

코드

//<script src="https://unpkg.com/axios/dist/axios.min.js"></script> 추가 해주기

const url = "https://jsonplaceholder.typicode.com/todos/";

async function start() {
    try {
        const result = await axios.get(url);
        console.log(result.data);
    } catch (error) {
        console.log(error);
    }
}

start();

 

출력

 

실습

1. Playlist를 추천해 주는 웹사이트 만들기

https://console.cloud.google.com/welcome?authuser=2&project=psychic-rhythm-378805 해당 링크에서Youtube data api v3" 검색하여 API키를 발급 받고, axios를 활용하여 유튜브의 API를 가져와 나만의 웹사이트를 만들어 보자

 

Google 클라우드 플랫폼

로그인 Google 클라우드 플랫폼으로 이동

accounts.google.com

 

 

코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <style>
        header{
            font-size: 30px;
            font-weight: bold;
            text-align: center;
            margin: 20px;
            border: 5px solid black;
            padding: 20px;
        }
        .radio-container{
            margin: 50px;
            display: flex;
            justify-content: space-evenly;
        }
        .radio-btn{
            font-weight: bold;
        }
        .video-container{
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
        }
        .items{
            margin: 10px;
            width: 320px;
            height: 300px;
        }
        a {
            text-decoration: none;
            color: inherit;
        }

    </style>
</head>
<body>
    <header>
        집중력 향상을 위한 Playlist 모음
    </header>
    <main>
        <div class="radio-container">
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="rainyDay music"> 비오는 날
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="travel music"> 놀러 가고 싶은 날
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="energy music"> 에너지가 필요한 날
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="game constration music"> 게임에 집중
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="miss home music"> 고향생각이 날때
            </div>
        </div>
        <div class="video-container">
        </div>
    </main>
    <script>
        let btn_indexs = document.querySelectorAll(".chk");
        btn_indexs.forEach((e) => {
            e.addEventListener('change', () => {
                while (container.firstChild) {
                    container.removeChild(container.firstChild);
                }
                getData(e.id);
            })
        })

        const url = "https://www.googleapis.com/youtube/v3";
        const key = "본인의 유튜브 API키 입력";
        const container = document.querySelector(".video-container");
        async function getData(word) {
            try {
                const responce = await axios.get(`${url}/search`, {
                    params: {
                        key: key,
                        part: "snippet",
                        type: "video",
                        q: word,
                        maxResults: 10,
                    },
                });
                console.log(responce.data.items);
                let result = responce.data.items.reduce((acc, cur) => {
                    acc += getComponents(cur);
                    return acc;
                }, "");
                container.insertAdjacentHTML('beforeend', result);
            } catch (error) {
                console.error(error);
            }
        }
        function getComponents(data) {
            return `
            <div class="items">
                <a href="https://www.youtube.com/watch?v=${data.id.videoId}">
                    <img src="${data.snippet.thumbnails.medium.url}" alt="">
                    <div>${data.snippet.title}</div>
                </a>
            </div>
            `
        }
    </script>
</body>
</html>

 

결과

radio 버튼의 각 id를 유튜브 검색어로 활용하였고, 각 버튼에 change 이벤트 리스너를 추가해 줘 체크가 변경될 경우 출력한 목록을 모두 지운 뒤 검색어에 알맞은 목록을 다시 노출시킨다.

 

axios를 통해 API 정보를 받아온 후 각 목록에 대한 배열을 reduce를 통해 순회 한 뒤 HTML 코드를 백틱으로 작성 후 insertAdjacentHTML를 통해 div내로 넘겨주었다.

 

이후 적당한 style을 적용해주고, 해당 요소를 클릭 시 관련 유튜브 채널로 이동하도록 설정하였다. iframe을 통해 구현하게 된다면 페이지 이동 없이 영상 플레이가 가능하다.

 

2. 영화 정보를 알려주는 사이트 만들기

https://www.themoviedb.org/ 에 가입하여 API 발급 받고 데이터를 가공하여 영화 정보를 알려주는 사이트를 만들어 보자

API에 대한 자세한 내용은 https://developers.themoviedb.org/3 해당 사이트를 참고하면 된다.

 

Getting Started

Welcome to version 3 of The Movie Database (TMDB) API. This is where you will find the definitive list of currently available methods for our movie, tv, actor and image API.

developer.themoviedb.org

 

 

The Movie Database (TMDB)

환영합니다 수백만 개의 영화, TV 프로그램 및 인물을 발견하세요. 지금 살펴보세요.

www.themoviedb.org

 

코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <style>
        header{
            font-size: 30px;
            font-weight: bold;
            text-align: center;
            margin: 20px;
            border: 5px solid black;
            padding: 20px;
            color:black;
            background-color: white;
        }
        .radio-container{
            margin: 50px;
            display: flex;
            justify-content: space-evenly;
        }
        .radio-btn{
            font-weight: bold;
        }
        .movie-container{
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
        }
        .items{
            margin: 10px;
            width: 240px;
            height: 450px;
        }
        a {
            text-decoration: none;
            color: inherit;
        }
        body {
            background-color: black;
            color: white;
        }

    </style>
</head>
<body>
    <header>
        영화 정보 특공대 출격!
    </header>
    <main>
        <div class="radio-container">
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc&with_release_type=2|3&release_date.gte={min_date}&release_date.lte={max_date}"> 현재 상영중
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc"> 인기 순
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="https://api.themoviedb.org/3/movie/top_rated"> 평점 높은 순
            </div>
            <div class="radio-btn">
                <input class="chk" type="radio" name="music" id="https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc&with_release_type=2|3&release_date.gte={min_date}&release_date.lte={max_date}"> 최신순
            </div>
        </div>
        <div class="movie-container">
        </div>
    </main>
    <script>
        const baseUrl = "https://image.tmdb.org/t/p/w500";
        let btn_indexs = document.querySelectorAll(".chk");
        btn_indexs.forEach((e) => {
            e.addEventListener('change', () => {
                while (container.firstChild) {
                    container.removeChild(container.firstChild);
                }
                options.url = e.id;
                getMovie();
            })
        })
        const container = document.querySelector(".movie-container");
        let options = {
            method: 'GET',
            url: '',
            params: {language: 'ko-KR', page: '1'},
            headers: {
                accept: 'application/json',
                Authorization: 'Bearer 본인의 key를 입력'
            }
        }
        async function getMovie() {
            axios
            .request(options)
            .then(function (response) {
                console.log(response);
                const html = response.data.results.reduce((acc, cur) => {
                    acc += getComponents(cur);
                    return acc;
                },"");
                container.insertAdjacentHTML('beforeend', html);
            })
            .catch(function (error) {
                console.error(error);
            });
        }
        
        function getComponents(data) {
            return `
            <div class="items">
                <a href="https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=${data.title}">
                    <img width="240px" height="320px" src="${baseUrl}${data.poster_path}" alt="">
                    <div>${data.title}</div>
                    <div>평점 : ${Math.round(data.vote_average, 1)}</div>
                    <div>추천 수 : ${data.vote_count}</div>
                    <div>개봉일 : ${data.release_date}</div>
                </a>
            </div>
            `
        }
    </script>
</body>
</html>

 

결과

 

1번과 마찬가지로 axios를 통해 themoviedb 사이트에서 API를 호출하여 포스터 이미지, 영화 제목, 평점, 추천 수, 개봉일 등에 대한 데이터를 파싱해 온 뒤 reduce를 활용하여 각 요소에 대해 HTML 폼을 만든 후 전체 폼을 백틱으로 만들어 insertAdjacentHTML을 통해 body안으로 넣어주었다.

 

다크 모드를 구현하고 싶어 적당한 style을 입혀 주었고 영화 정보를 클릭하면 네이버 검색으로 이동하게 링크 처리를 해놓았다.

728x90
반응형