기본 콘텐츠로 건너뛰기

firebase 일기(+expo)

firebase instance를 만들자.
https://console.firebase.google.com/project/<YOURAPP>-90431/overview 로 들어가보면
Welcome to Firebase! Get started here. 라고 반긴다.
필요한 설정을 복사하자. Add Firebase to your web app 를 눌러
<script src="https://www.gstatic.com/firebasejs/4.6.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "ㅌㅌㅌㅌㅌㅌㅌㅌ",
    authDomain: "ㅅㅅㅅㅅ-90431.firebaseapp.com",
    databaseURL: "https://ㅅㅅㅅㅅ-90431.firebaseio.com",
    projectId: "ㅅㅅㅅㅅ-90431",
    storageBucket: "ㅅㅅㅅㅅ-90431.appspot.com",
    messagingSenderId: "11111111111"
  };
  firebase.initializeApp(config);
</script>
이 부분 중 config만 복사.
Authentication > sign-in method 에 몇개 연결하고 Template을 한번 슥 본다.
음 다국어 처리가 되있군. 굿.
Database, Storage, Hosting, Functions 죄다 켜고.

Grow 에 Remote Config라는게 있어서 Software Version 같은 걸 한번 넣어봤다. 프로그래마틱하게도 설정 가능한 거 같다. 잘 모르겠다.
https://firebase.google.com/docs/remote-config/?authuser=0 일단 킵

https://github.com/jsappme/react-native-firebase-starter
설정 볼만하다. code-push도 있고 무제한 push notification 서비스인 https://onesignal.com 도 눈에 띤다. 근데 firebase notification 도 무료에 무제한 아닌가?
Analytics, App Indexing, Authentication, Dynamic Links, Invites, Notifications, Crash Reporting & Remote Config 모두 무제한 무료 맞네.

react-native(+expo)용 드라이버로는 고심끝에 그냥 npm install firebase --save 로 결정. 다른 것들은 문제가 있거나 deprecated 되거나 뭐 그렇네. 순정으로 가자.

web에서 간단하게 연습.
테스트 할 데이터는 이와 같다.
firebase.database()
  .ref('rooms/muka/messages')
  .on 'value', (o) ->
    # [{"text":"블라블라"},{"text":"요로호초"}]
    console.log JSON.stringify(o.val())
# added 될 때 마다
firebase.database()
  .ref('rooms/muka/messages')
  .on 'child_added', (o) ->
    # key:0. val();"text":"블라블라"
    # key:1. val();"text":"블라블라"
    console.log JSON.stringify( Object.assign key: o.key, o.val() )
.on에서 콜백으로 event를 처리하는데 value랑 child_added의 작동이 좀 다르다.
value는 전체 콜렉션을 한번에 가져오는 반면(근데 value라고 해도 react-native에선 그렇게 배열로 작동 안한다.
child_added는 Meteo의 observe처럼 건별로 발생한다.

다음은 notification 차례

Firebase console 에서 grow > Notification 가서 iOS든 Android든 하나 추가.
GoogleService-Info.plist 를 쓸일이 있을지 모르겠는데 일단 받아는 두었다.

https://docs.expo.io/versions/latest/guides/push-notifications.html#content
Spoiler alert: it’s almost too easy. 쉬움 주의란닼ㅋㅋㅋ
일단 push 이니만큼 실기기를 준비하고 먼저 안드로이드 기준으로 테스트.

1. 사용자 기기를 백엔드에 등록.

expo를 navigation 포함 버전으로 생성했을 때 api/registerForPushNotificationsAsync.js 가 있는데
const PUSH_ENDPOINT = 'https://exponent-push-server.herokuapp.com/tokens';
이 부분을 수정해준다.
즉, functions 를 만들어야할 곳은 여기.
functions를 만들고 보자 firebase cli가 있으니 firebase init 해본다.

firebase database:get '/rooms/muka/messages' 오옹 이런걸로도 JSON 뽑아올 수 있네

보통은 인증서도 등록하고 할게 많은데 expo란 앱이 이미 등록이 되있을 것이니 절차가 간소해지긴 하겠다.

해야할 것은 일단 저 PUSH_ENDPOINT를 https://github.com/exponent/exponent-server-sdk-node 설치로 확인해보고 잘 되면 functions로 옮겨봐야하겠다.

https://github.com/expo/exponent-server-sdk-node/blob/master/src/ExpoClient.js
요약하면 아래의 요청을 POST로 보내면 된다는 소리다.
https://exp.host/--/api/v2/push/send
accept: application/json
accept-encoding: gzip, deflate
content-type: application/json
curl -H "Content-Type: application/json" -X POST https://exp.host/--/api/v2/push/send -d '{
  "to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
  "title":"hello",
  "body": "world"
}'
백엔드 서버는 바로 위의 curl의 역할을 수행하면 되고.
기기의 푸쉬토큰을 잘 기억하고 있으면 그만이다.
registerForPushNotificationsAsync.js 를 보면 이렇다. token 이외엔 보내주는게 없는데 일단 이대로라면 누가 누구인지 알 수 없으므로 전체 푸쉬를 하는 걸 구현한다고 생각하고 해보자.
  // POST the token to our backend so we can use it to send pushes from there
  return fetch(PUSH_ENDPOINT, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      token: {
        value: token,
      },
      /* 여기에 사용자 정보가 더 필요하다. */
    }),
  });
이걸 받아들일 수 있는지 해보자.
위의 fetch 부분을 curl로 쓰면 아마도
curl -H "Content-Type: application/json" -X POST https://localhost:3000 '{
  "token": {
    value: "xxxxxxxxxxxxx"
  }
