구글 FCM 프로젝트 등록은 https://yeolco.tistory.com/85 를 참고하세요.

안드로이드 기준으로 작성되어있으니 프로젝트 생성까지만 따라하시고 오세요.


0. maifest.json

PWA 프로젝트 기준으로 작성되었기 때문에 mainfest.json내에

{

"gcm_sender_id": "103953800507"

}

를 추가해줍니다.

아이디는 위 아이디 그대로 사용하시면 됩니다.

(자신의 프로젝트의 sender id를 작성하면 오류발생합니다.)



1. 스크립트 영역(프론트)

<script src="https://www.gstatic.com/firebasejs/6.6.0/firebase-app.js"></script>

<script src="https://www.gstatic.com/firebasejs/5.10.1/firebase-messaging.js"></script>


<script>

// Your web app's Firebase configuration

var firebaseConfig = {

apiKey: "AIzaSyAnAp-nWTe4_N8piai73nfsl50lotYneu4",

authDomain: "cms-test-4f739.firebaseapp.com",

databaseURL: "https://cms-test-4f739.firebaseio.com",

projectId: "cms-test-4f739",

storageBucket: "",

messagingSenderId: "1095403590845",

appId: "1:1095403590845:web:b675f1753fc15ca0ab93d4"

};

// Initialize Firebase

firebase.initializeApp(firebaseConfig);

console.log("FCM INIT DONE");

</script>


프로젝트 설정 부분에서

이 부분을 그대로 복사한 후

푸시 메세지 사용을 위해

<script src="https://www.gstatic.com/firebasejs/5.10.1/firebase-messaging.js"></script>

를 추가해줍니다.


프론트 단(js)에서 적절한 위치(이벤트)에 토큰을 등록해줍니다.

const messaging = firebase.messaging();

messaging.usePublicVapidKey(applicationServerPublicKey);

Notification.requestPermission().then((permission) => {

if (permission === 'granted') {

console.log('Notification permission granted.');

// TODO(developer): Retrieve an Instance ID token for use with FCM.

messaging.getToken().then((currentToken) => {

if (currentToken) {

var data = { 

'token' : currentToken

};

$.ajax({

url: '/insertPushToken.do',

type: 'POST',

data: data,

success: function(data) {

console.log('RESULT', data);

},

error: function(err) {

console.log('ERROR', err);

}

});

} else {

console.log('No Instance ID token available. Request permission to generate one.');

}

}).catch((err) => {

console.log('An error occurred while retrieving token. ', err);

showToken('Error retrieving Instance ID token. ', err);

setTokenSentToServer(false);

});

else {

console.log('Unable to get permission to notify.');

}

});

1) applicationServerPublicKey는 FCM 콘솔에서 키 쌍 생성해서 넣어줍니다.

2) $.ajax 부분은 db에 토큰을 저장하는 부분입니다.

개인적으로 구현해서 사용하시면 됩니다. (혹시 필요하시면 댓글)


2. 자바(백엔드) 영역

// 푸시보내기 TEST

String FCM_URL = "https://fcm.googleapis.com/fcm/send";

String server_key = "AAAA_wskVL0:APA91bEd...............................kropWYS";

String tokenId = "e6vkJHnCd6s:.................................U_nYts_01-XNhzV";

String result = "";

URL url = new URL(FCM_URL);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();


conn.setUseCaches(false);

conn.setDoInput(true);

conn.setDoOutput(true);


conn.setRequestMethod("POST");

conn.setRequestProperty("Authorization", "key=" + server_key);

conn.setRequestProperty("Content-Type", "application/json");


JSONObject json = new JSONObject();


try {

json.put("to", tokenId.trim());

JSONObject data = new JSONObject();

data.put("url", "https://test.com");

data.put("icon", "test.png"); 

json.put("data", data);

JSONObject info = new JSONObject();

info.put("title", "푸시 테스트 중입니당"); 

info.put("body", "삐뽀삐뽀");

json.put("notification", info);

} catch (JSONException e1) {

e1.printStackTrace();

}


try {

OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());

wr.write(json.toString());

wr.flush();


BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));


String output;

System.out.println("Output from Server .... \n");

while ((output = br.readLine()) != null) {

System.out.println(output);

}

result = "succcess";

} catch (Exception e) {

e.printStackTrace();

result = "failure";

}

System.out.println("GCM Notification is sent successfully : " + result);

1. FCM_URL : 고정값입니다.

2. server_key : 동그라미 친 부분입니다.

3.  tokenId : 위에 프론트단에서 ajax로 디비에 넣은 토큰입니다.

저도 귀찮아서 그냥 하드코딩했어요 (이 부분은 디비에서 불러오면 됩니다.)


아 참고로 지금 단일 푸시 테스트 코드입니다.

여러명에게 보내는건 추후에 구현하고 올려드릴게요!


10/1 수정-----------------------------------------------------------------------------------


