sbyeol3/articles

[번역] 당신이 아직 알지 못하는 JavaScript API

Opened this issue · 0 comments

원문 JavaScript APIs You Don’t Know About

요약: 이 아티클에서는, Juan Diego씨가 Page Visibility API, Web Sharing API, Broadcast Channel API 그리고 Internationalization API와 같이 덜 알려졌지만 아주 유용한 API들을 다룹니다. 어떤 API인지 살펴보면서, 언제 어떻게 사용해야 하는지 알아봅시다.

며칠 전, 저는 아주 멋진 2021 State of JS Survey 사이트를 다시 방문했습니다. The state of JS는 전세계 개발자로부터 데이터를 모아 자바스크립트 커뮤니티의 최근과 향후의 트렌드를 확인하기 위한 온라인 설문입니다. 여기서 수집한 데이터 중 하나는 JavaScript가 제공하는 네이티브 기능에 대한 섹션인데 개발자들의 사용법과 인식 정도로 나열됩니다. 여러분도 예상할 수 있듯이 가장 잘 사용되는 기능들은 Optional chaining, Nullish coalescing, Websockets 등 이었습니다.

그렇지만 저는 이미 잘 사용되고 알려져 있는 API들에 관심이 가진 않았습니다. 저는 덜 알려진 것들을 찾고 있었습니다. 우리가 충분히 이야기하지 않고 있는 API들이 무엇인지 알고 싶었고 그 중에서 아주 유용한 4가지 API를 찾았습니다.

이 글에서는 이 API들이 무엇이고, 언제 사용해야 하며, 어떻게 사용해야 하는지 알게 됩니다.

참고: 이 API들은 이 데모에서 사용할 수 있어요.

Page Visibility API

이 API는 State of JS Survey에서 4개의 API 중에 가장 덜 알려진 API입니다. 사용자가 페이지를 떠났을 때를 여러분들에게 알려주는 역할을 합니다. 정확히 말하면, 유저가 윈도우 창을 줄이거나 키우거나 또는 탭을 전환할 때와 같은 페이지 가시성 상태가 변경될 때 이벤트를 트리거 합니다.

과거에는 유저가 탭을 전환하거나 윈도우를 줄일 때를 알고 싶었다면 특정한 전략을 사용해야 했습니다. 가장 유명한 전략은 blurfocus 브라우저 이벤트를 사용하는 것이었죠. 이 이벤트들을 활용하면 아래와 같은 결과를 얻을 수 있습니다.

window.addEventListener("focus", function () {
    // User is back on the page
    // Do Something
});

window.addEventListener("blur", function () {
    // User left the page
    // Do Something
});

이전 코드는 잘 동작은 하지만 의도한 대로 다 동작한는 코드는 아닙니다. 왜냐하면, blur 이벤트는 페이지가 포커스를 잃었을 때 발생되며 유저가 검색바, 얼럿 다이얼로그, 콘솔, 윈도우 보더 등을 클릭했을 때도 발생되기 때문입니다. 그래서 blurfocus는 페이지가 활성화되어 있는지는 알려줄 순 있지만, 페이지의 내용이 가려지거나 보이고 있는지를 알려주지는 않습니다.

사례

일반적으로 유저가 페이지를 보고 있지 않을 때 불필요한 프로세스를 중단하고, 반대로 백그라운드 액션들을 실행하고 싶을 때 Page Visibility API를 활용하고 싶을 겁니다.

  • 유저가 페이지를 떠났을 때 비디오, 이미지 캐러셀, 애니메이션의 일시정지
  • API로부터 라이브 데이터를 보여주고 있는 경우 유저가 떠나있는 동안 일시적으로 중단
  • 유저의 동작에 대한 분석 데이터를 전송

사용법

