[React native] 실시간 알림

MODAC·2023년 10월 18일
0

knockknock

목록 보기
3/9

현재 진행중인 knockknock 프로젝트의 알림 기능 구현을 위해 서버의 데이터를 실시간으로 스트리밍하면서 알림 데이터를 받아올 수 있는 방법에 대해 찾아봤다.

Rest API

클라이언트에서 HTTP 요청이 있을 때 서버는 요청에 대한 데이터를 전송하고 즉시 종료되는 클라이언트에서만 서버로 연결되는 단방향 통신이다.

  • 사용처: 게시판 CRUD, 회원정보, 상품 정보 등

WebSocket

TCP/IP 또는 UDP/IP와 같은 기존의 네트워크 프로토콜을 사용하는 Socket과 달리 HTTP를 기반으로 하며, 웹 브라우저와 웹 서버 간에 웹소켓 프로토콜을 사용하여 연결을 설정하는 양방향 통신이다.

  • 사용처: 채팅 서비스, 스트리밍 서비스, 실시간 차트 등

SSE(Server-Sent-Event)

버의 데이터를 클라이언트에서 실시간으로 스트리밍할 수 있도록 연결을 유지하는 단방향 통신이다. HTTP 프로토콜 위에서 동작하며 실행 시 기존의 HTTP 연결을 유지한 상태에서 리커넥팅이나 추가설정 없이 변경된 데이터를 지속적으로 수신할 수 있다.

  • 사용처: 알림, 중계 등

React-native-sse

알림 기능 구현을 위해 React native에서 사용 가능하고 엑세스 토큰 전송을 위한 커스텀 헤더 설정이 가능한 React-native-sse를 선택했다.

import React, {useEffect} from 'react';
import EventSource, {EventSourceListener} from 'react-native-sse';

const Notifications: React.FC= () => {
  
  //...
  
useEffect(() => {
  // 커스텀 헤더 옵션
    const option = {
      method: 'GET', // GET은 Defualt
      headers: {Authorization: `Bearer ${token}`},
      debug: true, // 요청을 디버깅하는 옵션
    };
  // 종속형 배열에 빈배열을 전달하여 컴포넌트의 첫 랜더링 시 실행
    const eventSource = new EventSource(streamUrl, option);
  
  	// 요청 후 응답에 따른 동작을 순수함수에 담았다.
    const listener: EventSourceListener = event => {
      if (event.type === 'open') {
        console.log('Open SSE connection.');
      } else if (event.type === 'message') {
        console.log('Connection', event);
      } else if (event.type === 'error') {
        console.error('Connection error:', event.message);
      } else if (event.type === 'exception') {
        console.error('Error:', event.message, event.error);
      }
    };
  // 이벤트리스너를 호출
    eventSource.addEventListener('open', listener);
    eventSource.addEventListener('message', listener);
    eventSource.addEventListener('error', listener);
  
  // 컴포넌트의 언마운트와 함께 연결이 종료된다.
    return () => {
      eventSource.removeAllEventListeners();
      eventSource.close();
    };
  }, []);
}
  
  //...
  

첫 연결 시도 시 Android 시뮬레이터에서 테스트 시 유효한 URL과 Token을 전달해도 401에러를 반환했다. 구글링 결과 안드로이드에 내장된 Flipper(모바일 에플리케이션 개발 시 디버깅을 위한 도구)에서 네트워크의 요청과 응답을 모니터링하는 NetworkFlipperPlugin 플러그인이 실행된다. 이 디버깅 과정 중에 SSE 요청을 가로채어 실시간 요청에 개입하여 발생한 문제로 아래의 코드를 주석처리하니 정상적으로 연결됐다.

public class ReactNativeFlipper {
  public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
    if (FlipperUtils.shouldEnableFlipper(context)) {
      final FlipperClient client = AndroidFlipperClient.getInstance(context);

      client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
      client.addPlugin(new DatabasesFlipperPlugin(context));
      client.addPlugin(new SharedPreferencesFlipperPlugin(context));
      client.addPlugin(CrashReporterPlugin.getInstance());

      // NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
      // NetworkingModule.setCustomClientBuilder(
      //     new NetworkingModule.CustomClientBuilder() {
      //       @Override
      //       public void apply(OkHttpClient.Builder builder) {
      //         builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
      //       }
      //     });
      // client.addPlugin(networkFlipperPlugin);
      client.start();

0개의 댓글