Firebase Cloud Messaging 서비스를 이용하여 나의 iOS 기기 및 Android 기기에 푸시 알람을 보내려고 한다.

이를 위해 Node js 를 이용하여 푸시 서버를 따로 둬서 내가 원하는 상황을 한번 구현해보도록 하자.

 

본격적으로 글에 들어가기에 앞서 해당 내용들을 진행하기 위한 선결조건으로서 다음 글을 완독하고 오길 권한다.

push 알람에 대한 이해를 돕는 글인데, 정말 잘 정리되어 있다.

https://tech.junhabaek.net/%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%9C%EB%B2%84-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-presentation-layer-3-%EC%9D%91%EB%8B%B5-%EC%9C%A0%ED%98%95%EC%97%90-%EB%94%B0%EB%A5%B8-variation-2-push-notification-1eacb4df4a7e

 

백엔드 서버 아키텍처 — Presentation Layer 3. 응답 유형에 따른 Variation 2— push notification

이 포스팅에서는 웹 서버의 응답 유형중 하나라고 볼 수 있는, push notification의 핵심 원리에 대해서 알아봅니다.

tech.junhabaek.net

 

목차

일단 다음과 같은 순서로 진행을 해볼 것이다.

1. Android 앱 만들기 및 Android 앱 Firebase에 등록

2. Android 앱 만들기 및 Android 앱 Firebase에 등록

3. Firebase - Node js 연결

4. Android(iOS)에서 토큰을 받기 위한 코드 작성

5. Push Notification 보내기

 

 

Android 앱 만들기

가장 먼저 앱을 만들어보자. 

 

안드로이드 스튜디오에서 앱을 하나 만든다.

 

Empty 프로젝트를 생성한다.

이 때 도메인은 조금 유니크하게 주자.

 

 

필자는 Minimum SDK는 26으로 설정했다.(oreo. galaxy s8 수준.)

 

firebase에서 '프로젝트 추가' 버튼을 누르고,

 

(Firebase에 계정이 있어서 필자는 그것으로 진행했다. 없으면 만들자.)

 

안드로이드 클릭

 

이제 아래와 같은 화면이 떴을텐데,

 

Package 이름의 경우 안드로이드 스튜디오의 manifest.xml에서 확인이 가능하고,

 

디버그 서명 인증서의 경우(SHA-1)

우측 상단 코끼리 모양 gradle 클릭 후 gradle signingReport를 입력하고 엔터를 누르면

조금 있다가 하단 터미널에 SHA1 의 정보가 나오니 그것을 붙여넣도록 하자.

 

이후 google-services.json을 다운하고, 

 

안드로이드 스튜디오에서 아래와 같이 열어주어

 

다음 그림처럼 `app` 폴더 안에 넣어준다.

 

이후 reload from disk로 해당 파일을 인식시켜 주자.

 

이후 '다음'을 눌러 아래 그림처럼 시키는 대로 파일을 적어준다.

(apply plugin: 'com.google.gms.google-services' 의 경우 해당 파일 맨 아래 적어주자.)

 

그런 다음 동기화를 한번 해주고(sync now),

콘솔로 이동한다.

 

빌드가 정상적으로 작동하는지도 한번 확인해주자.

(아무런 SDK가 없다면 하나 설치해주자. 필자는 android폰 실기기를 연결하여 썼다.)

 

이제 AndroidManifest.xml 파일을 다음과 같이 수정한다.

(아래에 내용 중 여러분의 파일에서 추가해야 할 부분은 

<uses-permission ~ 부분 및 <service ~ <service/> 부분이다.)

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kchoi.pushalarmtest">

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Pushalarmtest">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:name=".MyFirebaseMessagingService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>


    </application>

</manifest>

 

붙여 넣었다면 MyFirebaseMessagingService를 찾을 수 없다는 오류가 뜰 텐데, 이를 해결하기 위해 클래스를 하나 만들어주자. 클래스의 명은 똑같이 MyFirebaseMessagingService로 해준다.

(패키지명은 본인 것으로 맞추자)

package com.kchoi.pushalarmtest;

import android.util.Log;

import androidx.annotation.NonNull;

import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onNewToken(@NonNull String token) {
        super.onNewToken(token);

        Log.d("tag", "Refreshed token: " + token);

    }

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
    }
}

 

마지막으로 MainActivity.java 파일을 수정한다.

내용은 다음과 같이 맞춰준다.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FirebaseMessaging.getInstance().getToken()
            .addOnCompleteListener(new OnCompleteListener<String>() {
                @Override
                public void onComplete(@NonNull Task<String> task) {
                    if (!task.isSuccessful()) {
                        Log.w("TAG", "Fetching FCM registration token failed", task.getException());
                        return;
                    }

                    String msg = task.getResult();
                    Log.println(Log.INFO,"token", msg);
                    Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                }
            });
    }

 

이렇게 설정해놓고 돌려보면 Refreshed token: 이라는 메시지 뒤에 token 정보가 하나 뜰 것인데, 이후 이 정보가 필요할테니 따로 저장해두자.

(에러가 뜨는 사람은 많은 이유가 있겠지만 내 경우에는 jdk 버전이 레거시 버전이라서 그랬다. 업데이트 해서 쓰거나 나처럼 egov를 사용해서 업데이트를 하면 안 되는 경우 알아서 오류를 잡으시길. 필자는 회사용 컴퓨터에서 작업하길 포기하고 개인용 맥북에서 새로 깔아 썼다.)

 

 

 

iOS 앱 등록

