본문 바로가기
개발/리액트

[React] 우리서비스를 더 널리, SNS 공유하기 (Navigator.share)

by 핸디(Handy) 2022. 11. 22.

들어가며

이번에 갑자기 서비스를 운영 중에 팬덤을 타고 SNS에 서비스가 공유되는 일이 발생했었습니다.

그래서 이번 기회에 유저의 편의성을 위해 링크를 만들어 제공하거나 SNS로 바로 공유가 가능하도록 기능을 구현한 방법을 다뤄보겠습니다.

대상 독자는 

  • 공유하기 기능에 대한 예시 코드를 살펴보고 싶은 개발자
  • 리액트를 통해 공유 기능을 제공하려는 개발자

공유 기능 살펴보기

공유기능 생각보다 눈여겨보진 않았지만 어느덧 우리 삶에 깊숙이 들어온 기능입니다.

이번 기회에 다른 서비스 예시부터 그리고 어떤 UX를 가지고 있나 살펴보도록 하겠습니다.

공유하기의 UX

공유하기 기능은 크게 2가지 버전으로 나눌 수 있습니다.

  • 일반 브라우저에서의 공유하기
  • 모바일 브라우저에서의 공유하기

이렇게 나눠지는 이유는 실은 간단합니다.

모바일 브라우저에서 간단히 공유하기 기능을 제공할 수 있는 navigator/share api가 있기 때문입니다.

모바일에서의 공유하기

share api를 간단히 살펴보자면 사용법은 다음과 같습니다.

navigator.share({
  title: "핸디의 개발 블로그",
  text: "이 글은 SNS 공유하기에 대한 글입니다.,
  url: "https://all-dev-kang.tistory.com/",
});

그리고 공유가 완료되면 아래와 같이 제공됩니다. 참 쉽죠? 실제 예제 코드는 아래에서 한 번에 살펴보겠습니다.

카카오톡 공유하기 예시 ( 모바일 전체화면은 테스트 서비스 예시 )

근데 share api는 큰 문제가 있습니다. 바로 모바일에서만 지원하는 api라는 점입니다.

https://caniuse.com/?search=navigator%20share

 

Navigator.share - Web API | MDN

Navigator.share() 메소드는 Web Share API 의 부분으로서 디바이스의 네이티브 공유하기 메커니즘을 작동시킨다. Web Share API 가 지원되지 않는다면, 이 메소드는 undefined 일 것이다.

developer.mozilla.org

일반 적으로라면 문제 될 것이 없지만, 현재 제 서비스는 같은 웹으로 모바일, 데스크탑을 지원하고 있습니다.

그래서 모바일, 데스크탑이냐에 따라 행동이 달라져야 하는 상황이 되어버렸습니다.

데스크탑에서의 공유하기

그래서 다른 서비스들은 어떻게 제공하는지 궁금해서 찾아보았습니다.

네이버, 유튜브

서로서로 다르지만 공통적으로 트위터, 페이스북, 카카오톡, 그리고 URL 링크를 노출시키는 것을 확인할 수 있습니다.

공유하기의 기능 개발

앞써 말씀드리지만 트위터, 페이스북 공유는 매우 간단하지만, 카카오톡은 카카오 sdk를 이용한 공유를 해야 합니다.

그래서 과정이 쪼금 길지만 그렇게 어렵지 않으니 따라오시면 되겠습니다.

현재 title, url만 공유하기 때문에 해당 값만 sharedLink로 만드는 작업을 수행 중이지만 얼마든지 다른 값도 넘길 수 있습니다.

넘길 수 있는 값들은 각각의 api 스펙 문서를 보면 확인이 가능합니다.

트위터 공유하기

const shareToTwitter = () => {
  const sharedLink =
    "text=" + encodeURIComponent(title + " \n ") + encodeURIComponent(url);
  openWidnow(`https://twitter.com/intent/tweet?${sharedLink}`);
};

페이스북 공유하기

const shareToFacebook = () => {
  const sharedLink = encodeURIComponent(url);
  openWidnow(`http://www.facebook.com/sharer/sharer.php?u=${sharedLink}`);
};

카카오톡 공유하기

인터넷에서 찾아보면 많은 예시가 있습니다. 따라서 여기서는 간략 요약을 하도록 하겠습니다.

  1. 카카오 SDK 불러오기
  2. 발급받은 KEY로 인증처리
  3. 원하는 API 쏘기

그럼 이제 하나씩 구현을 해봅시다.

첫 번째로 카카오 SDK를 불러오는 과정입니다.

불러오는 방법에는 여러 가지가 있는듯하지만 제가 사용한 방법은 useEffect 내부에서 1회만 호출하여 사용하는 방법입니다.

전역적으로도 선언할 수 있었지만 기본적으로 유저가 공유하기 버튼을 할 확률을 생각해보면 해당 컴포넌트가 마운트 될 때 하는 방법도 좋은 방법이라고 생각했기 때문입니다.

useEffect(() => {
  const script = document.createElement("script");
  script.src = "https://developers.kakao.com/sdk/js/kakao.js"; // 카카오톡 SDK
  script.async = true;

  document.body.appendChild(script);

  return () => {
    document.body.removeChild(script); // return으로 제거해주기
  };
}, []);

2. 발급받은 KEY로 인증처리

