본문 바로가기
프로그래밍 공부(정리)/React-Native

[RN 0.67] RN과 ejabberd서버 간 XMPP 통신하기

by 프룹 2022. 4. 2.
반응형

리액트에서 채팅을 구현하려고 공부를 하면서 채팅 통신에 WebSocket / XMPP 방식 중 하나를 결정해서 쓰면 된다는 것을 알게 되었다. (Pooling, Long-Pooling, Streaming은 옛날 방식인 것 같다)

 

https://medium.com/@thinkwik/web-sockets-vs-xmpp-which-is-better-for-chat-application-113e3520b32

위 블로그 글을 읽으면서 '보안'의 요소 때문에라도 XMPP를 써야겠다는 생각을 하게 되었다.

 

XMPP서버는 다양하게 존재한다.

이 중에서 필자는 ejabberd를 선택하였다. 해당 서버를 선택한 이유는 그냥 전체적으로 사이트가 깔끔하고, 설명이 많은 것 같아서? 선택하게 되었다. 뭔가 폴트 톨러런스, 스케일 등 16 ram에 4 core면 200K~300K의 메시지를 견딜 수 있다고 하는 등 상업용으로 좋은 것 같아서..?

 

아무튼!

 

항상 찬양하는 도커에 ejabberd를 설치했다. 우여곡절이 많았다... 이다음 포스팅으로 ejabberd를 도커에 설치하는 방법을 올려야겠다.

# XMPP 서버 동작 확인

설치한 ejabberd가 정상적으로 작동하는지 확인하기 위해서 잘 만들어진 XMPP Client를 통해 확인을 해봤다.

 

Spark Client라는 프로그램을 설치한 후

등록한 사용자를 입력하고 로그인하면

이렇게 ejabberd 서버에 액세스가 되고, spark에는 '온라인'으로 바뀌는 것을 볼 수 있다.

 

여기까지 잘 되었다면, ejabberd 서버 설치와 XMPP 프로토콜은 정상적으로 동작하는 것이다.

 

# RN에서 XMPP 사용하기

AOS와 IOS에서 XMPP를 지원하는 다양한 라이브러리가 존재한다.

출처: ejabberd 사이트

이곳에서 전체적인 XMPP Client를 확인할 수 있다.

그러나 필자는 능력의 한계로 (Xcode로 써본 적도 없는,,, Object-C, Swift를 배우면서... 하기엔) 최대한 aos, ios를 동시에 지원하는 라이브러리를 찾게 되었다.

2개의 후보가 있었는데, xmpp.js를 사용하지 않는 이유는

xmpp.js에서는 rn에서 websocket만 지원하기 때문이다. 그럼 ejabberd를 안 쓸 텐데..

 

그래서 이제, react-native-xmpp 라이브러리를 이용해 XMPP 통신을 하는 방법을 알아보자!

18년도가 마지막 업데이트라 좀 아쉽지만, 그 나름 잘 만들어서 고칠 게 없다고 생각해야겠다.

아무튼 해당 사이트에서 시키는 대로 구현을 하면 서버 연결이 안 된다. 

 

보면 user2@localhost로 연결을 했는데, 연결에 실패했다는 문구가 뜬다.

이유는

xmpp에서는 계정을 기본적으로 "아이디@도메인"으로 설정해야만 한다.

ejabberd 서버 환경 설정을 하는 ejabberd.yml 파일의 일부이다.

보면 hosts가 localhost이기 때문에 도메인은 localhost이며, 사용자 계정은 "아이디@localhost"로 만들어야 한다.

 

yml에 등록되지 않는 도메인을 사용하게 되면

가령, user3@192.168.1.243이라는 계정을 생성한다고 입력하면

다음과 같이 Unknown virtual host라는 문구와 함께 계정 생성에 실패한다

 

그래서 위 spark client에서 사용자명이 user1, 도메인이 localhost로 설정한 것이다.

이때 연결하는 호스트는 192.168.1.243이다.

그니까 user1@localhost를 192.168.1.243으로 연결시켜야 ejabberd서버로 정상적으로 연결이 되는 것이다.

 

근데 설명에서는

해당 라이브러리에서 보여주는 예제는 connect에 호스트를 쓰지 않아도 연결이 되고, 통신이 되는 점을 확인할 수 있다.

그건 아마 라이브러리 작성자의 경우엔 도메인과 호스트의 주소가 같기 때문일 것이다.

 

호스트를 따로 주지 않으면 호스트는 도메인을 그대로 사용한다.

 

이는 해당 라이브러리의 index.js에 connect라는 함수를 확인해보면 알 수 있다.

즉, user2@localhost를 localhost에 연결하려고 해서 실패를 하는 것이다.

(사실, 이해가 안 가는 게 ejabberd가 local에 설치된 게 맞아서, localhost로 연결하면 돼야 할 텐데,,, 안 된다.)

 

그니까 결국엔 react-native-xmpp 라이브러리를 사용해서 연결을 시도했는데, 계속 실패한다면

도메인과 호스트를 달리 했어야 했는데, 그렇게 하지 않았기 때문이라 볼 수 있다

그래서 connet함수를 사용할 적에 파리미터로 호스트도 같이 주면 되는데,

불행히도 파라미터 순서가 hostname이 auth보다 뒤에 있어서 auth도 설정해 줘야 hostname도 설정할 수 있다.

때문에 index.js에서 connet 파라미터 순서를 위 이미지처럼 바꿔줘야 한다.

 

username, password, auth, hostname, port -> username, password, hostname, auth, port로!!

 

파라미터를 순서를 변경한 후 

이렇게 인자를 넘기면

 

다음과 같이 user1, user2 둘 다 연결에 성공했음을 알 수 있다.

위 사진은 user1은 spark에서 연결한 것이고, user2는 rn에서 xmpp를 사용해서 연결한 것이다.

 

그리곤 통신을 해보면

 

왼쪽이 RN의 node.js 창이고, 오른쪽이 spark 화면으로, spark에서 good, hhhhhh를 보내면 

node.js에서 해당 값을 받아 오게 된다.

null은 spark에서 키보드를 누를 때마다 넘어오게 된다.

왜 그, line 채팅 보면 상대방이 키를 치면 치는 중이라는 표식이 뜨는데, null이 계속 넘어오는 것을 통해서 그런 판단을 할 수 있나 보다. 

 

결론은, 

만약에 xmpp 라이브러리가 잘 안 된다면, 해당 라이브러리가 이상한 게 아니고, 

도메인, 호스트 이름이 달라서 그런 상황이 발생할 수 있으니, 참고하면 좋을 것 같다.

 

그냥 안 되는 줄 알고,,, 2일이나 끙끙 겨렸다...

 

----- 참고 사항 -----

 

이거 꼭 해줘야 하는지 확실치 않지만, 필자는 하지 않았다.

일단, 말하고 싶은 건

 

1. MainReactPackage() 그냥 쓰면 오류 난다.

위 라이브러리 import 해야 한다.

 

2. 패키지 return 하는 방식이 바뀌었다.

주석으로도 남겨져 있는데, packages.add() 함수에서 추가한 다음에

return packages를 해야 한다.

 

이렇게!

근데, 저거 add 한 다음에 return해도 오류 난다. 

 

그니까 결국엔 rn 하고 xmpp 하고 link안 되어 있으면 설정하라는 거 같은데, 

rn 0.6부터는 autolink가 돼서 필요 없는 거 같다. 

필자는 그냥 주석처리를 했는데, 관계없이 동작한다.

오히려 하면 컴파일이 안된다.

반응형

댓글