'
이정도만 받아들일 수 있으면 될 것이다.

----------- ---------------

열심히 쓴 글이 날아갔다;;; 

안되겠다. 요약하자.
firebase functions를 사용하려면 node v6.11.1을 사용하자.
node v6.11.1은 Object.entries가 없다. polyfill(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill) 을 이용하자.
appspot.com 에 올려서 외부 REST call을 쓰려고 했으나 실패. 무료에서 과금으로 전환.
orderBy를 썼다면 rules에 json파일을 추가해야함. orderBy를 쓰는 ref와 같은 depth로
        "messages": {
          ".indexOn": ["createdAt"]
        }
와 같이 .indexOn을 넣어줘야함
functions에서 추가 데이터를 감지할 땐 functions.database.ref("rooms/{roomId}/messages/{messageId}").onCreate(event=>...)를 사용하고 event.data.val()과 event.data.key로 변경분을 체크.
functions안에서 데이터베이스를 다룰 땐 admin.database()객체를 사용. 쿼리도 once를 사용하여 한번만 사용한다. on을 사용하면 핸들러를 달아서 계속 감시하는 것이므로 적절치 않음. (예: admin.database().ref("deviceToken").once('value').then(tokenInfo=>...) )

댓글

이 블로그의 인기 게시물

cURL로 cookie를 다루는 법

http://stackoverflow.com/questions/22252226/passport-local-strategy-and-curl 레거시 소스를 보다보면 인증 관련해서 cookie를 사용하는 경우가 있는데 가령 REST 서버인 경우 curl -H "Content-Type: application/json" -X POST -d '{"email": "aaa@bbb.com", "pw": "cccc"}' "http://localhost/login" 이렇게 로그인이 성공이 했더라도 curl -H "Content-Type: application/json" -X GET -d '' "http://localhost/accounts/" 이런 식으로 했을 때 쿠키를 사용한다면 당연히 인증 오류가 날 것이다. curl의 --cookie-jar 와 --cookie 옵션을 사용해서 cookie를 저장하고 꺼내쓰자. 각각 옵션 뒤엔 저장하고 꺼내쓸 파일이름을 임의로 지정하면 된다. 위의 과정을 다시 수정해서 적용하면 curl -H --cookie-jar jarfile "Content-Type: application/json" -X POST -d '{"email": "aaa@bbb.com", "pw": "cccc"}' "http://localhost/login" curl -H --cookie jarfile "Content-Type: application/json" -X GET -d '' "http://localhost/accounts/" 이렇게 사용하면

MQTT 접속해제 - LWT(Last will and testament)

통신에서 중요하지만 구현이 까다로운 문제로 "상대방이 예상치 못한 상황으로 인하여 접속이 끊어졌을때"의 처리가 있다. 이것이 까다로운 이유는 상대방이 의도적으로 접속을 종료한 경우는 접속 종료 직전에 자신의 종료 여부를 알리고 나갈 수 있지만 프로그램 오류/네트웍 연결 강제 종료와 같은 의도치 않은 상황에선 자신의 종료를 알릴 수 있는 방법 자체가 없기 때문이다. 그래서 전통적 방식으로는 자신의 생존 여부를 계속 ping을 통해 서버가 물어보고 timeout 시간안에 pong이 안올 경우 서버에서 접속 종료를 인식하는 번거로운 방식을 취하는데 MQTT의 경우 subscribe 시점에서 자신이 접속 종료가 되었을 때 특정 topic으로 지정한 메시지를 보내도록 미리 설정할 수 있다. 이를 LWT(Last will and testament) 라고 한다. 선언을 먼저하고 브로커가 처리하게 하는 방식인 것이다. Last Will And Testament 라는 말 자체도 흥미롭다. 법률용어인데  http://www.investopedia.com/terms/l/last-will-and-testament.asp 대략 내가 죽으면 뒷산 xx평은 작은 아들에게 물려주고 어쩌고 하는 상속 문서 같은 내용이다. 즉, 내가 죽었을(연결이 끊어졌을) 때에 변호사(MQTT Broker - ex. mosquitto/mosca/rabbitMQ등)로 하여금 나의 유언(메시지)를 상속자(해당 토픽에 가입한 subscriber)에게 전달한다라는 의미가 된다. MQTT Client 가 있다면 한번 실습해보자. 여러가지가 있겠지만 다른 글에서처럼  https://www.npmjs.com/package/mqtt  을 사용하도록 한다. npm install mqtt --save 로 설치해도 되고 내 경우는 자주 사용하는 편이어서 npm install -g mqtt 로 전역설치를 했다. 호스트는 무료 제공하고 있는 test.mosquitto.org 를

MQTT Broker Mosquitto 설치 후 설정

우분투 기준 $ sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa $ sudo apt-get update 하고 $ sudo apt-get install mosquitto 으로 설치하면 서비스까지 착실하게 올라간다. 설치는 간단한데 사용자를 만들어야한다. /etc/mosquitto/mosquitto.conf 파일에서 권한 설정을 변경하자. allow_anonymous false 를 추가해서 아무나 못들어오게 하자. $ service mosquitto restart 서비스를 재시작. 이제 사용자를 추가하자. mosquitto_passwd <암호파일 경로명> <사용자명> 하면 쉽게 만들 수 있다. # mosquitto_passwd /etc/mosquitto/passwd admin Password:  Reenter password:  암호 넣어준다. 두번 넣어준다. 이제 MQTT 약을 열심히 팔아서 Broker 사글세방 임대업을 하자.