Page Visibility API는 두 가지 프로퍼티와 페이지 가시성 상태에 대해 접근하는 이벤트를 가지고 있습니다.

  • document.hidden: 전역으로 사용가능하며 read-only 값입니다. 지금은 deprecated 되었으므로 사용하지 않아야 하지만, 접근은 가능합니다. 페이지가 숨겨지면 true, 페이지가 보이고 있으면 false를 반환합니다.
  • document.visibilityState: 위의 document.hidden의 업데이트된 버전입니다. 접근했을 때 페이지 상태에 따라 4가지 중 하나의 값을 가집니다.
    • visible: 페이지가 보이거나 정확히는 최소화되거나 다른 탭으로 전환되지 않은 상태
    • hidden: 페이지가 최소화되거나 다른 탭으로 전환되어 보이지 않는 상태
    • prerender: 보여지는 페이지가 프리 렌더링 중 초기 상태, 페이지의 상태는 prerender에서 시작해서 다른 상태로 변할 순 있어도 반대로 다른 상태에서 prerender로 변할 수는 없습니다.
    • unloaded: 메모리로부터 unloaded된 상태
  • visibilitychange: document 객체로부터 제공되는 이벤트로 페이지의 visibilityState가 변경되었을 때 트리거됩니다.
document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") {
        // page is visible
    } else {
        // page is hidden
    }
});

Page Visibility API를 어떻게 사용하는지 알고 싶다면, 사용자가 페이지를 떠날 때 비디오를 일시중지하고 API에서 리소스를 가져오는 것을 멈추게 하기 위해 이 API를 활용하는 예시를 작성해봅시다. 이 예시를 위해 저는 vite.js를 사용할 건데, 새로운 프로젝트를 빠르게 시작하기에 아주 좋은 도구입니다.

npm create vite@latest unknown-web-apis

프레임워크를 선택하라고 하면, 바닐라 자바스크립트로 짤테니 바닐라를 선택해주세요. 일단 프로젝트 생성이 되면 새 폴더에 가서 필요한 npm 패키지들을 설치하고 dev 서버를 켜주세요.

cd unknown-web-apis
npm install
npm run dev

localhost:3000/에 가면 Vite 프로젝트가 돌아가고 있는 걸 볼 수 있습니다!

image

먼저 바로 /main.js 파일로 가서 보일러플레이트를 모두 지웁니다. 그리고 /index.html을 열어 #app div tag 내부에 여러분들이 원하는 아무 비디오에 대한 엘리먼트를 추가합니다. 저는 춤추는 요시 비디오를 사용했어요. :)

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    </video>
</div>

다시 /main.js에 가서 document 객체에 visibilitychange 이벤트에 대한 이벤트 리스너를 추가합니다. 그럼 이제 페이지가 보이거나 가려졌을 때 document.visibilityState 프로퍼티를 접근할 수 있습니다.

document.addEventListener("visibilitychange", () => {
    console.log(document.visibilityState);
});

페이지 콘솔로 가서 여러분들이 윈도우를 최소화하거나 다른 탭으로 이동했을 때 페이지 가시성 상태가 변경되는 것이 보일 겁니다. 이제 이벤트 리스너 내부에서 document.visibilityState를 확인하고 hidden이면 비디오를 일시정지, visible일 때 재생하도록 코드를 작성할 수 있겠군요. (물론, 먼저 document.querySelector()를 사용해서 video 엘리먼트를 선택해야 합니다.)

const video = document.querySelector("#video");

document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") {
        video.play();
    } else {
        video.pause();
    }
});

이제 사용자가 페이지를 떠날 때마다 비디오를 멈출 수 있게 됐습니다. 이 API는 사용자가 페이지를 보고 있지 않을 때 불필요하게 리소스를 가져오지 않도록 활용할 수도 있습니다. 이를 확인하기 위해 계속 quotable.io API로부터 랜덤 인용구를 가져오는 함수를 작성해볼게요. 그리고 페이지가 hidden일 때 멈추게 하면 되겠죠. 먼저, /index.html 내에 인용구를 저장하는 새로운 div tag를 하나 만들어보겠습니다.

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    </video>
    <div id="quote"></div>
</div>

다시 /main.js로 돌아가서, Fetch API를 사용하여 quotable.io를 호출하고 quote div에 결과를 삽입하는 코드를 작성하겠습니다.

const quote = document.querySelector("#quote");