** 푸시 여러명에게 한번에 보내기


실제 프로젝트에서 수백~수천명에게 푸시를 보내야 하기 때문에

위 코드를 반복문으로 활용했을 경우 해당 코드에서 반복문을 돌면서(동기) 오랜시간 로딩이 걸린다.


fcm에서 여러명에게 푸시를 보내는 기능을 지원한다.

https://firebase.google.com/docs/cloud-messaging/http-server-ref

위 링크에서 다운스트림 json 부분을 확인한다.


위 단일 전송 코드에서 json.put("to", 토큰) 부분을 주석처리하고

아래와 같이 "registration_ids"를 추가한다.

=> json.put("registration_ids", tokens);


tokens는 배열(List)로 구성되어있다.

토큰들이 담긴 배열을 추가하면 된다.


처리 속도는 단일 메시지 보단 느리지만 300명 정도 테스트했을때 1초 이내로 실행되는것을 확인했다.


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


4. Service worker.js (서비스워커)

firebase push 사용시 서비스워커 js 파일을 만들어야합니다.

index와 같은 루트단에 firebase-messaging-sw.js 파일 생성하고 아래와 같이 작성합니다.

(토씨하나도 틀리면 오류나요)

var push_url;


// Functional: PUSH

self.addEventListener('push', event => {

var push_data = eval("(" + event.data.text() + ")");

push_url = push_data.data.url;

const title = push_data.notification.title;

const options = {

    body: push_data.notification.body,

    icon: push_data.data.icon

};


event.waitUntil(self.registration.showNotification(title, options));

});


// Push Notification Click

self.addEventListener('notificationclick', function(event) {

console.log('Notification click Received.', push_url);


event.notification.close();


if(push_url != null) {

event.waitUntil(

clients.openWindow(push_url)

);

}

});

1) self.addEventListener('push', event => : 푸시 받는 부분입니다. 

서버에서 푸시를 정상적으로 보내도 여기서 오류나면 못받습니다.

2) self.addEventListener('notificationclick', function(event)  : 푸시 notification 눌렀을때 처리할 이벤트입니다.


작동화면



'Java' 카테고리의 다른 글

facebook graph api로 게시글 가져오기  (1) 2019.09.23
구글, 파파고 번역 API 성능 비교  (1) 2019.09.18
google translate api v3 사용법  (1) 2019.09.16
Object 클래스에 대해  (0) 2018.11.04
자바 표준 입력 클래스 Scanner 사용법  (1) 2018.11.04
자바 상속  (0) 2018.10.17
자바 싱글톤 클래스(Singleton class)  (3) 2018.10.16
자바 Wrapper Class  (0) 2018.10.15


웹뷰를 사용하여 안드로이드와 ios 앱을 동시에 만들면


스크롤 방식이 ios와 android가 다르다는점을 알 수 있습니다.


먼저 android는 모멘텀 스크롤 방식으로


스크롤을 손가락으로 튕구면 멈추지 않고 힘의 크기에 비례하여 계속해서 스크롤 됩니다.


이를 모멘텀 스크롤 방식이라합니다.



반면에 ios는 스크롤을 하면 손가락이 떼어지는(touchend) 순간 스크롤은 멈추게됩니다.


이를 해결하기 위해 스크롤 되는(overflow) element에 다음과 같은 css를 추가하면 해결됩니다.


-webkit-overflow-scrolling : touch;


auto는 기존 멈추는 방식(default)이며 touch 옵션을 사용하면 안드로이드처럼 


모멘텀 스크롤을 사용할 수 있게됩니다.



또한 안드로이드에서 ios처럼 멈추게 하고싶다면


스크롤되는 element의 자식들 모두에게 z-index : 0; css를 추가합니다.


만약 스크롤 되는 element의 id가 scroll이라면


#scroll * {

z-index: 0;

}


을 추가하면 모든 자식에게 한번에 css를 적용시킬수있습니다.



* date 변수 format을 변경하는 방법


- timestamp를 date로 변경하는 등 date변수를 불러오면 다음과 같이 format이 이상하다.

ex) Thu May 09 2019 10:23:18 GMT+0900 (한국 표준시)


- 간단한 함수를 통해 다음과 같이 변경해보려고 한다.]

ex) 2019-05-09 10:23:18


- 먼저 timestamp 변수를 date변수로 변경하는 방법이다.

var sysdate = new Date(timestamp); 

여기서 timestamp는 timestamp형식의 변수를 의미한다.

이상태에서 sysdate를 출력해보면 맨위의 한국 표준시 어쩌고 하는 이상한 format이 적용된다.

이를 변경하기위해 아래 함수를 정의하여 사용한다.


function date_to_str(format)

