최종 프로젝트 | Notification API 로 웹푸시알림 구현하기

하영·2024년 11월 22일
0

팀프로젝트

목록 보기
26/27

프로젝트에서 타이머를 구현했는데 타이머가 종료되면 웹 푸쉬알림이 오도록 구현하고 싶었다. + 소리까지 나온다면 좋을듯! 해서 구현방법을 구글링했다.

PWA와 Notification API가 있었는데 타이머 기능은 팀 프로젝트에서 추가적인 기능이었고 특히나 푸쉬알림은 할 수 있다면 해보자!여서 최대한 간단하고 빠르게 구현이 가능한 것으로 해보기로 했다.


Notification API

사용자 에게 데스크톱 알림을 구성하고 표시하는 데 사용되는 api로,
이러한 알림의 모양과 구체적인 기능은 플랫폼마다 다르지만 일반적으로 사용자에게 비동기적으로 정보를 제공하는 방법을 제공한다.

notification permission 🔍

  • denied : 사용자가 알림 표시를 거부
  • granted : 사용자는 알림 표시에 동의
  • default : 사용자 선택이 알려지지 않았으므로 브라우저는 값이 거부된 것처럼 작동

예시 코드

이걸 참고해서 팀 프로젝트에도 적용해보았다.


알림 함수 만들기 👩🏻‍💻

export const triggerNotification = async (): Promise<"popup" | "push"> => {
  const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

  if (!isMobile && Notification.permission === "granted") {
    new Notification("타이머 종료", {
      body: "타이머가 종료되었습니다!",
      icon: "/images/mainLogo.svg"
    });
    return "push"; // 푸쉬 알림이 성공한 경우
  } else {
    return "popup"; // 토스트 알림이 필요한 경우
  }
};

export const playSound = () => {
  const audio = new Audio("/audio/5-Handoff.mp3");
  audio.play();
};

조건문을 준 이유는 모바일일 경우 푸쉬알림이 뜨지 않아서 추가해주었다.
모바일까지 하려면 튜토리얼이 더 길어지는데 거기까지 하기엔 시간도 부족했고 메인기능이 아니어서 모바일 환경에서는 토스트 알림이 뜨도록 만들었다.

playSound 함수를 통해 시간이 종료되면 알림음이 뜨도록 만들어주었다.


타이머 컴포넌트에 함수 적용하기 👩🏻‍💻

import { playSound, triggerNotification } from "./Notification";

const Timer: React.FC = memo(() => {
const [popupMessage, setPopupMessage] = useState<string | null>(null);

  // 타이머 실행 로직 + 알림음 팝업
  useEffect(() => {
    let timer: NodeJS.Timeout | null = null;
    if (isRunning && timeLeft > 0) {
      timer = setInterval(() => {
        setTimeLeft((prevTime) => prevTime - INTERVAL);
      }, INTERVAL);
    } else if (timeLeft <= 0 && isRunning) {
      clearInterval(timer!);
      setIsRunning(false);
      triggerNotification().then((type) => {
        if (type === "popup") {
          setPopupMessage("타이머가 종료되었습니다!");
        }
      });
      playSound();
    }

    return () => {
      if (timer) clearInterval(timer);
    };
  }, [isRunning, timeLeft]);

  // 팝업 메시지 호출 (5초 뒤에 사라짐)
  useEffect(() => {
    if (popupMessage) {
      const timeout = setTimeout(() => setPopupMessage(null), 5000);
      return () => clearTimeout(timeout);
    }
  }, [popupMessage]);

  
  // 중간 로직 생략
  
  return (
    <div className="fixed bottom-20 z-10 ssm:right-4 md:right-16">
      {/* 팝업 메시지 호출 */}
      {popupMessage && (
        <div className="absolute right-0 top-[-50px] rounded-lg bg-Primary-300 p-3 text-white shadow-md">
          {popupMessage}
        </div>
      )}
   )
 }


아까 만들었던 triggerNotification 함수를 실행하고 모바일 환경일 때는 토스트 알림이 보이도록 조건문을 넣어주었다.
그리고 playSound() 함수를 실행해 타이머 종료시 알림음이 울리도록 했다.


소소한 트러블슈팅 💥

실행시켰는데 소리는 잘 들리지만 중요한 푸쉬알림이 보이지 않았다. 토스트 알림은 보이는 걸 보아서는 notification 코드에도 문제가 있는 것 같지는 않았다.

콘솔에도 granted 로 나오는 걸 보았을 때 이건 코드상의 문제가 아니라 내 컴퓨터의 알림설정과 관련이 있을 수 있겠다 생각이 들어 환경설정에 들어가보았다.

역시 크롬 알림 허용을 비활성화 해둔 상태였고 이를 다시 활성화 시킨 후 다시 실행시켜보았다.


결과확인 ✅


크롬, 사파리 브라우저에서 모두 제대로 구현되는 걸 확인했고

모바일 환경에서도 토스트 알림이 잘 뜨고 있었다! 👏



생각보다 웹푸쉬알림이 간단하게 구현할 수 있어서 재미있고 신기했다.
시간 여유가 됐다면 모바일에서도 푸쉬알림이 나오게 구현해보고 싶다. 꼼꼼하게 알아보지 않았지만 PWA를 더 많이 사용하는 것 같은데 리펙토링을 하거나 다음에도 비슷한 기능을 구현해보게 된다면 PWA 를 사용해서 모바일/웹 모든 환경에서도 동일하게 푸쉬알림이 갈 수 있도록 해봐야겠다.


참고자료

profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글

관련 채용 정보