const getQuote = async () => {
    try {
        const response = await fetch("https://api.quotable.io/random");
        const {content, author, dateAdded} = await response.json();
        const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`;
        quote.innerHTML = parsedQuote;
    } catch (error) {
        console.error(error);
    }
};

getQuote();

유저가 윈도우를 최소화시키거나 탭을 이동해도 페이지는 여전히 불필요한 네트워크 로드를 생성하여 데이터를 가져올 것입니다. 이를 해결하기 위해 데이터를 가져오기 전에 페이지의 가시성 상태를 확인하면 되겠죠.

const getQuote = async () => {
    if (document.visibilityState === "visible") {
        try {
            const response = await fetch("https://api.quotable.io/random");
            const {content, author, dateAdded} = await response.json();
            const parsedQuote = `
            <q>${content}</q> <br> 
            <p>- ${author}</p><br> 
            <p>Added on ${dateAdded}</p>`;
            quote.innerHTML = parsedQuote;
        } catch (error) {
            console.error(error);
        }
    }
};

getQuote();

setInterval(getQuote, 10000);

이제 페이지가 유저에게 보일 때만 데이터를 가져올 수 있게 되었습니다.

Web Share API

Web Share API란?

Web Share API는 덜 알려진 API들 중 하나지만 아주 유용한 API입니다. 이 API는 여러분들이 운영체제의 네이티브 공유 메커니즘에 접근할 수 있게 해주는데 특히 모바일 유저들에게 아주 유용한 기능입니다. 이 API를 통해 따로 공유 메커니즘을 생성하거나 서드파티를 사용하지 않고도 텍스트, 링크, 파일들을 공유할 수 있습니다.

사례

크게 설명이 필요하지 않습니다. 페이지의 콘텐츠를 소셜 미디어에 공유하거나 유저의 클립보드로 복사하는 용도로 사용할 수 있습니다.

사용법

Web Share API는 유저의 공유 시스템에 접근하기 위한 두 가지 인터페이스를 제공합니다

  • navigator.canShare(): 공유하고자 하는 데이터를 인자로 받아 공유 가능여부에 대한 boolean 값을 반환합니다.
  • navigator.share(): 성공적으로 공유되었을 때 resolve되는 프로미스를 반환합니다. 네이티브 공유 메커니즘을 호출하고 공유하고자 하는 데이터를 인자로 받습니다. 유저가 링크나 버튼을 클릭했을 때에만 호출됨을 기억하세요. 즉, 순간적인 활성화가 필요합니다. 공유 데이터는 다음과 같은 프로퍼티를 가질 수 있는 객체입니다.
    • url: 공유되는 URL
    • text: 공유되는 텍스트
    • title: 공유되는 타이틀
    • files: 공유하는 파일들에 대한 File 객체의 배열

이전에 사용했던 예제를 재활용해서 Web Share API를 사용하여 인용구를 공유하는 옵션을 만들어보겠습니다. 먼저 /index.html에 공유 버튼을 만듭니다.

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    </video>
    <div id="quote"></div>
    <button type="button" id="share-button">Share Quote</button>
</div>

/main.js에 가서 DOM에서 공유 버튼을 선택합니다. 그러고 나서, 데이터를 공유하는 async 함수를 생성합니다.

const shareButton = document.querySelector("#share-button");

const shareQuote = async (shareData) => {
    try {
        await navigator.share(shareData);
    } catch (error) {
        console.error(error);
    }
};

이제 shareButton 엘리먼트에 이벤트 리스너를 추가하여 shareQuote 함수를 콜백함수로 실행하도록 합니다. shareData.text 값은 quote.textContent 프로퍼티가 되고, shareData.urllocation.href 프로퍼티와 같은 페이지 URL이 됩니다.

const shareButton = document.querySelector("#share-button");

const shareQuote = async (shareData) => {
    try {
        await navigator.share(shareData);
    } catch (error) {
        console.error(error);
    }
};

shareButton.addEventListener("click", () => {
    let shareData = {
        title: "A Beautiful Quote",
        text: quote.textContent,
        url: location.href,
    };

    shareQuote(shareData);
});

이제 여러분들의 데이터를 네이티브 OS를 통해 누구에게나 공유할 수 있습니다. 그러나 Web Share API는 반드시 안전한 환경에서만 동작함을 기억해야 합니다. 예를 들어 페이지는 https://wss:// URL을 통해 제공되어야 합니다.