dkmqflx's Blog

BroadcastChannel API 사용해서 서로 다른 탭 사이에 통신하기

JavaScript / React
2022.11.10

BroadcastChannel

BroadcastChannel은 동일한 Origin을 갖는 서로 다른 창 또는 탭 사이에서 통신할 때 사용할 수 있는 API 입니다.
아래처럼 BroadcastChannel을 생성할 수 있는데, 이 때 동일한 Origin에 대해서는 중복되는 Channel 이름으로 BroadcastChannel을 만들 수 없습니다.

const broadCastChannel = new BroadcastChannel(CHANNEL_NAME)

이렇게 선언된 BroadcastChannel은 postMessage 함수를 통해서 메세지를 전달할 수 있고, 전달된 메세지는 같은 이름의 BroadcastChannel를 listening 하고 있는 모든 BroadcastChannel에 전송됩니다

아래처럼 postMessage 함수에 'new Message!' 라는 메세지를 전달합니다.

const sendBroadCastChannel = new BroadcastChannel(CHANNEL_NAME)
broadCastChannel.postMessage('new Message!')

이렇게 전달된 메세지는 같은 BroadcastChannel 이름을 갖고 있는 BroadcastChannel 객체의 onmessage 함수를 통해 전달받을 수 있습니다.

const receiveBroadCastChannel = new BroadcastChannel(CHANNEL_NAME)
broadCastChannel.onmessage = event => {
  console.log(event.data) // new Message!
}

React 에서 BroadcastChannel 하는 Custom hook 만들기

리액트에서도 BroadcastChannel을 사용해서 서로 다른 탭 사이에 통신을 할 수 있습니다. 아래는BroadcastChannel을 사용하기 위한 Custom hook입니다.

// hooks/useNewTab.jsx

import { useEffect, useRef, useState } from 'react'

const CHANNEL_NAME = 'newtab'

const useNewTab = () => {
  const channel = useRef()
  const [data, setData] = useState()

  // 메세지 보내는 함수
  const postMessage = message => {
    channel.current?.postMessage(message)
  }

  // 새로운 탭 열 수 있는 함수
  const openNewTab = () => {
    window.open(`/newtab`)
  }

  useEffect(() => {
    channel.current = new BroadcastChannel(CHANNEL_NAME)

    if (channel.current) {
      // channel.current.onmessage와 동일, 메세지 이벤트 발생할 때 마다 state 변경해준다
      channel.current.addEventListener('message', event => {
        setData(event.data)
      })
    }

    return () => {
      channel.current?.removeEventListener('message', event => {
        setData(event.data)
      })
    }
  }, [])

  return { postMessage, data, openNewTab }
}

export default useNewTab

이렇게 선언한 Custom hook에는 BroadcastChannel가 선언되어 있기 때문에 hook을 사용하는 모든 곳에서 서로 데이터를 주고 받을 수 있게 됩니다.
아래는 새로운 탭을 열고 다른 BroadcastChannel에서 보낸 메세지를 받아서 보여주는 코드입니다.

// pages/Home.js
import useNewTab from '../src/hooks/useNewTab'

export default function Home() {
  const { data, openNewTab } = useNewTab()

  return (
    <div>
      <div>data is {data}</div>
      <button onClick={openNewTab}>Open new Tab</button>
    </div>
  )
}

Open new Tab 버튼을 눌러 새로운 페이지를 열어줍니다. 그리고 해당 페이지에서 데이터를 입력받은 후 확인 버튼을 누르면 위 페이지에서 입력한 데이터를 볼 수 있습니다

// pages/newtab.jsx
import useNewTab from '@/src/hooks/useNewTab'

const newtab = () => {
  const { postMessage } = useNewTab()

  const onSubmit = e => {
    e.preventDefault()

    postMessage(e.target.data.value)
  }

  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="data" />
      <button type="submit">확인</button>
    </form>
  )
}

export default newtab
© 2022 dkmqflx, Powered By Gatsby