Socket.io-client: ์ธ์‹ ํ•  ์ˆ˜์—†๋Š” WebSocket ์—ฐ๊ฒฐ ์˜ต์…˜`agent`,`perMessageDeflate`,`pfx`,`key`,`passphrase`,`cert`,`ca`,`ciphers`,`rejectUnauthorized`์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„`headers` ์•„๋ž˜์— ๋„ฃ์œผ๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๊นŒ?

์— ๋งŒ๋“  2019๋…„ 04์›” 15์ผ  ยท  49์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: socketio/socket.io-client

๋‹น์‹ ์€ :

  • [x] ๋ฒ„๊ทธ๋ณด๊ณ 
  • [] ๊ธฐ๋Šฅ ์š”์ฒญ

ํ˜„์žฌ ํ–‰๋™

๋นˆ React Native Expo ํ”„๋กœ์ ํŠธ์— socket.io-client ๋ฅผ ์„ค์น˜ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋…ธ๋ž€์ƒ‰ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Unrecognized WebSocket connection option(s) `agent`, `perMessageDeflate`, `pfx`, `key`, `passphrase`, `cert`, `ca`, `ciphers`, `rejectUnauthorized`. Did you mean to put these under `headers`?

์žฌํ˜„ ๋‹จ๊ณ„ (ํ˜„์žฌ ๋™์ž‘์ด ๋ฒ„๊ทธ ์ธ ๊ฒฝ์šฐ)

yarn add socket.io-client

React Native ํ”„๋กœ์ ํŠธ์˜ App.js์—์„œ :

import React from 'react';
import { YellowBox } from 'react-native';
import io from 'socket.io-client';

YellowBox.ignoreWarnings(['Remote debugger']);

import AppContainer from './config/routing';

export default class App extends React.Component {
    constructor(props) {
        super(props);
    }

    componentWillMount() {
        const socket = io('http://10.0.60.26:3000', {
            forceNew: true
        });
        socket.on('connect', () => console.log('Connection'));
    }

    render() {
        return <AppContainer />;
    }
}

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‚˜๋ฅผ ์œ„ํ•ด 2.1.1๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œํ–ˆ์„ ๋•Œ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.
yarn add [email protected]

์ฒ˜์Œ์—๋Š” ํŒจํ‚ค์ง€์˜ ๋‹ค๋ฅธ ๋ถ€ ๋ฒ„์ „์„ ํ—ˆ์šฉํ•˜๋Š” socket.io-client@^2.1.1 ๋ฒ„์ „ ์•ž์— ^ ๊ธฐํ˜ธ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  49 ๋Œ“๊ธ€