들어가기에 앞서 애플에서는 APNs를 따로 사용하고 있다는 것을 인지하기 위해 아래 글도 한번 읽어보자.

https://dongminyoon.tistory.com/47

 

iOS에서의 진행 절차는 다른 블로그들을 참조하며 직접 실행해본 결과 아래 블로그를 따라했을 때 가장 잘 작동했다.

https://medium.com/devvenusk/fcm-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%91%B8%EC%89%AC-%EC%95%8C%EB%A6%BC%EC%9D%84-%EB%B3%B4%EB%82%B4%EB%B3%B4%EC%9E%90-6ea9844a0cf5

 

 

Node js

iOS는 좀 날먹(?) 했지만 Node js는 그렇지 않을 것이다.

 

먼저 Node js를 설치하자.

https://opentutorials.org/course/3332/21029

내가 정말 좋아하는 사이트인 생활코딩에서 제공해주는 정보만 따라도 설치에는 큰 무리가 없을 것이다.

Windows, Linux, MacOS 모두 설명이 되어 있다.

(위 동영상에서 windows를 참고하시는 분들 중 cd dir 이런 명령어가 제대로 듣지 않는다면 git bash 이용을 권한다.)

 

추가적으로 Atom이라는 에디터도 다운 받아서 사용하면 필자가 node js를 돌리는 환경을 맞출 수 있을 것이다.

(사실 요즘에는 다들 VS Code를 많이 이용한다.)

 

vs 코드를 쓰든 atom을 쓰든, 위 설치 동영상을 시청하면서 따라했다면 우리가 만든 node js 디렉토리로 들어가 있을 것이다. 해당 디렉토리에서 우리가 만든 프로젝트 폴더에서 아래의 명령어를 입력하여 Firebase와 연결해주자.

sudo npm install firebase --save

 

설치가 완료됐다면 firebase로 들어가서, 비공개 키를 하나 생성하여 다운받아준다.

 

다운을 받은 ~.json 파일을 node js 프로젝트 폴더 안에 넣고,

해당 프로젝트 폴더 내부에

main.js 라는 이름으로 파일을 하나 만들고 내용을 아래와 같이 해주자.

 

(androidServiceAccount와 androidRegistrationToken 둘 다 맞춰 넣어주자.)

// main.js
var http = require('http');
var fs = require('fs');
var url = require('url');
var queryString = require('querystring');

const adminAndroid = require('firebase-admin')
let androidServiceAccount = require('여러분이 방금 받은 json 파일')

adminAndroid.initializeApp({
  credential: adminAndroid.credential.cert(androidServiceAccount)
})
var payload = {
  data: {
    MyKey1: "hello"
  }
};
var androidPayload = {
  data: {
    MyKey1: "android push alarm"
  }
};
var androidOptions = {
  priority: "high",
  timeToLive: 60 * 60 * 24
}
var androidRegistrationToken = "여러분이 android나 ios 기기로부터 받은 token"
var android_fcm_message = {
notification: {
  title: 'android',
  body: 'test android'
},
data: {
  fileno:'44',
  style:'gooooods'
},
token: androidRegistrationToken
};


var app = http.createServer(function(request,response){
    var _url = request.url;
    var queryData = url.parse(_url, true).query;





    if(_url == '/'){
      _url = '/index.html';
    }
    if(_url == '/favicon.ico'){
      return response.writeHead(404);
    }

    if(request.method == 'GET'){
      console.log('---------GET--------');
      var parsedUrl = url.parse(request.url);
      console.log('parsedUrl: ', parsedUrl);
      var parsedQuery = queryString.parse(parsedUrl.query, '&', '=');
      console.log(parsedQuery);
      console.log('--------GET END-----------');
    }
    else if(request.method == 'POST'){
        console.log(request);
    }

    adminAndroid.messaging().send(android_fcm_message)
    .then(function(response) {
      console.log('성공ㅣ', response);
    })
    .catch(function(err){
      console.log("errrrrr: ", err);
    })

    // admin.messaging().send(fcm_message)
    // .then(function(response) {
    //   console.log('성공ㅣ', response);
    // })
    // .catch(function(err){
    //   console.log("errrrrr: ", err);
    // })
    response.writeHead(200);
    response.end(queryData.id);


});
app.listen(3000);

 

여기까지 따라했다면 이제 다 한 것이다.

터미널(또는 커맨드 창)에서 node js 프로젝트로 들어가 

node main.js 를 입력하면 ... 

아무것도 뜨지 않은 상태가 돼 있을 것이다. 

그러면 지금 코드에서 설정한 3000번 포트가 열려있다는 뜻이니까, 

localhost:3000/ 으로 접속하면

여러분이 등록한 기기(시뮬레이터이든 실제 기기이든)에 알람이 가게 될 것이다.

참고로 앱이 백그라운드 상태에 있어야 알림이 뜬다. ^^

 

출처:

https://tech.junhabaek.net/%EB%B0%B1%EC%97%94%EB%93%9C-%EC%84%9C%EB%B2%84-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-presentation-layer-3-%EC%9D%91%EB%8B%B5-%EC%9C%A0%ED%98%95%EC%97%90-%EB%94%B0%EB%A5%B8-variation-2-push-notification-1eacb4df4a7e

https://velog.io/@jujube0/Node.js-%ED%91%B8%EC%8B%9C-%EC%95%8C%EB%9E%8C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0 

https://blog.naver.com/PostView.naver?blogId=ndb796&logNo=221553341369&redirect=Dlog&widgetTypeCall=true&directAccess=false 

https://dongminyoon.tistory.com/47 

 

 

 

 

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기

댓글을 달아 주세요

">