모바일 푸쉬 메시지(FCM)를 위한 PHP 서버 구현 2부

today 2016-12-24 face Posted by appkr turned_in Work & Play forum 0

이 포스트는 2016년 12월 24일 첫 포스트 이후, 2017년 1월, 2018년 7월, 2018년 11월 총 세차례에 걸쳐 완전히 다시 썼으며, 예제 코드 또한 변경되었습니다.

최종 리팩토링의 가장 큰 변경은 기존에 사용하던 brozot/laravel-fcm 패키지를 완전히 버리고, Guzzle로 직접 구현했다는 점입니다.

FCM(Firebase Cloud Message)은 Android, iOS, Web 등의 클라이언트에 푸쉬 메시지를 보내기 위한 서비스다. 과거 GCM(Google Cloud Message)이 진화한 것이다.

Firebase Logo

지난 1부에서는 푸쉬 메시지를 받을 모바일 단말 애플리케이션이 구글 Fcm 서버로 부터 받은 고유 식별 토큰을 애플리케이션 서버로 전달해 등록하는 과정을 구현했다. 이번 포스트에서는 등록한 토큰으로 푸쉬 메시지를 쏘는 기능을 구현한다.

모바일 푸쉬 메시지(FCM)를 위한 PHP 서버 구현 1부

today 2016-12-18 face Posted by appkr turned_in Work & Play forum 0

FCM(Firebase Cloud Message)은 Android, iOS, Web 등의 클라이언트에 푸쉬 메시지를 보내기 위한 서비스다. 과거 GCM(Google Cloud Message)이 진화한 것이다.

Firebase Logo

PubNub, Pusher 등의 메시징 서비스와 FCM이 다른 점은 단말기가 꺼져 있거나, 잠김 모드에 있거나, 메시지를 받을 애플리케이션이 실행 중이지 않을 때도 메시지를 보낼 수 있다는 점이다.

FCM을 이용한 푸쉬 메시징 시스템을 구성하라면 다음 두 가지가 필요하다.

  • 푸쉬 메시지를 받을 모바일 단말용 애플리케이션
  • 푸쉬 메시지를 전송할 모바일 단말을 선별하고, 원하는 메시지와 함께 구글 FCM 서버에 메시지 전송 요청을 부탁할 애플리케이션 서버(구글 공식 문서에서는 “앱 서버”라고 칭하기도 한다).

이 포스트에서는 애플리케이션 서버를 구현하는 과정을 기술해본다. 모바일 단말용 애플리케이션은 이 포스트에서 다루지 않는다.

RPC - Apache Thrift 입문 2부

today 2016-12-10 face Posted by appkr turned_in Work & Play forum 0

앞서 1부에서는 다음 내용을 다루었다.

  • RPC 시스템에 대한 이해와 여러 가지 RPC 프레임워크의 특징
  • Thrift IDL(Interface Definition Language)를 이용해서 API 규격 만드는 방법
  • API 규격을 다양한 언어로 컴파일하고 라이브러리화 하는 방법
  • API 서버 프로젝트에 라이브러리를 플러그인하고 API 규격에 맞춘 서비스를 개발하는 방법
  • API 클라이언트가 서버에 접속하여 Thrift 프로토콜로 통신하는 방법

1부에서 언급했다시피, Thrift 요청과 응답은 Thrift 프로토콜 안쪽에서 (역)직렬화 된다. 1부의 내용만으로는 디버깅이 어려워 서비스를 개발하기가 수월치 않다. 그래서 2부에서는 다음 내용을 다룬다.

  • Thrift 프로토콜 안쪽에서 작동하는 미들웨어를 만들어서 Thrift 요청을 핸들링하고 그 과정에서 발생한 예외를 잡고 소비하는 방법
  • 책임 연쇄(Chain of Responsibility) 패턴의 이해
  • 통합 테스트(Integration Test) 구현

Private(or Protected) 메서드 테스트 하기

today 2016-12-04 face Posted by appkr turned_in Work & Play forum 0

최근에 회사 일로 검색 서비스를 개발했다. 검색 엔진으로는 Elastic Search를 사용했고, 매일 최한시(off-peak time)에 한 번씩 운영 데이터베이스에서 검색, 필터링, 정렬, Aggregation 등에 필요한 컬럼만 골라 인덱싱하도록 설계했다. 그리고, 재고 수량과 같이 실시간 업데이트가 필요한 값 들은 다른 서비스에서 SNS 메시지 또는 메시지 큐를 이용해서 전달하고, 전달 받은 값을 인덱싱에 반영하도록 구현했다.

Elastic Search는 사용법이 복잡하긴 하지만, 인덱싱된 필드 값에 따라 내림차순, 오름차순으로 미리 정렬된 결과를 받을 수 있다. 그런데, 아무리 실시간 업데이트를 한다고 해도, 인덱싱된 값만으로 정렬이 불가능한 경우가 있고, 이 경우에는 검색 결과를 받아서 후 처리로 배열을 순회하면서 다시 정렬을 해야 한다. 같은 클래스의 Public 메서드가 정렬 요청을 하므로, 당연히 Protected 메서드로 구현했다.

일반적으로 알려진 테스트 모범 사례는 다음과 같다.

  • 내가 짠 코드만 테스트한다. 외부에서 가져온 라이브러리를 테스트할 이유는 없다.
  • Public 메서드만 테스트한다. Private나 Protected 메서드는 Public 메서드가 작동하는데 도움을 주는 메서드들이므로, Public 메서드를 테스트함으로써 자동으로 테스트된다.

후처리 정렬의 정상 작동을 확인해야 할 필요성이 생긴 것이다. 물론 구현한 Protected 메서드의 가시성을 Public으로 변경하면 쉽다. 그런데, 다른 클래스에서 호출하지도 않을 메서드를 Public으로 선언하는 것은 기분이 찜찜하다. 이 포스트에서는 Private나 Protected로 선언된 메서드를 유닛 테스트하는 방법을 설명한다. 결론부터 말하면, PHP의 Reflection API를 이용하는 것이다.

Monolog를 이용한 애플리케이션 로깅

today 2016-12-03 face Posted by appkr turned_in Work & Play forum 0

이 포스트에서는 PHP 커뮤니티에서 De facto(사실상) 표준으로 인식되는 로깅 라이브러리인 Monolog의 사용법을 소개한다. Monolog는 PSR-3 LoggerInterface를 구현한 구현체이며, RFC-5424에서 정의한 심각도 규격(e.g. DEBUG, INFO, ..)에 따라 로그를 핸들링한다. 컴포저를 만든 조르디 보기아노(Jordi Boggiano)가 구현했으며, 파일 뿐만 아니라 데이터베이스, 메일, SaaS 서비스등 다양한 방법으로 로그를 처리할 수 있다.

이 포스트에서는 라라벨 프로젝트에서 기본 로그 저장소인 파일(storage/logs/laravel.log)에 더해서 Elastic Search에도 로그를 적재하는 방법을 다룬다. 다음 도구 또는 서비스를 사용한다.

  • 라라벨: PHP 프로그래밍 언어로 작성된 풀 스택 웹 프레임워크1
  • Elastic Search: 검색에 특화된 데이터베이스. CRUD 및 설정을 위한 REST API를 제공한다.2
  • Docker: 컨테이너화된 애플리케이션 운영 환경을 관리하는 도구3

이 포스트의 소스 코드는 https://github.com/appkr/monolog-scratchpad에서 받을 수 있다.

keyboard_arrow_up