๊ฐ™์€ ๋ฌธ์ œ :(

+1

+1

+1

์ ์–ด๋„ 12 ์›” 18 ์ผ๋ถ€ํ„ฐ ๋ฌธ์ œ๊ฐ€ ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

+1

+1

+1

+1

React-Native์—์„œ socket.io (2.2.0)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์—ฌ์ „ํžˆ์ด ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์žฅ์น˜ ํ™”๋ฉด์˜ ๋…ธ๋ž€์ƒ‰ ์ƒ์ž๋ฅผ ์Œ์†Œ๊ฑฐ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { YellowBox } from 'react-native'

YellowBox.ignoreWarnings([
  'Unrecognized WebSocket connection option(s) `agent`, `perMessageDeflate`, `pfx`, `key`, `passphrase`, `cert`, `ca`, `ciphers`, `rejectUnauthorized`. Did you mean to put these under `headers`?'
])

ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์ฝ˜์†”์—์ด ์„ฑ๊ฐ€์‹  ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค ...

"socket.io-client"๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œ : "2.1.0"๋ฐ ๋ชจ๋‘ OK

๋‚˜๋ฅผ ์œ„ํ•ด 2.1.1๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œํ–ˆ์„ ๋•Œ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.
yarn add [email protected]

์ฒ˜์Œ์—๋Š” ํŒจํ‚ค์ง€์˜ ๋‹ค๋ฅธ ๋ถ€ ๋ฒ„์ „์„ ํ—ˆ์šฉํ•˜๋Š” socket.io-client@^2.1.1 ๋ฒ„์ „ ์•ž์— ^ ๊ธฐํ˜ธ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์—ฌ์ „ํžˆ ๋ฌธ์ œ @ 2.2.0

socket.io-client๋ฅผ 1.7.2๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œ ํ•ด๋ณด์‹ญ์‹œ์˜ค.

์—ฌ์ „ํžˆ ๋ฌธ์ œ @ ^ 2.3.0

react-native์—์„œ ์—ฌ์ „ํžˆ v2.3.0 ๋ฌธ์ œ

@ 2.1.1์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ 2.3.0์€ RN 0.61.1์— ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ์–ด๋–ค ํ•ด๊ฒฐ์ฑ…๋„

๋ฐ˜์‘ ๋„ค์ดํ‹ฐ๋ธŒ์™€ ํ•จ๊ป˜ ์—ฌ์ „ํžˆ ๋ฌธ์ œ v2.3.0

์–˜๋“ค ์•„! v2.1.1 ๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œํ•˜์—ฌ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ „ ๋ฒ„์ „์„ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ์บ์‹œ๋ฅผ ์ง€์›Œ์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. package.json์—์„œ socket.io-client๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  package-lock / yarn.lock ํŒŒ์ผ์„ ๋” ์ž˜ ์‚ญ์ œํ•˜์‹ญ์‹œ์˜ค.
  2. ์ „์ฒด node_modules ํด๋” ์‚ญ์ œ (์ƒˆ๋กœ ์‹œ์ž‘)
  3. npm ์„ค์น˜ ์†Œ์ผ“.

๋๋‚œ! ์ด๊ฒƒ์€ react-native ๋ฐ react-native-web์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!

๋‚˜๋Š” react-native: 0.61.4 ์™€ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์ง€๋งŒ ์–ด๋–ป๊ฒŒ ๋“  ์•ฑ์ด ์ถฉ๋Œํ•˜๊ณ  ๊ฒฝ๊ณ ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ๋˜๋Š” ๋‹ค๋ฅธ ์†Œ์ผ“ ๊ด€๋ จ ๋ฌธ์ œ์ธ์ง€ ์•Œ ์ˆ˜ ์—†์ง€๋งŒ ์†Œ์ผ“์— ์—ฐ๊ฒฐํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์•ฑ์ด ๋‹ซํž™๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‚ด conf์ž…๋‹ˆ๋‹ค.
{ autoConnect: false, reconnectionDelay: 1000, reconnection: true, transports: ['websocket'], agent: false, // [2] Please don't set this to true upgrade: false, rejectUnauthorized: false }

์†Œ์ผ“์ด ์ด๋ฏธ ์—ฐ๊ฒฐ๋œ ๊ฒฝ์šฐ socket.open ์ด (๊ฐ€) ์ถฉ๋Œํ•ฉ๋‹ˆ๊นŒ?

์ด ๊ฒฝ๊ณ ๋Š” ์—ฌ๊ธฐ์—์„œ ReactNative/WebSocket.js:117 ์˜ํ•ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. EngineIO (๋‚ด๋ถ€์—์„œ SocketIO์— ์˜ํ•ด ์‚ฌ์šฉ๋จ)๋Š” ๋‹ค์Œ ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” opts ์ „๋‹ฌ๋˜๋Š” EngineIO/websocket.js:121 ๋ฅผ ํ†ตํ•ด ๋…ธ์ถœ ๋œ ReactNative WebSocket ๊ตฌํ˜„์„ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ์–ธ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กญ๊ฒŒ๋„ EngineIO ๊ด€๋ฆฌ์ž๊ฐ€ ์ฃผ์„์„ ํ†ตํ•ด ์„ค๋ช…ํ•˜๋Š” ์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์†์„ฑ์€ "Node.js ํด๋ผ์ด์–ธํŠธ ์šฉ SSL ์˜ต์…˜"์ž…๋‹ˆ๋‹ค.

์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ EngineIO/websocket.js:114 ์กฐ์ž‘ํ•˜๋Š” opts ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋“  ์™ธ๋ถ€ ํ‚ค๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ์›น ์†Œ์ผ“ ์ƒ์„ฑ์ž์— ์ฃผ์–ด์ง„ opts ์„ฑ๊ณต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ๊ณ ๋ฅผ ์ค‘์ง€๋ฅผ 1 ๋“ฑ ( omit ์€ Lodash์—์„œ ๊ฐ€์ ธ ์˜ค๋ฉฐ ๋‹ค์‹œ ์ž‘์—… ํ•  ์ˆ˜ ์žˆ์Œ).

// lib/transports/websocket.js
...
if (this.isReactNative) {
  // prettier-ignore
  opts = omit(opts, ['agent', 'perMessageDeflate', 'pfx', 'key', 'passphrase', 'cert', 'ca', 'ciphers', 'rejectUnauthorized']);
}
...

๋‹น์‹ ์€ ๋‹จ์ˆœํžˆ ํ†ตํ•ด ๊ฒฝ๊ณ  ์Œ์†Œ๊ฑฐ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ์†”๋ฃจ์…˜์„ ์ฐพ๊ณ  ์žˆ๋‹ค๋ฉด YellowBox.ignoreWarnings ๋‹น์‹ ์€ ์™„์ „ํžˆ ๋ฌด์‹œํ•  ์ˆ˜ doOpen ์ •์˜ EngineIO/websocket.js:87 ์ด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ญ”๊ฐ€๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ , ReactNative ํ”„๋กœ์ ํŠธ์˜ ์ง„์ž… ์  (์ผ๋ฐ˜์ ์œผ๋กœ index.js ํ•ฉ๋‹ˆ๋‹ค.

// index.js
...
+ import 'patches/EngineIOHeaderWarning';
...
// patches/EngineIOHeaderWarning.js
const WS = require('engine.io-client/lib/transports/websocket');

var WebSocketImpl = WebSocket; // eslint-disable-line no-undef

WS.prototype.doOpen = function() {
  if (!this.check()) {
    // let probe timeout
    return;
  }

  var uri = this.uri();
  var protocols = this.protocols;
  var opts = {};

  if (this.extraHeaders) {
    opts.headers = this.extraHeaders;
  }
  if (this.localAddress) {
    opts.localAddress = this.localAddress;
  }

  try {
    this.ws = new WebSocketImpl(uri, protocols, opts);
  } catch (err) {
    return this.emit('error', err);
  }
};

์ „๋ฐ˜์ ์œผ๋กœ, this.isReactNative ๋ฅผ ํ†ตํ•ด ReactNative์—์„œ ์‚ฌ์šฉํ•  ๋•Œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ์ถ”๊ฐ€ opts ๋ฅผ ์ œ์™ธํ•˜๊ธฐ ์œ„ํ•ด EngineIO์— ๋Œ€ํ•œ pull ์š”์ฒญ์„ ์ƒ์„ฑํ•˜๋ฉด ํ•ด๋‹น ์†Œ์ผ“์—์„œ SocketIO ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์— ๋Œ€ํ•ด์ด ๊ฒฝ๊ณ ๋ฅผ ์–ต์ œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ReactNative ํ”„๋กœ์ ํŠธ.

๋‹น์‹ ์€ :

  • [x] _bug_ ์‹ ๊ณ 
  • [] _feature_ ์š”์ฒญ

ํ˜„์žฌ ํ–‰๋™

๋นˆ React Native Expo ํ”„๋กœ์ ํŠธ์— socket.io-client ๋ฅผ ์„ค์น˜ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋…ธ๋ž€์ƒ‰ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Unrecognized WebSocket connection option(s) `agent`, `perMessageDeflate`, `pfx`, `key`, `passphrase`, `cert`, `ca`, `ciphers`, `rejectUnauthorized`. Did you mean to put these under `headers`?

์žฌํ˜„ ๋‹จ๊ณ„ (ํ˜„์žฌ ๋™์ž‘์ด ๋ฒ„๊ทธ ์ธ ๊ฒฝ์šฐ)

yarn add socket.io-client

React Native ํ”„๋กœ์ ํŠธ์˜ App.js์—์„œ :

import React from 'react';
import { YellowBox } from 'react-native';
import io from 'socket.io-client';

YellowBox.ignoreWarnings(['Remote debugger']);

import AppContainer from './config/routing';

export default class App extends React.Component {
    constructor(props) {
        super(props);
    }

    componentWillMount() {
        const socket = io('http://10.0.60.26:3000', {
            forceNew: true
        });
        socket.on('connect', () => console.log('Connection'));
    }

    render() {
        return <AppContainer />;
    }
}

๋‚ด ์†”๋ฃจ์…˜ :

๋‹ค์Œ๊ณผ ๊ฐ™์ด useState์— ์†Œ์ผ“์„ ์ €์žฅํ•˜์‹ญ์‹œ์˜ค.

'socket.io-client'์—์„œ io ๊ฐ€์ ธ ์˜ค๊ธฐ;
// ...

const [socket] = useState(() => io('SERVER_URL'));

๋ฌธ์ œ ํ•ด๊ฒฐ๋จ.

์ œ ๊ฒฝ์šฐ์—๋Š” ๋กœ์ปฌ socket.io ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ๋•Œ v2.3์ด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์›๊ฒฉ socket.io ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์„œ๋ฒ„ ์†Œ์Šค๊ฐ€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ socket.io ํด๋ผ์ด์–ธํŠธ ๋ฒ„์ „์„ 2.1.1๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ฒฝ๊ณ ๋Š” ์—ฌ๊ธฐ์—์„œ ReactNative/WebSocket.js:117 ์˜ํ•ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. EngineIO (๋‚ด๋ถ€์—์„œ SocketIO์— ์˜ํ•ด ์‚ฌ์šฉ๋จ)๋Š” ๋‹ค์Œ ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” opts ์ „๋‹ฌ๋˜๋Š” EngineIO/websocket.js:121 ๋ฅผ ํ†ตํ•ด ๋…ธ์ถœ ๋œ ReactNative WebSocket ๊ตฌํ˜„์„ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ์–ธ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กญ๊ฒŒ๋„ EngineIO ๊ด€๋ฆฌ์ž๊ฐ€ ์ฃผ์„์„ ํ†ตํ•ด ์„ค๋ช…ํ•˜๋Š” ์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์†์„ฑ์€ "Node.js ํด๋ผ์ด์–ธํŠธ ์šฉ SSL ์˜ต์…˜"์ž…๋‹ˆ๋‹ค.

์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ EngineIO/websocket.js:114 ์กฐ์ž‘ํ•˜๋Š” opts ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋“  ์™ธ๋ถ€ ํ‚ค๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ์›น ์†Œ์ผ“ ์ƒ์„ฑ์ž์— ์ฃผ์–ด์ง„ opts ์„ฑ๊ณต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ๊ณ ๋ฅผ ์ค‘์ง€๋ฅผ 1 ๋“ฑ ( omit ์€ Lodash์—์„œ ๊ฐ€์ ธ ์˜ค๋ฉฐ ๋‹ค์‹œ ์ž‘์—… ํ•  ์ˆ˜ ์žˆ์Œ).

// lib/transports/websocket.js
...
if (this.isReactNative) {
  // prettier-ignore
  opts = omit(opts, ['agent', 'perMessageDeflate', 'pfx', 'key', 'passphrase', 'cert', 'ca', 'ciphers', 'rejectUnauthorized']);
}
...

๋‹น์‹ ์€ ๋‹จ์ˆœํžˆ ํ†ตํ•ด ๊ฒฝ๊ณ  ์Œ์†Œ๊ฑฐ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ์†”๋ฃจ์…˜์„ ์ฐพ๊ณ  ์žˆ๋‹ค๋ฉด YellowBox.ignoreWarnings ๋‹น์‹ ์€ ์™„์ „ํžˆ ๋ฌด์‹œํ•  ์ˆ˜ doOpen ์ •์˜ EngineIO/websocket.js:87 ์ด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ญ”๊ฐ€๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ , ReactNative ํ”„๋กœ์ ํŠธ์˜ ์ง„์ž… ์  (์ผ๋ฐ˜์ ์œผ๋กœ index.js ํ•ฉ๋‹ˆ๋‹ค.

// index.js
...
+ import 'patches/EngineIOHeaderWarning';
...
// patches/EngineIOHeaderWarning.js
const WS = require('engine.io-client/lib/transports/websocket');

var WebSocketImpl = WebSocket; // eslint-disable-line no-undef

WS.prototype.doOpen = function() {
  if (!this.check()) {
    // let probe timeout
    return;
  }

  var uri = this.uri();
  var protocols = this.protocols;
  var opts = {};

  if (this.extraHeaders) {
    opts.headers = this.extraHeaders;
  }
  if (this.localAddress) {
    opts.localAddress = this.localAddress;
  }

  try {
    this.ws = new WebSocketImpl(uri, protocols, opts);
  } catch (err) {
    return this.emit('error', err);
  }
};

์ „๋ฐ˜์ ์œผ๋กœ, this.isReactNative ๋ฅผ ํ†ตํ•ด ReactNative์—์„œ ์‚ฌ์šฉํ•  ๋•Œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ์ถ”๊ฐ€ opts ๋ฅผ ์ œ์™ธํ•˜๊ธฐ ์œ„ํ•ด EngineIO์— ๋Œ€ํ•œ pull ์š”์ฒญ์„ ์ƒ์„ฑํ•˜๋ฉด ํ•ด๋‹น ์†Œ์ผ“์—์„œ SocketIO ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์— ๋Œ€ํ•ด์ด ๊ฒฝ๊ณ ๋ฅผ ์–ต์ œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ReactNative ํ”„๋กœ์ ํŠธ.

๊ท€ํ•˜์˜ ์ฝ”๋“œ๋กœ ์ธํ•ด ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์œผ๋ฉฐ EngineIO์˜ ์˜๋„ ๋œ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋˜์—ˆ์œผ๋ฏ€๋กœ ํ•ด๋‹น ์˜ต์…˜์„ if ๋ฌธ์œผ๋กœ ๋ž˜ํ•‘ํ–ˆ์ง€๋งŒ ์ œ์•ˆํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํŒจ์น˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

// patches/EngineIOHeaderWarning.js
const WS = require('engine.io-client/lib/transports/websocket');

var WebSocketImpl = WebSocket; // eslint-disable-line no-undef

WS.prototype.doOpen = function() {
    if (!this.check()) {
        // let probe timeout
        return;
    }

    var uri = this.uri();
    var protocols = this.protocols;
    var opts = {};

    if(!this.isReactNative){
        opts.agent = this.agent;
        opts.perMessageDeflate = this.perMessageDeflate;

        // SSL options for Node.js client
        opts.pfx = this.pfx;
        opts.key = this.key;
        opts.passphrase = this.passphrase;
        opts.cert = this.cert;
        opts.ca = this.ca;
        opts.ciphers = this.ciphers;
        opts.rejectUnauthorized = this.rejectUnauthorized;
    }


    if (this.extraHeaders) {
        opts.headers = this.extraHeaders;
    }
    if (this.localAddress) {
        opts.localAddress = this.localAddress;
    }

    try {
        this.ws =
            this.usingBrowserWebSocket && !this.isReactNative
                ? protocols
                ? new WebSocketImpl(uri, protocols)
                : new WebSocketImpl(uri)
                : new WebSocketImpl(uri, protocols, opts);
    } catch (err) {
        return this.emit('error', err);
    }

    if (this.ws.binaryType === undefined) {
        this.supportsBinary = false;
    }

    if (this.ws.supports && this.ws.supports.binary) {
        this.supportsBinary = true;
        this.ws.binaryType = 'nodebuffer';
    } else {
        this.ws.binaryType = 'arraybuffer';
    }

    this.addEventListeners();
};

"socket.io-client"๋กœ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œ : "2.1.0"๋ฐ ๋ชจ๋‘ OK

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ์ž˜ ์ดํ•ดํ•˜๊ณ  ์žˆ๋‹ค๋ฉด https://github.com/socketio/socket.io-client/commit/06e9a4ca2621176c30c352b2ba8b34fa42b8d0ba์— ๋„์ž… ๋œ ๊ด€๋ จ ์ข…์†์„ฑ ๋ฌธ์ œ

2.1.1 ๋กœ์˜ ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œ๋Š” ์‹ค์ œ๋กœ ์ž‘๋™ํ•˜์ง€๋งŒ 2 ๋…„ ๋œ ๋ฆด๋ฆฌ์Šค์— ๊ฐ‡ํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค.

@ptboyer๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๊ณ  ๋ฆด๋ฆฌ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ๊ฒฝ๊ณ ๊ฐ€ ํŒจํ‚ค์ง€์˜ ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ค๋‹ˆ๊นŒ? ๊ทธ๋ƒฅ ์„ค์ •ํ•˜๊ณ  ์ด๊ฒƒ์— ์–ฝ๋งค์ด๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ์—†์œผ๋ฉด ๋ฌด์‹œํ•ด๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๊ฐ™์€ ๊ฒƒ์„ ๊ถ๊ธˆํ•ดํ•˜๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•ด. ๋‚ด๊ฐ€ ๋งํ•  ์ˆ˜์žˆ๋Š” ํ•œ์ด ๊ฒฝ๊ณ ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@schumannd ์ด ๋ฌธ์ œ๋Š” ์ˆœ์ „ํžˆ ์˜ค๋ฅ˜ / ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€ ์Œ์†Œ๊ฑฐ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ์ ์œผ๋กœ์ด ๊ฒฝ๊ณ ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. :)

+1

๋‚˜๋Š” socket.io ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—ฌ์ „ํžˆ ์œ ์ง€๋˜๊ณ  ์žˆ๋Š”์ง€ ์•„๋‹Œ์ง€์— ๋Œ€ํ•œ ๊ณต์‹์ ์ธ ๋‹ต๋ณ€์ด๋‚˜ ๋‹ค๊ฐ€์˜ค๋Š” ์—…๋ฐ์ดํŠธ๋กœ ์ธํ•ด ๋งค์šฐ ๊ฑฑ์ •๋ฉ๋‹ˆ๋‹ค.

+1

+1

const _io = ioClient.connect(socketurl, { forceNode: true });
์ผ์ด์•ผ

@isthaison ๊ทธ๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

@isthaison ์ด ์ž‘๋™ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๋ชจ๋“  http ์š”์ฒญ์€ ๋งค์šฐ ๋Š๋ ค์ง‘๋‹ˆ๋‹ค ... ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค ...ํ•˜์ง€๋งŒ ...

{forceNode : true}

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ•œ ์œ ์ผํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

์ด ๊ฒฝ๊ณ ๋Š” ์—ฌ๊ธฐ์—์„œ ReactNative/WebSocket.js:117 ์˜ํ•ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. EngineIO (๋‚ด๋ถ€์—์„œ SocketIO์— ์˜ํ•ด ์‚ฌ์šฉ๋จ)๋Š” ๋‹ค์Œ ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” opts ์ „๋‹ฌ๋˜๋Š” EngineIO/websocket.js:121 ๋ฅผ ํ†ตํ•ด ๋…ธ์ถœ ๋œ ReactNative WebSocket ๊ตฌํ˜„์„ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๊ฐ€ ์–ธ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กญ๊ฒŒ๋„ EngineIO ๊ด€๋ฆฌ์ž๊ฐ€ ์ฃผ์„์„ ํ†ตํ•ด ์„ค๋ช…ํ•˜๋Š” ์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์†์„ฑ์€ "Node.js ํด๋ผ์ด์–ธํŠธ ์šฉ SSL ์˜ต์…˜"์ž…๋‹ˆ๋‹ค.
์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ EngineIO/websocket.js:114 ์กฐ์ž‘ํ•˜๋Š” opts ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋“  ์™ธ๋ถ€ ํ‚ค๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ์›น ์†Œ์ผ“ ์ƒ์„ฑ์ž์— ์ฃผ์–ด์ง„ opts ์„ฑ๊ณต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ๊ณ ๋ฅผ ์ค‘์ง€๋ฅผ 1 ๋“ฑ ( omit ์€ Lodash์—์„œ ๊ฐ€์ ธ ์˜ค๋ฉฐ ๋‹ค์‹œ ์ž‘์—… ํ•  ์ˆ˜ ์žˆ์Œ).

// lib/transports/websocket.js
...
if (this.isReactNative) {
  // prettier-ignore
  opts = omit(opts, ['agent', 'perMessageDeflate', 'pfx', 'key', 'passphrase', 'cert', 'ca', 'ciphers', 'rejectUnauthorized']);
}
...

๋‹น์‹ ์€ ๋‹จ์ˆœํžˆ ํ†ตํ•ด ๊ฒฝ๊ณ  ์Œ์†Œ๊ฑฐ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ์†”๋ฃจ์…˜์„ ์ฐพ๊ณ  ์žˆ๋‹ค๋ฉด YellowBox.ignoreWarnings ๋‹น์‹ ์€ ์™„์ „ํžˆ ๋ฌด์‹œํ•  ์ˆ˜ doOpen ์ •์˜ EngineIO/websocket.js:87 ์ด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ญ”๊ฐ€๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ , ReactNative ํ”„๋กœ์ ํŠธ์˜ ์ง„์ž… ์  (์ผ๋ฐ˜์ ์œผ๋กœ index.js ํ•ฉ๋‹ˆ๋‹ค.

// index.js
...
+ import 'patches/EngineIOHeaderWarning';
...
// patches/EngineIOHeaderWarning.js
const WS = require('engine.io-client/lib/transports/websocket');

var WebSocketImpl = WebSocket; // eslint-disable-line no-undef

WS.prototype.doOpen = function() {
  if (!this.check()) {
    // let probe timeout
    return;
  }

  var uri = this.uri();
  var protocols = this.protocols;
  var opts = {};

  if (this.extraHeaders) {
    opts.headers = this.extraHeaders;
  }
  if (this.localAddress) {
    opts.localAddress = this.localAddress;
  }

  try {
    this.ws = new WebSocketImpl(uri, protocols, opts);
  } catch (err) {
    return this.emit('error', err);
  }
};

์ „๋ฐ˜์ ์œผ๋กœ, this.isReactNative ๋ฅผ ํ†ตํ•ด ReactNative์—์„œ ์‚ฌ์šฉํ•  ๋•Œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ์ถ”๊ฐ€ opts ๋ฅผ ์ œ์™ธํ•˜๊ธฐ ์œ„ํ•ด EngineIO์— ๋Œ€ํ•œ pull ์š”์ฒญ์„ ์ƒ์„ฑํ•˜๋ฉด ํ•ด๋‹น ์†Œ์ผ“์—์„œ SocketIO ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์— ๋Œ€ํ•ด์ด ๊ฒฝ๊ณ ๋ฅผ ์–ต์ œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ReactNative ํ”„๋กœ์ ํŠธ.

๊ท€ํ•˜์˜ ์ฝ”๋“œ๋กœ ์ธํ•ด ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์œผ๋ฉฐ EngineIO์˜ ์˜๋„ ๋œ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋˜์—ˆ์œผ๋ฏ€๋กœ ํ•ด๋‹น ์˜ต์…˜์„ if ๋ฌธ์œผ๋กœ ๋ž˜ํ•‘ํ–ˆ์ง€๋งŒ ์ œ์•ˆํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํŒจ์น˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

// patches/EngineIOHeaderWarning.js
const WS = require('engine.io-client/lib/transports/websocket');

var WebSocketImpl = WebSocket; // eslint-disable-line no-undef

WS.prototype.doOpen = function() {
    if (!this.check()) {
        // let probe timeout
        return;
    }

    var uri = this.uri();
    var protocols = this.protocols;
    var opts = {};

    if(!this.isReactNative){
        opts.agent = this.agent;
        opts.perMessageDeflate = this.perMessageDeflate;

        // SSL options for Node.js client
        opts.pfx = this.pfx;
        opts.key = this.key;
        opts.passphrase = this.passphrase;
        opts.cert = this.cert;
        opts.ca = this.ca;
        opts.ciphers = this.ciphers;
        opts.rejectUnauthorized = this.rejectUnauthorized;
    }


    if (this.extraHeaders) {
        opts.headers = this.extraHeaders;
    }
    if (this.localAddress) {
        opts.localAddress = this.localAddress;
    }

    try {
        this.ws =
            this.usingBrowserWebSocket && !this.isReactNative
                ? protocols
                ? new WebSocketImpl(uri, protocols)
                : new WebSocketImpl(uri)
                : new WebSocketImpl(uri, protocols, opts);
    } catch (err) {
        return this.emit('error', err);
    }

    if (this.ws.binaryType === undefined) {
        this.supportsBinary = false;
    }

    if (this.ws.supports && this.ws.supports.binary) {
        this.supportsBinary = true;
        this.ws.binaryType = 'nodebuffer';
    } else {
        this.ws.binaryType = 'arraybuffer';
    }

    this.addEventListeners();
};

const _io = ioClient.connect(socketurl, { forceNode: true });
์ผ์ด์•ผ

์ €์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

"socket.io-client": "^2.3.0"

const socket = io(host, { forceNode: true });

const _io = ioClient.connect(socketurl, { forceNode: true });
์ผ์ด์•ผ

์ €์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

"socket.io-client": "^2.3.0"

const socket = io(host, { forceNode: true });

๊ทธ๊ฒƒ์€ ๋‚˜์—๊ฒŒ๋„ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค! ํฐ ๊ฐ์‚ฌ๋ฅผ ๋“œ๋ฆฐ๋‹ค

ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋งŒํ•˜๋ฉด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!
socket = io.connect('SOCKET_URL_HERE', { jsonp: false, agent: '-', pfx: '-', cert: '-', ca: '-', ciphers: '-', rejectUnauthorized: '-', perMessageDeflate: '-' });

const _io = ioClient.connect (socketurl, {forceNode : true});

์ด๊ฒƒ์€ ๊ฒฝ๊ณ ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€๋งŒ ๋‚ด ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ์ •๋ง ๋Š๋ฆฌ๊ฒŒ (์‹ค์ œ๋กœ ์‹œ๊ฐ„ ์ดˆ๊ณผ)ํ•˜๋ฏ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

const _io = ioClient.connect (socketurl, {forceNode : true});

์ด๊ฒƒ์€ ๊ฒฝ๊ณ ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€๋งŒ ๋‚ด ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ์ •๋ง ๋Š๋ฆฌ๊ฒŒ (์‹ค์ œ๋กœ ์‹œ๊ฐ„ ์ดˆ๊ณผ)ํ•˜๋ฏ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—๋„ ๋™์ผ : ์—ฐ๊ฒฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ!

froceNode๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  2.1.0 ๋‹ค์šด ๊ทธ๋ ˆ์ด๋“œํ–ˆ๋Š”๋ฐ ์ œ๋Œ€๋กœ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ ์žฅ์น˜์˜ IP๊ฐ€ ์•„๋‹Œ localhost๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ œ๊ฐ€์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ @SaveYourTime , ์ €๋Š” "socket.io-client": "^2.3.0"
์—ฌ๊ธฐ https://socket.io/docs/client-api/๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค
forceNode ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ด์œ 

์ด ๋ฌธ์ œ๋Š” engine.io-client v3.4.3์—์„œ ์ˆ˜์ •๋˜์–ด์•ผํ•˜๋ฏ€๋กœ yarn.lock ํŒŒ์ผ๊ณผ node_modules ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์‚ญ์ œ ํ•œ ๋‹ค์Œ yarn install ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ๋งŒํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค.

ref https://github.com/socketio/engine.io-client/commit/2f5c948abe8fd1c0fdb010e88f96bd933a3792ea

@BassemN ์•„๋งˆ๋„ yarn.lock ํŒŒ์ผ์„ ์‚ญ์ œํ•˜๋Š” ๋Œ€์‹  yarn upgrade-interactive ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒ„์ „์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฒ”ํ”„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

ํŒจํ‚ค์ง€๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œ ํ•  ๋•Œ๋งˆ๋‹ค ํŒŒ์ผ์„ ์™„์ „ํžˆ ํŒŒ๊ดดํ•˜๋ฉด "์ž ๊ธˆ"ํŒŒ์ผ์ด๋ผ๋Š” ๊ฐœ๋…์— ๋‹ค์†Œ ๋ฐ˜ ์ง๊ด€์ ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ๐Ÿ˜…

https://github.com/socketio/engine.io-client/commit/e5bc1063cc90a7b6262146c7b5338ffff1ff9e5b ( [email protected] ๋ฐ [email protected] )๋กœ ์ˆ˜์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

forceNode ์˜ต์…˜๊ณผ ๊ด€๋ จํ•˜์—ฌ React Native๋Š” ์‹ค์ œ๋กœ WebSocket ( ref )์„ ์ง€์›ํ•˜๋ฏ€๋กœ forceNode: true ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