발급하는 방법은 카카오 개발자 사이트에 가서 하면 됩니다.

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

추가하기 -> 앱 키 (그중 JavaScript 키)

이제 인증을 하고, API를 날려보겠습니다.

// 카카오 SDK는 window 객체에 전역으로 추가되니 TS를 위해 선언해줍시다.
declare global {
  interface Window {
    Kakao: any;
  }
}

const shareToKakaoTalk = (title : string, url : string) => {
  if (window.Kakao === undefined) {
    return;
  }

  const kakao = window.Kakao;

  // 인증이 안되어 있는 경우, 인증한다.
  if (!kakao.isInitialized()) {
    kakao.init(KAKAO_SHARE_KEY); // 가져온 KEY를 넣는 장소, ENV로 넣던지 아니면 스트링으로 해셔도..ㅎ
  }

  kakao.Share.sendDefault({
    objectType: "text",
    text: title,
    link: {
      mobileWebUrl: url,
      webUrl: url,
    },
  });
};

카카오톡 공유하기
결과 화면

공유하기의 Tip | useSNSShare 훅

저는 이런 기능을 다 같이 모아 훅으로 만들었는데 코드로 살펴볼게요.

import { config } from "@util/properties";
import { useEffect } from "react";

interface UseSNSShareParams {
  title?: string;
  url?: string;
  option?: {
    windowOpenTarget: "_black" | "_parent" | "_self" | "_top";
  };
}

declare global {
  interface Window {
    Kakao: any;
  }
}

const useSNSShare = ({ title, url, option }: UseSNSShareParams) => {
  const { t } = useTranslation();

  const shareToTwitter = () => {
    const sharedLink =
      "text=" + encodeURIComponent(title + " \n ") + encodeURIComponent(url);
    openWidnow(`https://twitter.com/intent/tweet?${sharedLink}`);
  };

  const shareToFacebook = () => {
    const sharedLink = encodeURIComponent(url);
    openWidnow(`http://www.facebook.com/sharer/sharer.php?u=${sharedLink}`);
  };

  const shareToKakaoTalk = () => {
    if (window.Kakao === undefined) {
      return;
    }

    const kakao = window.Kakao;

    // 중복 initialization 방지
    if (!kakao.isInitialized()) {
      // 두번째 step 에서 가져온 javascript key 를 이용하여 initialize
      kakao.init(config.KAKAO_SHARE_KEY);
    }

    kakao.Share.sendDefault({
      objectType: "text",
      text: title,
      link: {
        mobileWebUrl: url,
        webUrl: url,
      },
    });
  };

  const shareToNavigator = ({ text, url }: { text: string; url: string }) => {
    const sharedData = {
      text: text,
      url: url,
    };

    try {
      if (navigator.canShare && navigator.canShare(sharedData)) {
        navigator
          .share(sharedData)
          .then(() => {
            console.log("성공")
          })
          .catch(() => {
            console.log("취소")
          });
      }
    } catch (e) {
      console.log("실패")
    }
  };

  const openWidnow = (url: string) => {
    window.open(url, option?.windowOpenTarget || "_blank");
  };

  useEffect(() => {
    const script = document.createElement("script");
    script.src = "https://developers.kakao.com/sdk/js/kakao.js";
    script.async = true;

    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
    };
  }, []);

  return {
    isAvailNavigator: typeof navigator.share !== "undefined",
    shareToTwitter,
    shareToFacebook,
    shareToKakaoTalk,
    shareToNavigator,
  };
};

export default useSNSShare;

그리고 해당 훅의 return 값에는 isAvailNavigator라는 값이 있습니다.

현재 브라우저가 Navigator.share를 사용 가능한지 확인하는 boolean 값입니다.

특정 컴포넌트에서 share기능으로 데이터는 공유할 건지, 아니면 링크 복사 또는 가능한 SNS를 제공할지 결정하는 기준이 됩니다.

Share 또는 Custom SNS share 컴포넌트

 

모바일 브라우저 디버깅

이렇게 공유 기능을 다 만들고 나서 테스트를 하려니.. 뭔가 불편합니다.

배포 -> dev -> 핸드폰으로 동작 확인의 무한 반복 속에 지쳐가다가 결국 모바일 브라우저 디버깅 세팅을 하기로 결심합니다.

빨간창만 신경쓰면 됩니다.

그리고 inspect를 누르게 되면 다음과 같은 창이 뜹니다.

이제 실제 기기 테스트하려 가시면 됩니다.

저 같은 경우 위에 navigator.share api를 테스트하기 위해 해당 기능을 설치했습니다.

마무리

이번 글에서는 네이버, 유튜버의 공유하기 UI를 살펴보고 공통된 SNS만 추출하여 실제 코드를 가지고 글을 작성해봤습니다.

생각보다 간단하고 당연시되는 기능 중에 하나이지만, 구현하면서 느낀 점은 앱과 모바일 웹의 경계가 점점 사라진다는 것이었습니다.

아무튼 이번 기회에 API 스펙 문서를 가지고 카카오톡, 페이스북, 트위터만 공유하기를 만들었는데 다양한 SNS로 확장한 오픈소스 라이브러리가 있으면 좋겠다는 생각을 잠깐 해봤네요. ( 시간 나면 만들어볼지도? )

끝.

댓글