본문 바로가기
React Native

0055. 실전 FE 개발 배우기12 - 웹소켓 연결하기, 실시간 데이터 받기, 로그아웃(Bearer 토큰)

by 보초코더^_^;; 2024. 2. 7.
반응형

섹션 2. 서버 API 연동하기

8강. 웹소켓 연결하기

 

1) 웹소켓 기반 라이브러리

요청-응답 방식이 아니라 실시간 양방향 통신 가능

기존 : app → axios  응답

소켓 : 한 번만 연결을 맺으면 연결이 끊어지기 전까지 실시간으로 가능. 서버에서 먼저 보내줄 수도 있다.

 

대신, 배터리 소모가 있다.

npm i socket.io-client

웹소켓 라이브러리 설치

 

 

2) Custom hooks

 

자주 쓰는 것은 hook으로 만든다.

Custom hook에 익숙해져야 한다.

 

import { io, Socket } from 'socket.io-client';
import Config from 'react-native-config';

let socket: Socket | undefined;
const useSocket = () => {
    socket = io(`${Config.API_URL}, {
        transports: ['websocket'],
    });
};

export default useSocket;

이게 기본 포맷

 

소켓 통신이 안될 때 실시간으로 통신이 되는 것처럼 빠르게 요청 → 응답하는 것을 long-polling이라고 한다. 그런데 이 방식은 서버에 무리를 줄 수 있기 때문에 가급적 쓰지 않는 것이 좋다.

즉, transports: ['websocket']은 그냥 웹소켓 방식으로만 통신하라는 뜻이다.

 

  if (!socket && isLoggedIn) {
    console.log(!socket && isLoggedIn, '웹소켓 연결을 진행합니다.');
    socket = SocketIOClient(`${Config.API_URL}`, {
      transports: ['websocket'],
    });
  }

만일, 서버에 연결되어 있는데 여러 번 계속해서 소켓이 연결되면 한번 요청해도 여러 번 요청이 가고, 여러 번 응답이 올 것이다. 그래서 소켓이 없을 때(!socket)만 연결하도록 로직을 구성한다.

 

let socket: Socket | undefined;

소켓이 있을 수도 없을 수도..

 

위랑 아래랑 똑같은 뜻이다.

const useSocket = (): [typeof socket, () => void] => { }

소켓의 타입을 지정하는 똑같은 의미

 

const useSocket = (): [typeof socket, () => void] => {
    const disconnect = useCallback( () =>{
        if(socket) {
            socket.disconnect();
            socket = undefined;
        },
    }, []);
}

() => void는 아래의 disconnect 함수의 타입을 지정해 주는 것

매개변수로 아무것도 안 받고, 리턴값은 undefined다.

함수의 리턴값을 지정하지 않으면 undefined인데, typescript의 경우 void라고 표현한다.

 

 

9강. 실시간 데이터 받기, 로그아웃(Bearer 토큰)

1) 실시간 데이터 받기

hooks에 넣어놨던 useSocket 코드를  AppInner에  넣기

  const [socket, disconnect] = useSocket();

  useEffect(() => {
    const helloCallback = (data: any) => {
      console.log(data);
    };
    if (socket && isLoggedIn) {
      console.log(socket);
      socket.emit('login', 'hello');
      socket.on('hello', helloCallback);
    }
    return () => {
      if (socket) {
        socket.off('hello', helloCallback);
      }
    };
  }, [isLoggedIn, socket]);

  useEffect(() => {
    if (!isLoggedIn) {
      console.log('!isLoggedIn', !isLoggedIn);
      disconnect();
    }
  }, [isLoggedIn, disconnect]);

 

      socket.emit('login', 'hello');
      socket.on('hello', helloCallback);

서버에게 데이터는 보내는 것 : socket.emit

서버에서 데이터를 받아오는 것 : socket.on

 

        socket.off('hello', helloCallback);

받는 거 그만하기 : socket.off

 

 

키=값 또는 키, 값 꼴로 수신

  • 키, 값
  • 'hello', 'world'
  • 'userInfo', { name: 'chobo', address: coder-chobo.tistory.com }
  • 'order', { orderId: '1224s', price: 1000, latitude: 37.5, longitude: 123.5 }

 

useEffect(() => {
    const helloCallback = (data: any) => {
      console.log(data);
    };
    if (socket && isLoggedIn) {
      socket.on('hello', helloCallback);
    }
    return () => {
      if (socket) {
        socket.off('hello', helloCallback);
      }
    };
  }, [isLoggedIn, socket]);
  • useEffect의 return 함수는 cleanUp
  • socket.on : 연결
  • socket.off : 끊기

hello라는 key로 data를 받아올 건데, 위에 나온 부분 중 다음 부분으로 받아오는 것

    const helloCallback = (data: any) => {
      console.log(data);
    };

서버로부터 데이터를 받을 때는 callback 방식으로 처리

즉, 미리 계획되어 있어야 한다. 서버개발자가 서버로부터 hello라는 key로 보내줄 거라고 얘기한 상황이어야 한다.

 

소켓이 연결되면 서버에 연결되었다고 알림이 뜬다.

 

1초에 한 번씩 emit이 올라가는데, 이는 back에서 1초에 한번 리턴하라고 코딩이 되었기 때문

이거 오류인 줄 알고 고치려고 몇 시간 봤는데.. 흑흑

 

연결되면 콜백을 해주도록 해놨기 때문

 

위에는 hello로 해놨지만 실제로는 key를 서버에 전달하면 주문 내역을 리턴하는 등으로 바꿀 수 있다.

이건 서버 개발자와 약속해서 진행하면 된다.

 

2) 로그아웃

토큰을 꺼내오기 : state.user.accessTocken

 

slice의 user.ts안의 토큰을 가져온다.

const initialState = {
  name: '',
  email: '',
  accessToken: '',
};

 

          headers: {
            Authorization: `Bearer ${accessToken}`,
          },

header도 키값이다.

Authorization Bearer도 서버개발자와 약속이다.

 

여기서 accessToken을 넣어주면 서버가 나인지 아닌지 판단을 하는 것이다.

 

      dispatch(
        userSlice.actions.setUser({
          name: '',
          email: '',
          accessToken: '',
        }),
      );

setUser에서 초기화해주면 알아서 다 정보가 들어간다.

 

      await EncryptedStorage.removeItem('refreshToken');

refreshToken도 지워줘야(초기화해 줘야) 된다.

그러지 않으면 로그아웃 했다고 해도 로그아웃이 안된다.

 

앱-서버 불일치가 일어나면 오류가 발생한다.

앱이 오류가 발생하면 서버도 오류가 발생해야 한다.

 

반응형