{

    var year = format.getFullYear();

    var month = format.getMonth() + 1;

    if(month<10) month = '0' + month;

    var date = format.getDate();

    if(date<10) date = '0' + date;

    var hour = format.getHours();

    if(hour<10) hour = '0' + hour;

    var min = format.getMinutes();

    if(min<10) min = '0' + min;

    var sec = format.getSeconds();

    if(sec10) sec = '0' + sec;

    

    return year + "-" + month + "-" + date + " " + hour + ":" + min + ":" + sec;

}


위 함수를 정의하여 다음과 같이 사용한다.

sysdate = date_to_str(sysdate);


완료


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


여기서 date format을 자신이 원하는 format으로 변경하고싶다면

date_to_str 함수에 마지막 return 값을 수정하면된다.

ex) 연도와 날짜까지만 출력하고 싶다면 date 뒤를 지우면된다.



기본적인 배열은 일반 변수들이 나열된 모양이다.

var arr = [ "사과", "딸기", "복숭아 ];

var arr2 = [ 5, 3, 0.5, 7, 2, 9];


이런 일반적인 배열에서 인덱스를 통해 배열의 값을 구할수있다.

console.log(arr[0]); // "사과" 출력

console.log(arr2[2]); // 0.5 출력


반대로 배열의 값을 아는경우에 해당 배열의 몇번째 인덱스인지 indexOf함수를 사용하여 다음처럼 구할수있다.

console.log(arr.indexOf("복숭아")); // 2 출력

console.log(arr2.indexOf(5)); // 0 출력


하지만 자바스크립트에서 배열의 원소들이 객체(object)라면 어떻게 될까?

아래의 예를 살펴보자.

var arr3 = [

{ num : 0, name : "홍길동" },

{ num : 1, name : "박보검" },

{ num : 2, name : "강호동" }

];


위와 같은 객체배열이 존재한다고 가정하자.

객체 배열에서 객체안의 변수를 구하려면 다음과 같이 사용한다.

console.log(arr3[1].name); // "박보검" 출력

console.log(arr3[2].num); // 2 출력


그렇다면 반대로 "강호동"이라는 문자열을 가지고 2라는 인덱스를 구하려면 어떻게해야할까?

(실제로 프로그래밍도중 해당 지식이 필요하여 찾아서 정리한것이다..)

답은 findIndex() 함수를 사용하면 된다. 예를 통해 살펴보자.

var index = arr3.findIndex(i => i.name == "강호동"); 


여기서 index의 값으로 2를 반환받는다.

i라는 변수명은 아무거나 적어도 작동하는것을 보였다. 하지만 다른 변수이름과 중복되면 왠지모를 찝찝함이 생기므로

obj나 안쓰는 다른 변수명을 사용하자.


그럼이제 저 index를 사용하여 해당 배열에 접근할수있겠지?

질문이나 오타는 댓글로 남겨주길.



자바스크립트는 런타임 스크립트 언어라 실행을 해야 오류를 발견할 수 있다.

요즘엔 크롬 개발자도구 (F12) 등 가볍고 좋은 기능이 많이 있어서 오류찾기가 수월하다.


일단 이 오류에 대해 알아보자.


SyntaxError 라는 뜻은 쉽게 말해 문법오류라는 뜻이다.

문법에 맞게 작성되지 않은 경우 나타나는 오류인데 이는 비교적 해결하기가 쉽다.

에러가 난 줄 수나 위치, 틀린 문법 등을 바로 알려주기 때문이다.


해당 파일 이름을 클릭하면 실제로 코드를 보여주며 빨간색 밑줄 쳐져있는 부분이 보일것이다.


실제로 가장 자주 나타나는 ) 나 '' 오류는 해당 줄에서 괄호, 따옴표를 열기 또는 닫기를 제대로 해주지 않아서이다.

따라서 해결방법은 간단하다.

오류가 난 코드의 행으로 이동하여 자신이 무엇을 잘 못 표기했는지(오타), 괄호나 따옴표 등이 열리고 닫힌것이 정확한지만 찾아내면 끝이다.


이런 오류를 방지하기 위해서는 들여쓰기(탭)을 사용하여 코드 가독성을 높이고

띄어쓰기를 해서 문자와 변수, 괄호 사이에 가독성을 높인다.


예를들어 필자는 이런식으로 사용한다.


$(document).on('click' , '.class_name' , function() {

블라블라....

});


띄어쓰기와 문법 사이에 공간을 두어 가독성을 높인다.



또한 폰트도 개발자의 코드 가독성에 영향을 주는데,

보통 기본적인 프로그래밍 폰트는 consolas이며 윈도우 내장 폰트이다.

간혹 폰트를 바꾸는 경우가있는데 필자의 경우는 기본 폰트(consolas)가 가장 가독성이 좋았다.

(소문자 l (엘)과 대문자 I(아이)와 숫자 1(일)이 햇갈려서는 안된다.)

물론 개발자마다 다른 취향이 있으니 이는 자신이 사용해보고 가장 최적화된 폰트를 사용하기 바란다.


그럼 이만




to Top