반응형

Jetbrain Blog의 번역 글입니다. 원본은 아래 주소에 접속하여 확인 해 주세요 
https://blog.jetbrains.com/kotlin/2023/11/kotlin-multiplatform-development-roadmap-for-2024/ 

 

Kotlin Multiplatform Development Roadmap for 2024 | The Kotlin Blog

To equip you with the best cross-platform development experience, JetBrains aims to deliver a host of further improvements to the core Kotlin Multiplatform technology, Compose Multiplatform, KMP tooling, and KMP libraries in 2024.

blog.jetbrains.com


Kotlin Multiplatform Development Roadmap for 2024

더보기

With the recently achieved stability of Kotlin Multiplatform, development teams worldwide can now seamlessly and confidently adopt it in production. However, this is just the beginning for KMP and its ecosystem. To equip you with the best cross-platform development experience, JetBrains aims to deliver a host of further improvements to the core Kotlin Multiplatform technology, Compose Multiplatform, KMP tooling, and KMP libraries in 2024. Read on to learn what we’re planning and our priorities in these areas.

최근 완성된 코틀린 멀티플랫폼의 안정성 덕분에, 세계의 많은 개발팀들은 이제 장애물 없이 코플린 멀티 플랫폼을 프로덕션에 자신있게 적용할 수 있게 되었다.  하지만 이는 단지 KMP(Kotlin Multiplatform)과 에코시스템을 시작하는것일 뿐이다. 최고의 크로스 플랫폼 개발을 경험을 갖추게 하기 위해서, 2024년에 JetBrains는 핵심 코틀린 펄티플랫폼기술, 컴포즈 멀티 플랫폼, KMP도구와 라이브러리 같은 미래의 발전을 주도할것이다. 이 분야에서 무엇을 배워야하고, 어떤 순서로 배뭐야할지 알아보자. 

Compose Multiplatform

더보기

We’re dedicated to making Compose Multiplatform a framework that allows creating beautiful and performant applications that look the same way on all supported platforms. Right now, our main focus is to get Compose for iOS to Beta, but we’re also working on other things. Here’s what we plan to do:

  • Make all Jetpack Compose core APIs and components multiplatform.
  • Improve rendering performance on iOS.
  • Make scrolling and text editing in Compose for iOS apps behave the same as in iOS native apps.
  • Implement a common API for sharing all types of resources.
  • Integrate with iOS and Desktop accessibility APIs.
  • Provide a solution for multiplatform navigation.

Many of the aforementioned improvements benefit Compose for Desktop, as well. In addition, we’re working on improving its stability and evolving it according to the feedback from those who use it in production.

We’ll also continue to explore what’s possible with Compose for Web, specifically with Wasm. Our nearest goal is to promote it to Alpha, which includes:

  • Allowing you to port your existing apps and reuse all of your common code.
  • Supporting different screen sizes, orientations, and densities.
  • Supporting input from a mouse, touchscreen, physical keyboard, or onscreen keyboard.
  • Improving performance and binary size.

 

우리는 컴포즈 멀티플랫폼을 만들기 위해 헌신했다. 컴포즈 멀티플랫폼은 우리가 지원하는 모든 플랫폼에서 어플리케이션이 동일하게 동작하고 동일하게 보이도록지원해주는 아름답고 효율적인 프레임워크이다. 지금 당장 우리가 집중하고 있는것은 iOS를 위한 컴포즈 Beta 버전이다. 하지만 우리는 다른것들도 진행하고있다. 아래는 우리의계획이다. 

  • 모든 Jetpack Compose 코어API와 멀티플랫폼 컴포넌트 제작
  • iOS에서의 랜더링 퍼포먼스 향상
  • iOS 앱용 컴포즈에서의 스크롤링, 문자 수정(text edting) 동작을 iOS네이티브 앱과 동일하게 만들기
  • 모든 타입의 리소스를 공유할 수 있는 공통API 구현
  • iOS와 데스크탑의 접근성 API 통합
  • 멀티플렛폼 네비게이션을 위한 소루션 제공

앞서 말한 많은 개선사항은 컴포즈 for 데스크탑에도 역시 도움이 된다. 더욱이, 우리는 제품 사용자들의 피드백을 통해서 안정성 향상과 새로운 기능 향상 작업도 진행하고있다.

우리는 또한 컴포즈 for Web, 특히 Wasm에 대한 작업도 지속하고있다. 우리의 가장 가까운 목표는 컴포트 for Web을 알파 버전으로 만드는 것이다. 알파버전엔 다음이 포함된다. 

  • 이미 존재하는 앱들의 포팅기능, 공통코드의 재사용 기능.
  • 다양한 화면 사이즈(size, orientation, densitie) 지원,
  • 마우스, 터치스크린, 키보드, 스크린 키보드 지원
  • 퍼포먼스와 용량 향상.
  •  

Tooling

We’re committed to providing a great IDE experience for Kotlin Multiplatform. That means not only investing in the core platform and, for example, migrating Kotlin IDE plugin to K2 compiler frontend, but also providing a single tool (Fleet) for all Kotlin Multiplatform targets and codebases where you integrate it, eliminating the need to constantly switch between different IDEs.

We plan to quickly iterate over your feedback about using Fleet for Kotlin Multiplatform development  to make sure that we have everything you need for your development experience to be great. Among other things, we’re going to deliver in the following areas:

  • Enhanced support for Compose Multiplatform, including live preview for common code and visual debugging tools.
  • The IDE helping you with project configuration.
  • Unified and enhanced debugging experience for all parts of your Multiplatform project.

우리는 Kotlin Multiplatform을 위한 훌륭한 IDE 환경을 제공하기 위해 최선을 다하고 있습니다. 이는 Kotlin IDE plugin을 K2 compiler frontend 마이그레이팅 하는것 같은 코어 플랫폼 뿐만 아니라 개발자들이 통합하게 될 모든 Kotlin Multiplatform 타겟과 코드베이스를 위한 싱글툴(Fleet)을 제공하여 끊임없는 IDE변경을 제거한다는 의미입니다. 

우리는 Fleet for Kotlin Multiplatform development의 사용성에 대한 피드백을 빠르고 반복적으로 처리하여 개발자들에게 훌륭한 개발 경험을 제공하려고 합니다. 이런 행위들 사이에서 우리는 아래와 같은것들을 제공할 것 입니다.

  • 공통 코드를 위한 라이브 프리뷰와 시각적 디버깅 툴을 포함한 컴포즈 멀티플랫폼 서포트 증가
  • IDE의 프로젝트 configuration 도움
  • 멀티플랫폼 프로젝트의 모든 부분에서 통합되고 향상된 디버깅 경험 제공.

Multiplatform core

더보기

One of the popular Kotlin Multiplatform scenarios is sharing code with the iOS target. We want to focus on the development experience of iOS developers who work with Kotlin Multiplatform frameworks in their codebases.

The main initiative in this area is a direct Kotlin-to-Swift export. It will eliminate the Objective-C bottleneck, allowing for broader Swift language support and more natural exporting of APIs. Additionally, we are creating tools specifically for Kotlin library authors. These tools are designed to improve the compatibility and user-friendliness of Kotlin APIs when exported to Swift. We’re also paying close attention to tooling. The IDE and build systems are essential parts of the developer experience, and our goal is to ensure that the Swift Export integrates smoothly.

Our other initiatives include speeding up Kotlin/Native compilation, enhancing CocoaPods integration, and introducing support for exporting your framework with SwiftPM.

We also plan to continue exploring ways to improve the build setup of Kotlin Multiplatform applications. With Kotlin 1.9.20, we released huge improvements in the Gradle Multiplatform DSL, making it easier to read and write. We will continue to gradually improve it. In addition, we’re experimenting with Amper, a new project configuration tool focused on usability, onboarding, and IDE support.

Kotlin Multiplatform의 가장 유명한 시나리오 중 하나는 iOS 타겟괴 코드를 쉐어 하는 것 이다. 코드 베이스에서 코틀린 멀티플랫폼 프레임워크를 사용하는 iOS개발자의 경험에 중점을 두고 있다. 

이 분야에서의 주요 계획은 Kotlin-to-Swift의 직접 번역(direct export)이다.  이를 통해 Object-C 보틀렉을 제거와 광범위한 Swift언어 지원, 자연스러운 API exporting이 가능해진다. 더욱이, 우리는 코틀린 라이브러리 개발자들을 위한 도구(tool)들을 만들었다. 이 도구들은 Swift로 export될 때  Kotlin API의 호환성과 사용자친화성을 개선하도록 디자인 되다. 우리는 툴링(tooling)에도 세심한 주의를 기울이고 있다. IDE와 빌드 시스템은 개발자 경험의 중요한 부분입니다. 우리의 목표는 Swift Export를 부드럽게 만드는 것 이다. 

우리의 또 다른 우선순위는 Kotlin/Native 컴파일의 속도 증가, CocoaPods의 강화, SwiftPM을 사용한프레임워크 exporting 서포트 소개 를 포함하고 있다. 

우리는 또한 코틀린 멀티 플랫폼 어플리케이션의 빌드 셋업 향상을 위한 방법도 지속적으로 탐험할 계획이다. Kotlin1.9.20애서 우리는 Gradle Multiplatform DSL의 거대한 향상을 릴리즈하여 읽고, 쓰기 쉽게 만들었다. 우리는 계속적으로 향상시킬 예정이다. 더욱이 우리는 Amper라는 실험을 하고있다. Amper는 사용성, 온보딩, IDE서포트에 초점을 맞춘 새로운 프로젝트 configuration tool이다. 

Library ecosystem

더보기

As the Kotlin Multiplatform ecosystem is growing fast, the backward compatibility of the libraries becomes crucial. To ensure it, the JetBrains team and library creators must work together. Here’s our plan:

  • Improve the klib format so library creators can leverage their knowledge of building JVM libraries.
  • Implement the same code-inlining behavior in Kotlin Multiplatform libraries as for the JVM.
  • Provide a tool that ensures that your multiplatform library public API hasn’t changed in an incompatible way.

We’re also going to improve the publishing process for KMP libraries. Specifically, we plan to:

  • Make it possible to build and publish a KMP library without having a Mac machine.
  • Provide templates and extensive guidelines for creating and publishing a KMP library.

Even though Kotlin Multiplatform is now stable, we’re planning significant updates. But don’t worry: Libraries built with the current format will still work with newer Kotlin versions.

코틀린 멀티플랫폼의 에코시스템이 빠르게 성장함에 따라 라이브러리들의 이전 버전과의 호환성이 중요해졌다. 호환성을 위해서 JetBrains 팀과 라이브러리 제작자들은 함께 일해야만한다. 아래는 우리의 계획이다. 

  • klib format 발전으로 라이브러리 크리에이터들이 그들의 JVM라이브러리 빌드 지식을 향상시킬 수 있다.
  • 코틀린 멀티플랫폼의 code-inlining 행동이 JVM에서의 행동과 동일하도록 구현한다. 
  • 멀티플랫폼 라이브러리의 퍼블릭 API들이 호환되지 않는 방향으로 변경되지 않게 하는 도구를 제공한다. 

우리는 또한 KMP라이브러리의 퍼플리싱 프로세스 향상할 것이다. 특히, 아래와 같은 계획이다. 

  • Mac 없이 KMP라이브러리를 빌드하고 배포할 수 있게 만든다.
  • KMP라이브러리를 생성하고, 배포하기 위한 템플릿과 광범위한 가이드라인을 제공한다. 

Read more

반응형
반응형

심심해서 nginx에 대해서 검색하고있었는데 비기너스 가이드 beginners_guide가 번역된곳이 없는거같아서 번역해본다.

영어실력이 미천하니 참고로만 봐주시면 좋겠다.

원본 링크 http://nginx.org/en/docs/beginners_guide.html

글 작성일 2021.06.08

목차

  • 시작, 멈춤, 리로딩 설정
  • 설정파일(컨피그파일) 구조
  • 정적파일(Static content) 제공
  • 간단한 프록시 서버 만들기
  • FaxtCGI Proxing 세팅

이 가이드는 nginx에 대한 기본적인 소개화 함께 nginx를 이용해서 수행할 수 있는 간단한 작업에 대해서 서술하고있다. 글을 읽는 사람의 시스템에 이미 nginx가 설치 되어있다고 가정하고 설명을한다. nginx가 아직 설치되지 않았다면 ** 인스톨 페이지 ** 를 참조하도록하라. 이 가이드는 nginx를 시작하는법과 멈추는법, 설정(configuration)을 리로드 하는법, 설정파일의 구조 설명, nginx가 정적 컨텐츠(static content)를 제공하도롱 설정하는법에 대한 설명, nginx를 프록시 서버로 설정하는법, FastCGI 애플리케이션으로 세팅 하는법에 대해 설명한다.

nginx는 하나의 마스터 프로세스와 몇개의 워커 프로세스를 가진다. 마스터 프로세스의 주된 목정은 설청파일을 읽고, 수행하는것과 워커프로세스를 관리하는것이다. 워커 프로세스는 실제 요청을 수행한다. nginx는 워커 프로세스 사이의 효율적인 요청(request)분배를 위해서 이벤트 기반 모델, OS 종속적인 메카니즘을 사용한다. 워커 프로세스의 숫자는 설청 파일에 정의되어있고 주어진 설정량 만큼으로 고정될수 도 있고 사용 가능한 CPU 코어 숫자에 따라서 자동으로 조정될 수 도 있다. (자세한 사항은 워커 프로세스 를 참조하라)

nginx와 모듈들의 동작 방식은 설정파일에 정의되어있다. 설정파일의 디폴트 이름은 nginx.conf이고, /usr/local/nginx/conf, /etc/nginx, /usr/local/etc/nginx의 경로에 위치한다.

시작, 멈춤, 리로딩 설정 Nginx Start / Stop / Configuration 리로드

nginx 시작을 위해선 실행 가능한 파일을 실행시켜야한다. 일단 nginx가 실행되면 -s 옵션을 이용하여 실행파일을 호출해서 제어할 수 있다.
아래와 같은 문법을 사용하면된다.

nginx -s signal

signal은 아래 중 하나가 될 수 있다.

  • stop -- 빠른 종료(fast shutdown)
  • quit -- 적절한 종료(graceful shutdown)
  • reload -- 설정파일 리로드
  • reopen -- log 파일 재 오픈

예를 들어서 워커 프로세스들이 현재 수행중인 요청을 완료할때가지 기다린 후 nginx프로세스를 종료하길 원한다면 아래와 같이 명령어를 실행하면된다.

nginx -s quit

|위 명령어는 nginx를 실행시킨 계정과 같은 계정에서 실행해야 동작한다.|

설정파일의 변화는 nginx에 리로드 명령어를 보내거나 재시작 하기 전까지는 적용되지 않는다. 설정파일을 리로드 하기 위해선 아래의 명령어를 사용한다.

nginx -s reload

마스터 프로세스가 설정을 리로드 하라는 신호를 받으면 마스터 프로세스는 새 설정의 문법 검사(syntax validity)를 수행하고 새로운 설정을 적용하려고 시도한다. 설정 적용에 성공하면 마스터 프로세스는 새로운 워커 프로세스를 실행시키고, 이전 워커 프로세스들에게는 종료 메시지를 보낸다. 설정 적용에 실패하면 마스터 프로세스는 설정을 롤백하고 이전 설정으로 작업을 진행한다. 종료 메시지를 받은 이전 워커 프로세스들은 새로운 컨넥션을 받는것을 중지하고 현재 요청을 완료한 후 종료된다.

요청(signal)은 kill같은 Unix툴에 의해서 전송될 수 도 있다. 이경우 요청은 주어진 Process Id를 참조하여 직접 프로세스에 전달된다. nginx의 마스터 프로세스의 process ID는 default로 nginx.pid 파일에 적혀저있고, 기본 경로는 /usr/local/nginx/logs 또는 /var/run에 있다. 예를들어 마스터 프로세스의 process ID 가 1628일 경우 nginx를 적절한종료(graceful shutdown)하기위해서 아래의 명령어로 QUIT 요청(signal)을 보낼 수 있다.

kill -s QUIT 1628

실행중인 nginx 프로세스를 리스트화 해서 보기위해서는 ps유틸을 사용할 수 있다.

ps -ax | grep nginx

nginx에 요청을 보내는 방법에 대한 더 자세한 정보를 원한다면 Controlling nginx 문서를 참조하라

설정파일(컨피그파일) 구조 Configuration File's Structure

nginx는 모듈로 구성되어있고, 각 모둘들은 설정파일에 명시된 지시(directives) 따라 컨트롤된다. 지시(directives)들은 간단한(simpmle) 지시 들과 블럭 지시들로 나뉘어진다. 간단한 지시는 스페이스(공백)로 나뉘어진 이름과 파라미터로 구성되어있고 마지막에 세미콜론(;)으로 끝난다. 블럭 지시는 간단한 지시와 같은 구조로 되어있으나 세미콜론으로 끝나지않고 중괄호({})로 둘려싸여진 추가적인 지시(instructions)들의 셋을 가지고있다. 블럭 지시는 중괄호 안에 다른 지시를 가지고 있을 수 있고, 이를 컨텍스트(context) 라고 부른다.(ex, events, http, server, location).

설정파일 의 컨텍스트 밖에 위치한 지시들은 main컨텍스트로 간주된다. event 와 http 지시는 main 컨텍스트에 위치하고, server 컨텍스트는 http 컨텍스트, location 컨텍스트는 server 컨텍스트에 위치한다.

# 표시 뒤의 글자들은 주석이된다.

정적파일(Static content) 제공 Serving Static Content

웹서버의 중요한 역할은 (이미지나 정적 html같은)file을 제공하는것이다. 우리는 요청에 따라서 적절한 위치에서 파일을 제공하는 예제를 구현해볼 것이다.
HTML파일은 /data/www에서 제공하고, 이미지 파일은 /data/images 에서 제공하도록 하자. 이렇게 하기위해선 설정파일을 수정해야한다. http블럭에 있는 server블럭에 두 경로를 세팅해보자.

먼저 /data/www 디렉토리를 만들고 index.html 파일을 만들어서 적절한 글자를 좀 써두자. 그리고 /data/images 디렉토리를 만들고 적절한 이미지 몇개를 넣어두자.

다음으로 설정파일을 열자. 디폴트 설정파일에 이미 server 블럭예제가 들어있다. 대부분 주석처리가 되어있다. 이제 모든 블럭의 주석처리하고 새로운 server 블럭을 만들어보자.

http {
    server {
    }
}

일반적으로 설정파일엔 몇개의 server블록이 포트번호와 서버 이름으로 구별되어있다. nginx가 어떤 서버가 요청을 수행할지 결정하면 서버브럭 내에 정의된 위치 지시문(location directives)의 파라미터에 대해 리퀘스트 헤더에 지정된 URI를 테스한다.

아래의 location블럭을 server블럭에 추가해보자.

location / {
    root / data/www;
}

이 location블럭은 리퀘스트의 URI와 비교할 "/" 프리픽스를 지정했다. 매칭되는 리퀘스트에서 URI는ㄴ root 지정된 root 경로를 추가하게된다. 즉, /data/www를 추가하여 요청된 파일을 로컬 파일 시스템의 경로로 연결한다. 매칭되는 location 블럭이 여러개 있다면 nginx는 가장 긴 프리픽스를 선택하게된다. 위의 location블럭은 프리픽스의 길이가 1이기때문에 다른 모든 location블럭이 일치되지 않는 경우에만 사용되게 된다.

이제 두번째 location 블럭을 추가해보자.

location /images/ {
    root /data;
}

위 블럭은 리퀘스트가 /images/로 시작되는 경우에 매칟된다. (/images/로 시작되는 요청은 location / 에도 매칭 되지만 /의 길이가 더 짧기때문에 /images/로 매칭된다.)

server블럭의 결과는 아래와 같을 것이다.

server {
    location / [
        root /data/www;
    }

    location /images/ {
        root /data;
    }
}

이 블럭은 이미 스탠다드 포트인 80포트의 요청을 리슨(listen)하는 서버의 설정으로 동작하게된다. 그리고 로컬 머신에서 'http://localhost/"에 연결할 수 있게 된다. /images/로 시작되는 URI 리퀘스트에 대한 응답으로 서버는 /data/images 디렉토리의 파일을 전송해줄것이다. 예를 들어서 "http://localhost/images/example.png" 리퀘스트에 대한 요청으로 nginx는 /data/images/example.png 파일을 전송해줄것이다. 만약에 해당 파일이 없다면 nginx는 404에러를 넘겨준다. URI가 /images/로 시작되지 않는 요청에대해서는 /data/www 디렉토리로 매핑한다. 예를들어서 "http://localhost/some/example.html" 이라는 요청을 받으면 nginx는 /data/www/some/example.html 파일을 전송한다.

새로운 설정 파일을 적용하기위해서, 아직 nginx를 실행하지 않았다면 시작하도록하고, 이미 시작했다면 reload 시그널을 nginx의 마스터 프로세스에 보내주면 된다.

nginx -s reload

만일 예상대로 동작하지 않는 경우엔 access.log파일과 error.log파일에서 원인을 찾을 수 있다. 해당 파일은 /usr/local/nginx/logs 또는 /var/log/nginx 디펙토리에 있다.

간단한 프록시 서버 만들기 Setting Up a Simple Proxy Server

nginx가 자주 사용되는 방식 중 하나는 프로식 서버로써 사용하는것이다. 프록시서버란 리퀘스트를 받은 후 프록시된 서버로 해당 리퀘스트를 전달해주고, 프록시된 서버가 돌려준 응답을 다시 요청한 클라이언트에게 돌려주는 서버이다.

이제 우리는 기본적인 프로식서버 설정을 할 것이다. 이 프록시 서버는 로컬 디렉토리에서 이미지와 파일 리쿼스트만 받고 다른 모든 요청들은 프록시(된) 서버로 넘긴다. 이 예에서 두 서버 모두 하나의 nginx인스턴스에 정의될 것이다.

먼저 프록시(된) 서버를 만든다. nginx의 설정 파일에 아래의 내용을 추가해서 server블럭 하나를 더 만든다.

server {
    listen 8080;
    root /data/up1;

    location / {
    }
}

이제 이코드로인해서 8080포트를 리슨 하는 단순한 서버가 만들어졌다.(이전엔 listen이 없었기때문에 스탠다드 포트인 80을 사용하고 있었다.)
이 서버는 모든 리퀘스트를 로컬 파일 시스템의 /data/up1 디렉토리로 매핑한다. 해당 디렉토리를 생성하고 index.html 파일을 넣어두자. root는 server 컨텍스트에 위치해 있다는 점을 기억해두자. 이런 root는 location블럭이 root를 가지고 있지 않을경우 사용된다.

다음으로 이전섹션에서 사용한 server 설정을 사용해자. 해당 설정을 수정해서 프록시 서버 설정으로 변환해보자. 첫번째 location 블럭 안에 프로토콜과 함께 proxy_pass 명령을 만들자. 이름과 프록시 될 서버의 포트를 파라미터로 설정해둔다. (우리의 예제에서는 http://localhost:8080이다)

server {
    location / {
        proxy_pass http://localhost:8080;
    }

    location /images/ {
        root /data;
    }
}

우리는 두번째 location 블럭을 수정할 예정이다. 현재는 /images/ 프리픽스를 가진 요청은 /data/images 디렉토리에 매핑되고있다. 이제 요청에 일반적인 파일 확장자를 가진 요청이 있는경우 매칭되게 만들기 위해서 location 블럭은 아래와 같이 변경된다.

location ~ \.(gif|jpg|png)$ {
    root /data/images;
}

파라미터는 정규식이다. URI가 .gif, .jpg, .png 로 끝날경우 모두 매칭된다. 정규식은 반드시 ~ 로 시작해야한다. 이제 일치하는 리퀘스트는 /data/images 디렉토리에 매핑되게 된다.

nginx가 요청을 수행하기위해서 location 블럭을 선택할때 먼저 location 명령어가 특정한 프리픽스를 가지고 있는지 확인한다. 앞서 말한것처럼 가장 긴 프리픽스를 가진 location을 기억하고있고, 정규표현식을 체크한다. 만일 정규표현식에 매칭되는 location이 있다면 해당 로케이션을 선택하고 없는 경우엔 기억하고있던 location을 선택한다.

우리가만든 프록시 서버의 설정을 아래와 같다.

server {
    location / {
        proxy_pass http://localhost:8080;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

이 서버는 .gif, .jpg, .png로 끝나는 요청을 필터링하고 (URI를 root명령어의 파라미터로 추가해서 )/data/images 디렉토리로 매핑할 것이다. 그리고 다른 모든 요청은 이미 설정해놓은 프록시드 서버로 전달한다.

새로운 설정을 적용하기위해서 nginx에 리로드 시그널을 보내야한다. 이전 섹션에서 사용한 명령어를 사용한다.

nginx엔 프록시 서버 설정에 사용가능한 다양한 설정 명령어들이 있다.

FaxtCGI Proxing 세팅 Setting Up FastCGI Proxying

nginx는 리퀘스트를 FastCGI 서버로 라우팅 하기위해서도 사용된다. FastCGI서버는 어플리케이션을 실행하는 다양한 프로그래밍 언어와 프레임워크로 만들어진 서버를 말한다.

FastCGI 서버와 함께 사용하는 대부분의 nginx 설정은 proxy_pass 명령어 대신 fastcgi_pass명령어를 사용한다. 그리고 fastcgi_param명령어를 이용해서 FastCGI 서버에 파라미터를 전달한다. FastCGI서버가 localhost:9000으로 접근 가능하다고 가정해보자. 이전 섹션에서 기본으로 사용한 프록시 설정을 변경해보자. proxy_pass 명령어를 fastcgi_pass명령어로 변환하고 파라미터를 localhost:9000으로 변환한다. PHP에서는 스크립트 이름을 정의하기 위새허 SCRIPT_FILENAME 파라미터를 사용한다. 그리고 QUERY_STRING 파라미터를 이용해서 리퀘스트 파라미터를 전달한다. 변경된 설정은 아래와 같다.

server {
    location / {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

이제 이설정이 서버가 스태틱 이미지 요청을 제외한 모든 요청을 FastCGI프로토콜을 통해서 프록시된 서버인 localhost:9000으로 보내게된다.

반응형
반응형

모든 내용을 번역하기는 좀 시간이 부족해서 어노테이션 설명의 첫문단만 번역함.

원문.

docs.spring.io/spring-framework/docs/current/reference/html/testing.html#integration-testing

 

Testing

The classes in this example show the use of named hierarchy levels in order to merge the configuration for specific levels in a context hierarchy. BaseTests defines two levels in the hierarchy, parent and child. ExtendedTests extends BaseTests and instruct

docs.spring.io

 

3.4.1. Spring Testing Annotations

The Spring Framework provides the following set of Spring-specific annotations that you can use in your unit and integration tests in conjunction with the TestContext framework. See the corresponding javadoc for further information, including default attribute values, attribute aliases, and other details.

스프링 프레임워크는 다음와 같은 스프링 특화 어노테이션을 제공한다. 이 어노테이션들은 유닛테스트 혹은 통합테스트를 할때 테스트 프레임워크(TestContext framework)와의 연결을 위해서 사용된다. 디폴트값, 속성, 등 더많은 정보를 위해서는 대응되는 javadoc을 보도록 하라.

 

Spring’s testing annotations include the following:

스프링의 테스팅 어노테이션은 아래를 포함한다.

 

@BootstrapWith

@BootstrapWith is a class-level annotation that you can use to configure how the Spring TestContext Framework is bootstrapped. Specifically, you can use @BootstrapWith to specify a custom TestContextBootstrapper. See the section on bootstrapping the TestContext framework for further details.

@BootstrapWith는 클래스 레벨 어노테이션이다. 어떻게 스프링 테스트 프레이워크가 부트스트랩 되는지를 정의한다. 특히, @BootstrapWith를 사용하면 커스텀 테스트 컨텍스트 부트스트랩퍼를 지정할 수 있다. 더 많은 정보를 위해서 bootstrapping the TestContext framework  를 참조하도록 하라.

 

@ContextConfiguration

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests. Specifically, @ContextConfiguration declares the application context resource locations or the component classes used to load the context.

@ContextConfiguration은 클래스 레벨 메타데이터를 정의한다. 메타데이터는 통합 테스트를 위한 어플리케이션 컨텍스트를 어떻게 구성 하고, 로드 하는지를 정의한다. 특히, @ContextConfiguration은 어플리케이션 컨텍스트 리소스의 위치(location) 혹은 컨텍스트를 로드할때 사용되는 클래스의 컴포넌트를 선언한다.

 

@WebAppConfiguration

@WebAppConfiguration is a class-level annotation that you can use to declare that the ApplicationContext loaded for an integration test should be a WebApplicationContext. The mere presence of @WebAppConfiguration on a test class ensures that a WebApplicationContext is loaded for the test, using the default value of "file:src/main/webapp" for the path to the root of the web application (that is, the resource base path). The resource base path is used behind the scenes to create a MockServletContext, which serves as the ServletContext for the test’s WebApplicationContext.

@WebAppConfiguration은 클래스 레벨 어노테이션이다. @WebAppConfiguration은 통합 테스트를 위한 어플리케이션 컨텍스트가 WebApplicationContext여야 하는 경우 사용된다. @WebAppConfiguration가 사용되는 유일한 이유는 테스트를 할때WebApplicationContext가 로드되었다는것을 보장해주고, 웹 어플리케이션의 루트 패스인 "file:src/main/webapp"를 디폴트 값으로 사용하는것을 보장하는 것이다. 리소스의 베이스 패스는 Mock서블렛 컨텍스트를 생성하기위해서 사용되며 Mock서블렛 컨텍스트는 WebApplicationContext의 테스트에 사용되는 서블렛 컨텍스트 역할을 수행한다.

 

@ContextHierarchy

@ContextHierarchy is a class-level annotation that is used to define a hierarchy of ApplicationContext instances for integration tests. @ContextHierarchy should be declared with a list of one or more @ContextConfiguration instances, each of which defines a level in the context hierarchy. 

@ContextHierachy는 클래스레벨 어노테이션이다. @ContextHierarchy는 통합 테스트시 어플리케이션 컨텍스트의 인스턴스의 계층을 정의하기위해 사용된다. @ContextHierachy는 하나 이상의 @ContextConfiguration인스턴스와 함께 정의 되어야한다. 이때 사용되는 각 @ContextConfiguration가 컨텍스트 계층 레벨을 정의한다. 

 

@ActiveProfiles

@ActiveProfiles is a class-level annotation that is used to declare which bean definition profiles should be active when loading an ApplicationContext for an integration test.

@ActiveProfiles는 클래스 레벨 어노테이션이다. @ActiveProfiles는 통합 테스트시 어플리케이션 컨텍스를 로딩할때 어떤 빈 정의 프로파일이 활성화 되어야하는지를 정의한다. 

 

@TestPropertySource

@TestPropertySource is a class-level annotation that you can use to configure the locations of properties files and inlined properties to be added to the set of PropertySources in the Environment for an ApplicationContext loaded for an integration test.

 

 

 

반응형
반응형

Implementing GCM Client on Android 안드로이드에 GCM 클라이언트 확장(Implementing)하기

A Google Cloud Messaging (GCM) Android client is a GCM-enabled app that runs on an Android device. To write your client code, we recommend that you use the GoogleCloudMessaging API.

구글 클라우드 메시징(GCM) 안드로이드 클라이언트는 안드로이드 디바이스에서 작동하는 GCM이 허용된 앱이다. 당신의 클라이언트 코드를 작성하기 위해서 우리는 구글 클라우드 메시징 API를 당신이 참고하는것을 추천한다.

Here are the requirements for running a GCM Android client: 아래는 안드로이드에서 GCM이 작동하기위한 요구 조건이다.

  • At a bare minimum, GCM requires devices running Android 2.2 or higher that also have the Google Play Store application installed, or an emulator running Android 2.2 with Google APIs. Note that you are not limited to deploying your Android applications through Google Play Store. 최소 조건으로 GCM은 안드로이드 2.2 이상을 필요로한다 또한, 구글 플레이스토어가 인스톨 외어있어야 하며, 에뮬레이터일경우도 안드로이드 구글API와함께 안드로이드 2.2가 필요하다. 그러나 구글 플레이스토어에서 배포될 필요는 없다.
  • However, if you want to continue to use new GCM features that are distributed through Google Play Services, the device must be running Android 2.3 or higher, or you can use an emulator running Android 2.3 with Google APIs. 그러나 당신이 계속해서 새로운 GCM의 구글 플레이스토어를 아우르는 서비스를 이용하고 싶다면, 디바이스는 안드로이드 2.3 이상에서 동작해야며 에뮬레이터를 쓸 경우도 안드로이드 2.3이상을 사용해야한다.
  • On Android devices, GCM uses an existing connection for Google services. For pre-3.0 devices, this requires users to set up their Google accounts on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher. 안드로이드 디바이스에서, GCM은 구글서비스와 이미 존재하는 연결(connection)을 사용한다. 안드로이드 3.0 이하의 디바이스에서는 유저가 구글 계정을 설정해야함 한다. 구글 어카운트는 안드로이드 4.0.4 이상의 버전에서는 필요로 하지 않는다.

A full GCM implementation requires both a client implementation and a server implementation. For more information about implementing the server side, see Implementing GCM Server

완전한 GCM확장(implementation)을 위해서는 클라이언트와 서머 모두 확장(implementation)이 필요하다. implementing the server side에 대한 더많은 정보를 보려면 링크를 참조해라

The following sections walk you through the steps involved in writing a GCM client-side application. Your client app can be arbitrarily complex, but at bare minimum, a GCM client app must include code to register (and thereby get a registration ID), and a broadcast receiver to receive messages sent by GCM.

아래의 섹션들은 클라이언트 사이드의 GCM 코딩에 대해서 당신을 안내해 줄 것이다. 당신의 클라이언트 앱은 독단적으로 복잡할(arbitarily complex)수 도 있고, 최소한만을 충종할 수 도 있다, GCM 클라이언트는 반드시 등록(registrationID를 얻는 행위)코드를 포함해야하며, GCM이 전송한 메시지를 수신하기위한 브로드케스트 리스버를 가지고 있어야한다.

Step 1: Set Up Google Play Services 스텝1. 구글 플레이 서비스 설정(set up)


To write your client application, use the GoogleCloudMessaging API. To use this API, you must set up your project to use the Google Play services SDK, as described in Setup Google Play Services SDK.  당신의 클라이언트앱에서 구글클라우드 메시징 API를 사용하기 위해서, 당신은 구글 플레이 서비스SKD레 프로젝트 설정을 해야한다. Setup Google Play Services SDK에 잘 설명되어있다.

Caution: When you add the Play Services library to your project, be sure to add it with resources, as described in Setup Google Play Services SDK. The key point is that you must reference the library—simply adding a .jarfile to your Eclipse project will not work. You must follow the directions for referencing a library, or your app won't be able to access the library's resources, and it won't run properly. If you're using Android Studio, this is the string to add to the dependency section of your application's build.gradle file: 

주의: 당신이 플레이서비스 라디브러리에 당신의 프로젝트를 등록할때, 리소스가 함께 Setup Google Play Services SDK에서 설명한 대로 등록(add)되었는지 확인해라. 키포인트는 당신이 이클립스 프로젝트에서 간단하게 .jar 파일로 라이브러리를 참조하는것한방식으로는 동작하지 않는다는 것이다. 당신은 무조건 라이브러리를 참조하(referencing a libary)해야한다. 그게아니면 당신의 앱은 라이브러리에 접근할 수 없고, 앱은 재대로 동작하지 않을것디아. 만약 너가 안드로이드 스튜디오를 쓰고있다면 당신의 앱의 build.gradle 파일에 의존성(dependency)섹션에 아래에 있는 코드(string)을 추가하면 된다.

dependencies {
  compile
"com.google.android.gms:play-services:3.1.+"
}

Step 2: Edit Your Application's Manifest 스텝2. 매니페스트 수정


Add the following to your application's manifest: 

당신의 어플리케이션 메니패스트에 아래의 사항대로 추가해라:

  • The com.google.android.c2dm.permission.RECEIVE permission so the Android application can register and receive messages. 
  • com.google.android.c2dm.permission.RECEIVE 권한을 추가함으로써 등록을 할 수 있고, 메시지를 받을 수 있다.
  • The android.permission.INTERNET permission so the Android application can send the registration ID to the 3rd party server.
  • android.permission.INTERNET 권한을 추가함으로써 앱이 서트파티엡에 registration ID를 전송할 수 있다.
  • The android.permission.WAKE_LOCK permission so the application can keep the processor from sleeping when a message is received. Optional—use only if the app wants to keep the device from sleeping.
  • android.permission.WAKE_LOCK 권한을 추가함으로써 앱이 슬립상태에서도 메시지를 수신하는 프로세서를 유지할 수 있다. 선택사항(Optional)이다. 앱이 슬립 상태에서도 디바이스에서 동작하기를 원할 경우에만 추가해라.
  • An applicationPackage + ".permission.C2D_MESSAGE" permission to prevent other Android applications from registering and receiving the Android application's messages. The permission name must exactly match this pattern—otherwise the Android application will not receive the messages.
  • applicationPackage + ".permission.C2D_MESSAGE" 권한은 대른 앱이 등록허거나 메시지를 수신하는것은 예방해준다. 권한명(permission name)은 반드시 이 패턴과(패키지명.premissionC2D_MESSAGE) 맞아야한다. 안그러면 앱이 메지시를 수신 
  • A receiver for com.google.android.c2dm.intent.RECEIVE, with the category set as applicationPackage. The receiver should require the com.google.android.c2dm.permission.SEND permission, so that only the GCM Framework can send a message to it. If your app uses an IntentService (not required, but a common pattern), this receiver should be an instance of WakefulBroadcastReceiver. A WakefulBroadcastReceiver takes care of creating and managing a partial wake lock for your app.
  • com.google.android.c2dm.intent.RECEIVE, 수신기는 applicationPackage카테고리로 세팅되야한다. 리시버는 반드시 com.google.android.c2dm.permission.SEND 권한을 필요로한다. 그러면(so that) GCM프레임워크가 메시지를 앱으로 보낼 수 있다. 만일 너의 앱이 인텐트를 사용한다면(인텐트는 필수는 아니지만 흔한 패턴이다.) 이 리시버는 WakefulBroadcastReceiver의 한종류(instance of)가 될 것이다. WakefulBroadcastReceiver는 앱의 부분적 웨이크 락(partial wake lock)을 생성하거나 관리한다.
  • Service (typically an IntentService) to which the WakefulBroadcastReceiver passes off the work of handling the GCM message, while ensuring that the device does not go back to sleep in the process. Including anIntentService is optional—you could choose to process your messages in a regular BroadcastReceiver instead, but realistically, most apps will use a IntentService.
  • 서비스(일반적으로는 인텐트 서비스)가 GCM을 관리(handling)하기 위해서 WakefulBroadcastReceiver로 전달되는것은 디바이스가 슬립상태(sleep in process)로 돌아가지 않는것을 보장한다. 인텐트서비스를 포함하는것은 선택사항(optional)이다 - 당신은 메시지를 처리하기위해 일반적인(regular) BroadcastReceiver 를 선택할 수도 있다. 그러나 대부분의 앱은 인텐트 서비스를 사용할 것이다.
  • If the GCM feature is critical to the Android application's function, be sure to set android:minSdkVersion="8" or higher in the manifest. This ensures that the Android application cannot be installed in an environment in which it could not run properly.
  • 만약 GCM이 안드로이드 기능을 사용할 수 없는 특징을 가지고 있다면 매니페스트에 최소버전이 8(android:minSdkVersion="8") 또는 그 이상으로 되어있는지 확인해봐라. 이게 설정되어있으면 제대로 동작하지 않는 기기에는 인스톨되지 않는다. 

Here are excerpts from a sample manifest that supports GCM:  여기 GCM을 지원하는 매니패스트의 샘플을 발췌해 논것이있다:

<manifest package="com.example.gcm" ...>

   
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/>
   
<uses-permission android:name="android.permission.INTERNET" />
   
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
   
<uses-permission android:name="android.permission.WAKE_LOCK" />
   
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

   
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
       
android:protectionLevel="signature" />
   
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />

   
<application ...>
       
<receiver
           
android:name=".GcmBroadcastReceiver"
           
android:permission="com.google.android.c2dm.permission.SEND" >
           
<intent-filter>
               
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
               
<category android:name="com.example.gcm" />
           
</intent-filter>
       
</receiver>
       
<service android:name=".GcmIntentService" />
   
</application>

</manifest>

Step 3: Write Your Application 스텝3. 앱 코드 작성


Finally, write your application. This section features a sample client application that illustrates how to use theGoogleCloudMessaging API. The sample consists of a main activity (DemoActivity), a WakefulBroadcastReceiver(GcmBroadcastReceiver), and an IntentService (GcmIntentService). You can find the complete source code for this sample at the open source site.

마침내 이제 코드를 쓴다. 이 섹션은 구글 클라우드 메시징API를 어떻게 사용하는지에 대한 간단한 클라이언트 앱 셈플이다. 샘플은 메인 액티비티(DemoActivity), 웨이크풀브로드케스트리시버(GcmBroadcastReceiver), 인텐트(GcmIntentService)로 구성되어있다. 당신은 이 코드의 완전한 코드를 오픈소스사이트(링크)에서 찾을 수 있다. 

Note the following: 

아래사항을 주의해라:

  • Among other things, the sample illustrates registration and upstream (device-to-cloud) messaging. Upstream messaging only applies to apps that are running against a CCS (XMPP) server; HTTP-based servers don't support upstream messaging.
  • 다른것들 사이에, 셈플은 등록과 업스트림( 디바이스에서 클라우드로)메시지를 설명한다. 업스트림메시지는 CCS(XMPP)서버와 동작(running against)하는 앱만 지원한다; HTTP기반 서버는 업스트림 메시지를 서포트하지 않는다. 
  • The GoogleCloudMessaging registration APIs replace the old registration process, which was based on the now-obsolete client helper library. While the old registration process still works, we encourage you to use the newer GoogleCloudMessaging registration APIs, regardless of your underlying server.
  • 구글 클라우드 메시징 등록(registration) API는 예전 등록 프로세스(지금은 쓸수 없는 클라이언트 헬버 라이브러리 기반 프로세스)를 대체했다. 비록 예전 프로세스가 아직 작동하긴 하지만, 우리는 새로운 구글 클라우드 메시징 등록 API를 사용하기를 권고한다.

Check for Google Play Services APK 구글 플레이서비스 API 확인

As described in Setup Google Play Services SDK, apps that rely on the Play Services SDK should always check the device for a compatible Google Play services APK before accessing Google Play services features. In the sample app this check is done in two places: in the main activity's onCreate() method, and in its onResume()method. The check in onCreate() ensures that the app can't be used without a successful check. The check inonResume() ensures that if the user returns to the running app through some other means, such as through the back button, the check is still performed. If the device doesn't have a compatible Google Play services APK, your app can call GooglePlayServicesUtil.getErrorDialog() to allow users to download the APK from the Google Play Store or enable it in the device's system settings. For example:

Setup Google Play Services SDK에 설명된바에 따르면, Play Services SKD에 연걸되어있는 앱들은 항상구글플레이 스토어 서비스에 접속하기 전에 구글 플레이서비스APK에 호환이 되는지 확인해야한다.  예제(sample)앱에서 이 확인작업은 두곳에서 실행된다: onCreate메소드와 onResume메소드. onCreate메소드에서의 체크는 완전한 체크없이 앱을 사용할 수 없게한다. onResume메소드에서의 체크는 앱이 실행중 백번튼같은것을 눌렀을때 사용된다. 만약에 휴대폰이 구글 플레이서비스APK와 호환이 안된다면 당신의 앱은 GooglePlayServicesUtil.getErrorDialog()를 불러오게 되며 , 디바이스 시스템 세팅에서 구글플레이스토어APK를 다운로드받게 할것이다.

예를보자. 

private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
...
@Override
public void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);

    setContentView
(R.layout.main);
    mDisplay
= (TextView) findViewById(R.id.display);

    context
= getApplicationContext();

   
// Check device for Play Services APK. //구글플레이서비스APK를 체크한다.
   
if (checkPlayServices()) {
       
// If this check succeeds, proceed with normal processing. 체크가 성공하면 일반적인 작동을 할거다.
       
// Otherwise, prompt user to get valid Play Services APK. 반면에 아니라면 구글플레이서비스 권한을 획득하게하는 창을 띄운다.
       
...
   
}
}

// You need to do the Play Services APK check here too. 여기에도 플레이서비스APK체크를 해야한다.
@Override
protected void onResume() {
   
super.onResume();
    checkPlayServices
();
}

/**
 * Check the device to make sure it has the Google Play Services APK. If
 * it doesn't, display a dialog that allows users to download the APK from
 * the Google Play Store or enable it in the device's system settings.

* 디바이스가 구글플레이스토어 APK를 가지고 있는지 확인한다.

* 만약에 APK가 없아면 다이얼로그를 통해서 유저가 APK를 다운받게한다.
 */

private boolean checkPlayServices() {
   
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
   
if (resultCode != ConnectionResult.SUCCESS) {
       
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
           
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                    PLAY_SERVICES_RESOLUTION_REQUEST
).show();
       
} else {
           
Log.i(TAG, "This device is not supported.");
            finish
();
       
}
       
return false;
   
}
   
return true;
}

Register for GCM  GCM에 등록

An Android application needs to register with GCM servers before it can receive messages. When an app registers, it receives a registration ID, which it can then store for future use (note that registration IDs must be kept secret). In the following snippet the onCreate() method in the sample app's main activity checks to see if the app is already registered with GCM and with the server:

안드로이드앱은 메시지를 받기전에 GCM서버에 등록되어있어야만한다. 앱이 등록될때, 앱은 미래에 사용될 registrationID를 받아온다(registrationID는 비밀로 유지되어야한다). 다음의 정보에 따르면 샘플 엡에 main actitivity의 onCreate() 는 GCM서머에 앱이 이미 등록되어있는지를 체크한다.

/**
 * Main UI for the demo app. //데모앱의 메인 UI
 */

public class DemoActivity extends Activity {

   
public static final String EXTRA_MESSAGE = "message";
   
public static final String PROPERTY_REG_ID = "registration_id";
   
private static final String PROPERTY_APP_VERSION = "appVersion";
   
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

   
/**
     * Substitute you own sender ID here. This is the project number you got
     * from the API Console, as described in "Getting Started."

* 여기의 당신의 센더 아이디를 넣으세요. 센더아이디는 Getting Started에 성명되어있는 API콘솔에서 당신이 얻은 프로젝트 넘버입니다.
     */

   
String SENDER_ID = "Your-Sender-ID";

   
/**
     * Tag used on log messages. 로드메시지에 사용될 TAG
     */

   
static final String TAG = "GCMDemo";

   
TextView mDisplay;
   
GoogleCloudMessaging gcm;
   
AtomicInteger msgId = new AtomicInteger();
   
SharedPreferences prefs;
   
Context context;

   
String regid;

   
@Override
   
public void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);

        setContentView
(R.layout.main);
        mDisplay
= (TextView) findViewById(R.id.display);

        context
= getApplicationContext();

       
// Check device for Play Services APK. If check succeeds, proceed with
       
//  GCM registration.

// 디바이스가 Play Services APK를 사용가능한지 체크한다. 체크가 성공하면 GCM registration을 수행한다.
       
if (checkPlayServices()) {
            gcm
= GoogleCloudMessaging.getInstance(this);
            regid
= getRegistrationId(context);

           
if (regid.isEmpty()) {
                registerInBackground
();
           
}
       
} else {
           
Log.i(TAG, "No valid Google Play Services APK found.");
       
}
   
}
...
}

The app calls getRegistrationId() to see whether there is an existing registration ID stored in shared preferences:

앱은 shared preferences에 이미 저장된 regestrationid가 존재하는지 알아보기위해서 getRegistrationId()메소드를 호출한다. 

/**
 * Gets the current registration ID for application on GCM service. //현재 GCM서비스를 위해서 registrationId를 가져온다.
 * <p>
 * If result is empty, the app needs to register. //만약에 결과가 empty라면 앱은 register가 필요하다.
 *
 * @return registration ID, or empty string if there is no existing
 *         registration ID.
 */

private String getRegistrationId(Context context) {
   
final SharedPreferences prefs = getGCMPreferences(context);
   
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
   
if (registrationId.isEmpty()) {
       
Log.i(TAG, "Registration not found.");
       
return "";
   
}
   
// Check if app was updated; if so, it must clear the registration ID
   
// since the existing registration ID is not guaranteed to work with
   
// the new app version.

//앱이 업데이트 되었는지 체크한다. 업데이트 되었다면 registrationID를 초기화해야만한다.

//새로운 버전의 앱에서는 이미 존재하는 registrationID가 작동한다는 보장이 없다.
   
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
   
int currentVersion = getAppVersion(context);
   
if (registeredVersion != currentVersion) {
       
Log.i(TAG, "App version changed.");
       
return "";
   
}
   
return registrationId;
}
...
/**
 * @return Application's {@code SharedPreferences}.
 */

private SharedPreferences getGCMPreferences(Context context) {
   
// This sample app persists the registration ID in shared preferences, but
   
// how you store the registration ID in your app is up to you.

// 샘플앱은 shared preferences에 계속 registration id를 보관한다, 그러나 이부분은 당신이 원하는 방법으로 수정해도됟다.
   
return getSharedPreferences(DemoActivity.class.getSimpleName(),
           
Context.MODE_PRIVATE);
}

If the registration ID doesn't exist or the app was updated, getRegistrationId() returns an empty string to indicate that the app needs to get a new registration ID. getRegistrationId() calls the following method to check the app version:

registrationID가 없거나 앱이 업데이트된경우 getregistrationID()메소드는 앱이 새로운 registrationId가 필요하단것을 알려주기 위해서 

 empty스트링을 리턴한다.  getRegistrationid()메소드는 앱버전을 체크하기위해서 아래의 메소드를 호출한다.

/**
 * @return Application's version code from the {@code PackageManager}.
 */

private static int getAppVersion(Context context) {
   
try {
       
PackageInfo packageInfo = context.getPackageManager()
               
.getPackageInfo(context.getPackageName(), 0);
       
return packageInfo.versionCode;
   
} catch (NameNotFoundException e) {
       
// should never happen
       
throw new RuntimeException("Could not get package name: " + e);
   
}
}

If there isn't a valid existing registration ID, DemoActivity calls the following registerInBackground() method to register. Note that because the GCM methods register() and unregister() are blocking, this has to take place on a background thread. This sample uses AsyncTask to accomplish this:

만일 유효한 registrationID가 없다면, DemoActivity는 아래의 registrerInBackground()메소드를 호출하여 등록을한다.  GCM 메소드인 register()와 unregister()는 블로킹(트랜잭션이 처리될 때 락이 걸림)을한다. 그래서 이건 무조건 백그라운드 스레드에서 작업해야된다.샘플앱은 수행을 위해서 AsyncTask를 사용한다.

※아래의 구글 공식 방법으로는 작동을 안합니다. 제가 작성한 작동되는 버전을 곧 올리겠습니다.


/**
 * Registers the application with GCM servers asynchronously.//앱을 GCM서버에 비동기식으로 등록한다.
 * <p>
 * Stores the registration ID and app versionCode in the application's
 * shared preferences.

* 앱의 shared preferences에 registrationId와 버전코드를 저장한다.
 */

private void registerInBackground() {
   
new AsyncTask

() {
       
@Override
       
protected String doInBackground(Void... params) {
           
String msg = "";
           
try {
               
if (gcm == null) {
                    gcm
= GoogleCloudMessaging.getInstance(context);
               
}
                regid
= gcm.register(SENDER_ID);
                msg
= "Device registered, registration ID=" + regid;

               
// You should send the registration ID to your server over HTTP, //http프로토콜을 이용해서 서버에 registrationID를 전송해야한다.
               
// so it can use GCM/HTTP or CCS to send messages to your app. //그것이 당신의 앱에 gcm/http 또는 ccs메시지를 사용가능하게 해준다.
               
// The request to your server should be authenticated if your app // 당신의 앱이 계정(account)를 사용한다면 서버에 요청할때 반드시 진짜임을 증명해야한다.
               
// is using accounts.
                sendRegistrationIdToBackend
();

               
// For this demo: we don't need to send it because the device
               
// will send upstream messages to a server that echo back the
               
// message using the 'from' address in the message.
//이 데모에서 우리는 우리는 전송할 필요가 없다. 왜냐하면 디바이스가 서버에 업스트림 메시지를 보낼것이고, 그것이 반사되어 메시지안에서 'from' 주소를 포함해주기때문이다.
               
// Persist the registration ID - no need to register again. /registrationid를 사용할때 다시 등록할 필요는 없다.
                storeRegistrationId
(context, regid);
           
} catch (IOException ex) {
                msg
= "Error :" + ex.getMessage();
               
// If there is an error, don't just keep trying to register.
               
// Require the user to click a button again, or perform
               
// exponential back-off. //에러가 발생하면 등록을 하지않는다. 유저가 클릭을 다시하거나, 뒤로가기를 해야한다.
           
}
           
return msg;
       
}

       
@Override
       
protected void onPostExecute(String msg) {
            mDisplay
.append(msg + "\n");
       
}
   
}.execute(null, null, null);
   
...
}

Once you've received your registration ID, send it to your server:  //한번 registrationID를 받으면 당신의 서버(서드파티서버)로 전송해라

/**
 * Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
 * or CCS to send messages to your app. Not needed for this demo since the
 * device sends upstream messages to a server that echoes back the message
 * using the 'from' address in the message.
* registrationID를 HTTP프로토콜을 통해서 당신의 서버에 전송해라. 그것이 GCM/HTTP나 CCS메시지를 당신의 앱으로 전송할 수 있게 해준다.  
이 데모에서 우리는 우리는 전송할 필요가 없다. 왜냐하면 디바이스가 서버에 업스트림 메시지를 보낼것이고, 그것이 반사되어 메시지안에서 'from' 주소를 포함해주기때문이다.

 */
private void sendRegistrationIdToBackend() {
   
// Your implementation here.
}

After registering, the app calls storeRegistrationId() to store the registration ID in shared preferences for future use. This is just one way of persisting a registration ID. You might choose to use a different approach in your app:

등록이 끝난 후, 앱은 미래에 사용하기 위해서 shared preferences에 registrationid를 저장하기 위해 storeRegistrationId()메소드를 호출한다.  이건 단지 registrationId를 저장하기 위한 한가지 방법일 뿐이다. 어떤방법을 쓰던 당신이 정해서 사용해라.

/**
 * Stores the registration ID and app versionCode in the application's //registrationID와 버전 코드를 저장한다.
 * {@code SharedPreferences}.
 *
 * @param context application's context.
 * @param regId registration ID
 */

private void storeRegistrationId(Context context, String regId) {
   
final SharedPreferences prefs = getGCMPreferences(context);
   
int appVersion = getAppVersion(context);
   
Log.i(TAG, "Saving regId on app version " + appVersion);
   
SharedPreferences.Editor editor = prefs.edit();
    editor
.putString(PROPERTY_REG_ID, regId);
    editor
.putInt(PROPERTY_APP_VERSION, appVersion);
    editor
.commit();
}

Handle registration errors  registration에러 다루기

As stated above, an Android app must register with GCM servers and get a registration ID before it can receive messages. A given registration ID is not guaranteed to last indefinitely, so the first thing your app should always do is check to make sure it has a valid registration ID (as shown in the code snippets above).

정해진 상태에 따르면, 안드로이드 앱은 메시지를 받기 전에 반드시 gcm서버에 등록을 해야하고 registrationID를 얻어야한다. 전달된 registrationID가 마지막 식별자라는것은 보장되지 않는다. 그래서 당신의 앱이 해야하는 첫번째 일은 registrationID가 유효한것인지 체크하는것이다. (snippets above에서 보여준 코드처럼)

In addition to confirming that it has a valid registration ID, your app should be prepared to handle the registration error TOO_MANY_REGISTRATIONS. This error indicates that the device has too many apps registered with GCM. The error only occurs in cases where there are extreme numbers of apps, so it should not affect the average user. The remedy is to prompt the user to delete some of the other client apps from the device to make room for the new one.

추가적으로 유효안 registrationID인지 확인하기위해서, 앱은 등록의 TOO_MANY_REGISTRATIONS에러를 다룰 준비를 하고있어야한다. 이 에러는 디바이스가 GCM에 너무 많은 등록이 되어있다는것을 보여둔다. 이에러는 앱의 숫자가 극도로(extreme) 많을때만 나타난다. 처리방법은 새로은 registrationID를 위한 공간을 위해서 즉각적으로 다른 클라이언트앱의것들을 지우는 것이다.

Receive a downstream message  다운스트림 메시지 받기

As described above in Step 2, the app includes a WakefulBroadcastReceiver for thecom.google.android.c2dm.intent.RECEIVE intent. A broadcast receiver is the mechanism GCM uses to deliver messages.

Step2에 나온 셜명에 따르면, 앱은 com.google.android.c2dm.intent.RECEIVE를 위해서 WakefullBroadcastReceiver를 포함해야한다.  브로드캐스트 리시버는 GCM이 메시지를 전달하는 메카니즘이다.

WakefulBroadcastReceiver is a special type of broadcast receiver that takes care of creating and managing apartial wake lock for your app. It passes off the work of processing the GCM message to a Service (typically anIntentService), while ensuring that the device does not go back to sleep in the transition. If you don't hold a wake lock while transitioning the work to a service, you are effectively allowing the device to go back to sleep before the work completes. The net result is that the app might not finish processing the GCM message until some arbitrary point in the future, which is not what you want.

WakefulBroadcastReceiver는 당신의 앱을 위한 partial wake lock를 만들고, 다루는 특별한타입의 브로드캐스트 리시버이다. WakefulBroadcastReceiver는 서비스(일반적으로 인텐트서비스)를 처리하기위한 GCM메시지를 전달하고, 수행중에 sleep모드로 돌아가지않게 하는걸 보장한다. 만일 당신이 서비스하기위한 일을 전송중에 wake lock을 고정하지 않는다면 당신은 특별히 작업 수행전에 슬립모드로 들어가는것을 허용해야한다. 넷 결과는 앱이 gcm메시지를 임의의 구간에서 완료하지 못하게 할거다. 이걸 당신이 원하진 않겠지

Note: Using WakefulBroadcastReceiver is not a requirement. If you have a relatively simple app that doesn't require a service, you can intercept the GCM message in a regular BroadcastReceiver and do your processing there. Once you get the intent that GCM passes into your broadcast receiver's onReceive() method, what you do with it is up to you.

WakefulBroadcastREceiver를 사용하는것이 필요하지않다. 만약 당신이 서비스를 필요로하지 않는 간단한 앱을 사용한다면, 당신은 GCM메시지를 일반적인 BroadcastReceiver로 가로챌수있고, 거기서 당신의 작업을 할 수 있다. 일단 GCM이 브로드캐스트리시버의 onReceive()메소드로 인텐트를 보내면 뭘하던 당신한테 달려있다.

This snippet starts GcmIntentService with the method startWakefulService(). This method is comparable tostartService(), except that the WakefulBroadcastReceiver is holding a wake lock when the service starts. The intent that is passed with startWakefulService() holds an extra identifying the wake lock:

이 정보는 GcmIntentService를 startWakefulSErvice()메소드와 함께 시작한다. 이 메소드는  WakefulBroadcastReceiver가 wake lock를 서비스가 시작할때 제어(holding)한다는 것을 제외하면 startService()메소드와 비슷하다  인텐트는 startWakefulService()와 함께 전달되어 추가의 wake lock 의 식별자를 홀드한다.

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
   
@Override
   
public void onReceive(Context context, Intent intent) {
       
// Explicitly specify that GcmIntentService will handle the intent. //GcmIntentService는 인텐트를 다룰수 있는것을 명확하게 명시한다.
       
ComponentName comp = new ComponentName(context.getPackageName(),
               
GcmIntentService.class.getName());
       
// Start the service, keeping the device awake while it is launching. //서비스를 시작하고, 실행중에 디바이스가 계속 깨어있게한다.
        startWakefulService
(context, (intent.setComponent(comp)));
        setResultCode
(Activity.RESULT_OK);
   
}
}

The intent service shown below does the actual work of handling the GCM message. When the service is finished, it calls GcmBroadcastReceiver.completeWakefulIntent() to release the wake lock. ThecompleteWakefulIntent() method has as its parameter the same intent that was passed in from theWakefulBroadcastReceiver.

인텐트서비스는 실제 GCM메시지 다루기작업보다 아래에서 보여준다. 서비스가 끝나면, GcmBroadcastReceiver.completeWakefulIntent()를 호출해서 wake lock을 풀어준다. completeWakefulIntent()메소드는 WakefulBroadcastReceiver와 동일한 파라메터를 가지고있다.

This snippet processes the GCM message based on message type, and posts the result in a notification. But what you do with GCM messages in your app is up to you—the possibilities are endless. For example, the message might be a ping, telling the app to sync to a server to retrieve new content, or it might be a chat message that you display in the UI.

이정보는 메시지 타입과 알림의 결과를 보내주는것에 기초한 GCM 메시지 프로세스이다. 그러나 GCM메시지가 어떤 작업을 수행할지는 당신에게 달려잇다 - 가능성은 끝이없다. 예를들어 메시지는 ping이나 새로운 컨텐츠를 앱에 알려주거나, UI에 표시해주는 체팅 메시지일수도있다.

public class GcmIntentService extends IntentService {
   
public static final int NOTIFICATION_ID = 1;
   
private NotificationManager mNotificationManager;
   
NotificationCompat.Builder builder;

   
public GcmIntentService() {
       
super("GcmIntentService");
   
}

   
@Override
   
protected void onHandleIntent(Intent intent) {
       
Bundle extras = intent.getExtras();
       
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
       
// The getMessageType() intent parameter must be the intent you received
       
// in your BroadcastReceiver. //getMessageType() 인텐트 파라미터는 BroadcastReceiver에서 받아야한다.
       
String messageType = gcm.getMessageType(intent);

       
if (!extras.isEmpty()) {  // has effect of unparcelling Bundle //
           
/*
             * Filter messages based on message type. Since it is likely that GCM
             * will be extended in the future with new message types, just ignore
             * any message types you're not interested in, or that you don't
             * recognize.
            *  메시지 타잎에 기초한 필터메시지. GCM이 미래에 확장할 수 있는 새로운 메지시타임과 같은것들은 당신이 다루려고 하거나, 인지할 수 없는 메시지일경우 전부 무시한다.

*/
           
if (GoogleCloudMessaging.
                    MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
                sendNotification
("Send error: " + extras.toString());
           
} else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_DELETED
.equals(messageType)) {
                sendNotification
("Deleted messages on server: " +
                        extras
.toString());
           
// If it's a regular GCM message, do some work. 일반적 GCM메시지라면, 뭔일을 시켜라.
           
} else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
               
// This loop represents the service doing some work. 이 루프는 뭔가 일을한다.
               
for (int i=0; i<5; i++) {
                   
Log.i(TAG, "Working... " + (i+1)
                           
+ "/5 @ " + SystemClock.elapsedRealtime());
                   
try {
                       
Thread.sleep(5000);
                   
} catch (InterruptedException e) {
                   
}
               
}
               
Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
               
// Post notification of received message. 받은 메시지에다핸 알림을 준다.
                sendNotification
("Received: " + extras.toString());
               
Log.i(TAG, "Received: " + extras.toString());
           
}
       
}
       
// Release the wake lock provided by the WakefulBroadcastReceiver. 웨이크락을 풀어준다.
       
GcmBroadcastReceiver.completeWakefulIntent(intent);
   
}

   
// Put the message into a notification and post it. 알림을 준다.
   
// This is just one simple example of what you might choose to do with
   
// a GCM message. 이건 그냥 예제일뿐이도 gcm메시지로 뭘할지는 당신이 알아서해라
   
private void sendNotification(String msg) {
        mNotificationManager
= (NotificationManager)
               
this.getSystemService(Context.NOTIFICATION_SERVICE);

       
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
               
new Intent(this, DemoActivity.class), 0);

       
NotificationCompat.Builder mBuilder =
               
new NotificationCompat.Builder(this)
       
.setSmallIcon(R.drawable.ic_stat_gcm)
       
.setContentTitle("GCM Notification")
       
.setStyle(new NotificationCompat.BigTextStyle()
       
.bigText(msg))
       
.setContentText(msg);

        mBuilder
.setContentIntent(contentIntent);
        mNotificationManager
.notify(NOTIFICATION_ID, mBuilder.build());
   
}
}

Send an upstream message   업스트림 메시지 보내기

When the user clicks the app's Send button, the app sends an upstream message using the GoogleCloudMessagingAPI. In order to receive the upstream message, your server should be connected to CCS. You can use one of the demo servers in Implementing an XMPP-based App Server to run the sample and connect to CCS.

유저가 앱의 센드 메시지를 보내면, 앱은 업스트림 메시지를 GoogleCloudMessgingAPI를 통해서 보낸다. 업스트림 메시지를 보내는거 대신에 당신의 서버는 반ㄴ드시 CCS랑 연결되어야한다. 당신은 샘플을 실행해보고 CCS에 접속해보기위해 Implementing an XMPP-based App Server 의 데모서버중 하나를 쓸 수 있다.

public void onClick(final View view) {
   
if (view == findViewById(R.id.send)) {
       
new AsyncTask() {
           
@Override
           
protected String doInBackground(Void... params) {
               
String msg = "";
               
try {
                   
Bundle data = new Bundle();
                        data
.putString("my_message", "Hello World");
                        data
.putString("my_action",
                               
"com.google.android.gcm.demo.app.ECHO_NOW");
                       
String id = Integer.toString(msgId.incrementAndGet());
                        gcm
.send(SENDER_ID + "@gcm.googleapis.com", id, data);
                        msg
= "Sent message";
               
} catch (IOException ex) {
                    msg
= "Error :" + ex.getMessage();
               
}
               
return msg;
           
}

           
@Override
           
protected void onPostExecute(String msg) {
                mDisplay
.append(msg + "\n");
           
}
       
}.execute(null, null, null);
   
} else if (view == findViewById(R.id.clear)) {
        mDisplay
.setText("");
   
}
}

Running the Sample 샘플 실행하기


To run the sample: 

  1. Follow the instructions in Getting Started to get your sender ID and API key.
  2. Implement your client app, as described in this document. You can find the complete source code for the client app at the open source site.
  3. Run one of the demo servers (Java or Python) provided in Implementing an XMPP-based App Server. Whichever demo server you choose, don't forget to edit its code before running it to supply your sender ID and API key.

샘플 실행을 위해서:

1. GettingStartd의 설명을 따라서 당신의 senderId와 API키를 얻어라.
2. 문서에 나온거처럼 클라이언트엡에 
3.데모서버(자바 또는 파이선)에서의 작동은 XMPP에 기초한 앱서버를 확장하는것을 제공한다. 어떤 데모서버를 선택하던지, 서버가 작동하기전에 센더아이디와 API키를 수정하는것을 잊지말자.

Viewing Statistics


To view statistics and any error messages for your GCM applications:

GCM앱에서 통계와 에러메시지를 보기위해서

  1. Go to the Developer Console.
  2. Login with your developer account.

    You will see a page that has a list of all of your apps.

  3. Click on the "statistics" link next to the app for which you want to view GCM stats.

    Now you are on the statistics page.

  4. Go to the drop-down menu and select the GCM metric you want to view.
1. 디벨로퍼콘솔로가라.
2.디벨로퍼 어카운트로 로그인해라. 너는 너의 앱 리스트를 볼 수 있을것이다.
3. 'statistics'항목을 클릭해라.
4. 드랍다운메뉴로가서 GCM metric을 선택해라.

Note: Stats on the Google API Console are not enabled for GCM. You must use the Developer Console.

구글API콘솔이 GCM에 허가되지 않은 상태라면, 디벨로커 콘솔을 이용해라.


반응형
반응형

Overview 개요

Google Cloud Messaging (GCM) is a free service that enables developers to send downstream messages (from servers to GCM-enabled client apps), and upstream messages (from the GCM-enabled client apps to servers). This could be a lightweight message telling the client app that there is new data to be fetched from the server (for instance, a "new email" notification informing the app that it is out of sync with the back end), or it could be a message containing up to 4kb of payload data (so apps like instant messaging can consume the message directly). The GCM service handles all aspects of queueing of messages and delivery to and from the target client app.

구글클라우드 메시징(GCM)은 개발자가 다운스트림 메시지( 서버에서 GCM이 가능한 클라이언트 앱으로)와 업스트림메시지(GCM이가능한 앱에서 써버로)를 가능하게하는 공짜서비스다.

이 가벼운 메시지는 서버로부터 새로운 메시지(예를들면 백엔드와 동기화하지 않는 앱에서 '새 메일'정보를 알려주는 메시지)를 가지고 오거나 최대 4kb의 데이터를 가지고 온다(앱이 메시지를 바로 사용할 수 있다.)  GCM은 모든면의 메시지쿼리를 다룰 수있고, 타겟 클라이언트앱으로 메시지를 전달하거나, 가져올 수 있다.

Key Concepts 주요 컨셉


This table summarizes the key terms and concepts involved in GCM. It is divided into these categories:

이 표는 GCM의 주요 컨셉과 용어를 요학안다. 카테고리별로 나누어져 있다.

  • Components — The entities that play a primary role in GCM.
  • 컴포넌트 - GCM에서 개별적 역할을 가지고있는 독립체(entities)
  • Credentials — The IDs and tokens that are used in GCM to ensure that all parties have been authenticated, and that the message is going to the correct place.
  • 자격(credentials) - GCM에서 권한을 주고, 메시지를 정확한곳으로 인도하는 토큰과 아이디들

Table 1. GCM components and credentials. 표1. GCM컴포넌트와 자격들

Components 컴포넌트

GCM Connection Servers
GCM 연결 서버

The Google-provided servers involved in sending messages between the 3rd-party app server and the client app.
구글이 제공하는 서머. 서드파티 앱서버와 클라이언트 앱사이의 메시지를 전송하는 기능이 포함되어있다.

Client App
클라이언트앱

A GCM-enabled client app that communicates with a 3rd-party app server.
서드파이 앱서버와 통신할 수 있는 GCM이 가능한 앱
3rd-party App Server
서드파티서버

An app server that you write as part of implementing GCM. The 3rd-party app server sends data to a client app via the GCM connection server.

당신이 만든 GCM이 포함된 서버의 일부분. 서드파티 앱서버는 GCM서버와의 연결을 통해서 데이터를 클라이언트 앱으로 보낸다.

Credentials  자격들

Sender ID
샌더아이디

A project number you acquire from the API console, as described in Getting Started. The sender ID is used in the registration process to identify a 3rd-party app server that is permitted to send messages to the client app.
API콘솔로부터 얻은 프로젝트넘버, 시작하기에 설명 되어있다.

이 센더아이디는 클라이언트로 메시지를 보내는 권한이 있는 서드파이템을 알아내기위한 등록 프로세스로 사용된다.

Sender Auth Token
샌더 권한 토큰

An API key that is saved on the 3rd-party app server that gives the app server authorized access to Google services. The API key is included in the header of POST requests.
API키는 구글 서비스에 겁속하기위한 권한으로써 서드파티앱 서버에 저장된다.

API는 포스트 리퀘스트해더를 포함하고있다.

Application ID
앱아이디

The client app that is registering to receive messages. How this is implemented is platform-dependent. For example, an Android app is identified by the package name from themanifest. This ensures that the messages are targeted to the correct Android app.
메지시를 받기위한 등록을 한 클라이언트앱. 플랫폼에 의존적으로 implement된다.
예를들어 안드로이드앱이 매니페스트에서 확인된다면, 이 확인은 메시지가 정확한 앱으로 가도록 타케팅 된다.

Registration ID
등록아이디

An ID issued by the GCM servers to the client app that allows it to receive messages. Note that registration IDs must be kept secret.
GCM서버가 클라이언트앱으로 메지시를 보내는것을 허용하기위해 발행되는 ID.

ID를 기록해놔야하고, 반드시 비밀로 유지해야한다.

Architectural Overview 구조적(Architectual) 개요


A GCM implementation includes a Google-provided connection server, a 3rd-party app server that interacts with the connection server, and a GCM-enabled client app. For example, this diagram shows GCM communicating with a client app on an Android device:

GCM은 구글이 제공한 컨넥션서버, 컨낵션서버와 소통하는 서드파티앱서버, GCM이 가능한 클라이언트 앱을 포함한다.

예를들어, 이 다이어그램은 안드로이드 디바이스에 있는 클라이언트앱이 GCM과 커뮤니케이션 하는 모습을 보여주는 다이어그램이다.

Figure 1. GCM Architecture.   그림1. GCM구조(Architecture)

This is how these components interact:

컴포넌트들이 소통하는 방법:

  • Google-provided GCM Connection Servers take messages from a 3rd-party app server and send these messages to a GCM-enabled client app (the "client app"). Currently Google provides connection servers forHTTP and XMPP.
  • 구글이 제공하는 GCM 컨넥션 서버는 서트파티 앱서버로 부터 메시지를 전달받는다, 그리고 클라이언트 앱으로 메시지를 전송한다. 현재 구글은 HTTP와 XMPP서버 컨넥션을 제공한다.
  • The 3rd-Party App Server is a component that you implement to work with your chosen GCM connection server(s). App servers send messages to a GCM connection server; the connection server enqueues and stores the message, and then sends it to the client app. For more information, see Implementing GCM Server.
  • 서드파티 앱 서버는 당신이 선택한 GCM연결 서버를 포함하는 요소(component)이다. 앱서버는 메시지를GCM으로 보낸다; 컨넥션 서버는 큐에 메시지를 넣고 저장한다. 그리고 클라이언트앱으로 전송한다. 더많은 정보는 Implementing GCM Server를 참고해라.
  • The Client App is a GCM-enabled client app. To receive GCM messages, this app must register with GCM and get a registration ID. If you are using the XMPP (CCS) connection server, the client app can send "upstream" messages back to the 3rd-party app server. For more information on how to implement the client app, see the documentation for your platform.
  • 클라이언트앱은 GCM이 가능한 앱이다. GCM메시지를 받기 위해서는 이 앱은 GCM에 등록하여 registrationID를 얻어야만한다. 만약 XMPP(CCS) 컨넥션서버를 사용한다면, 클라이언트앱은 서드파티앱서버로 업스트림메시지를 전송할 수 있다.  클라이언트앱에  포함시키기위한 더 많은 정보를 위해서 당신의 플랫폼 문서를 봐라

Lifecycle Flow 라이프사이클 흐름


  • Register to enable GCM. A client app registers to receive messages. For more discussion, see Register to enable GCM.
  • GCM이 가능하게 등록한다. 클라이언트앱을 메시지를 받기 위하여 등록한다. 더많은 설명을 보려면 REgister to Enable GCM을 봐라
  • Send and receive downstream messages.
  • 다운스트림 메시지 보내기
    • Send a message. A 3rd-party app server sends messages to the client app:
    • 메시지 보내개. 서드파티앱서버가 클라이언트앱으로 메시지를 보낸다:

      1. The 3rd-party app server sends a message to GCM connection servers.  서드파티앱이 GCM컨넥션 서버에 메시지를 전송한다.
      2. The GCM connection server enqueues and stores the message if the device is offline.  디바이스가 오프라인일 경우 컨넥션 서버는 메시지를 큐에 넣고 저장한다.
      3. When the device is online, the GCM connection server sends the message to the device. 디바이스가 온라인이 되었을때 GCM 컨넥션 서버는 디바이스로 메시지를 보낸다.
      4. On the device, the client app receives the message according to the platform-specific implementation. See your platform-specific documentation for details. 디바이스에서, 클라이언트앱을 platform-specific 확장을 통하여 메시지를 받는다. 세부사항을 위해서 당신의 디바이스의 platform0specific문서를 봐라
      5. Receive a message. A client app receives a message from a GCM server. See your platform-specific documentation for details on how a client app in that environment processes the messages it receives. 메시지 수신, GCM서버로부터 메시지를 수신한 클라이언트앱. 당신의 platform-specific문서를 봐라 클라이언트앱이 수신된 메시지를 처리하는 환경 프로세스를 어떻게 처리하는지 알기 위하여
  • Send and receive upstream messages. This feature is only available if you're using the XMPP Cloud Connection Server (CCS).
  • 업스트림 메시지의 전송과 수신. 이 특징은 오직 당신이 XMPP Cloud Connection(CSS)를 사용할때만 적용된다.

    • Send a message. A client app sends messages to the 3rd-party app server: 메시지보내기. 클라이언트앱이 서드파티앱서버로 메시지를 보낸다.
      1. On the device, the client app sends messages to XMPP (CCS).See your platform-specific documentation for details on how a client app can send a message to XMPP (CCS).  디바이스에서, 클라이언트앱은 XMPP로 메시지를 보낸다. 클라이언트앱이 XMPP로 메시지를 보내는 방법에 대한 세부사항을 위해서 당신의 platform-specific 문서를 봐라.
      2. XMPP (CCS) enqueues and stores the message if the server is disconnected. XMPP(CCS)는 서버가 연결이 안돼있을경우 메시지를 큐에 넣고, 저장한다.
      3. When the 3rd-party app server is re-connected, XMPP (CCS) sends the message to the 3rd-party app server. 서드파티앱서버가 연결되었을때 XMPP(CCS)는 서드파티 앱서버로 메시지를 보낸다.
    • Receive a message. A 3rd-party app server receives a message from XMPP (CCS) and then does the following: 메시지 수신. 서드파티 앱서버는 아래사항에 따라서 XMPP(CCS)로부터 메시지를 받는다.
      1. Parses the message header to verify client app sender information. 클라이언트 앱 전송자의 절보를 확인하기위해 메시지 해더를 파싱한다.
      2. Sends "ack" to GCM XMPP connection server to acknowledge receiving the message.  메시지를 수신받았다는 것을 GCM XMPP연결서버에 알려주기 위해 "ack"를 보낸다.
      3. Optionally parses the message payload, as defined by the client app. 선택적으로 메시지 데이터(payload)를 파싱한다. 클라이언트앱을 정의하기 위해서

Register to enable GCM GCM을 가능하게 하기위한 등록


Regardless of the platform you're developing on, the first step a client app must do is register with GCM. This section covers some of the general best practices for registration and unregistration. See your platform-specific docs for details on writing a GCM-enabled client app on that platform.

당신이 개발해놓플랫폼의 종류와 상관없이. 클라이언트 앱의 첫번째 스탭은 GCM에 등록하는것이다. 이 섹션은 등록과 등록해지의 가장좋은 방법이다.

Keeping the Registration State in Sync 동기화에서 등록 상태 유지

Whenever the app registers as described in Implementing GCM Client, it should save the registration ID for future use, pass it to the 3rd-party server to complete the registration, and keep track of whether the server completed the registration. If the server fails to complete the registration, the client app should retry passing the registration ID to 3rd-party app server to complete the registration. If this continues to fail, the client app should unregister from GCM.

앱이 Implementing GCM Client 에서 말해놓은 등록을 할땐 언제라도, 미래의 사용하고, 서드파티 앱서버에 완벽하게 등록하고, 서버가 등록여부를 완전히 알고있게하기 위해서 registrationID를 저장해 놔야한다. 만약 서버가 등록에 실패하면, 클라이언트앱은 registrationID를 서트파티앱서버에 다시 전송해서 완전한 등록을 해야한다. 만일 계속해서 실패하면 클라이언트앱은 GCM에서 등록해지된다.

There are also two other scenarios that require special care:  별한 관리를 위한 두가지 시나리오가 있다.

  • Client app update   클라이언트 앱 업데이트
  • Backup and restore   백업과 저장

Client app update: When a client app is updated, it should invalidate its existing registration ID, as it is not guaranteed to work with the new version. The recommended way to achieve this validation is by storing the current app version when a registration ID is stored. Then when the app starts, compare the stored value with the current app version. If they do not match, invalidate the stored data and start the registration process again.

클라이언트 앱 업데이트: 클라이언트 앱이 업데이트될따, 기존의 registrationid는 만료된다. 따라서 기존의 registration ID는 새로운 버전에서의 동작을 보장하지 않는다.  유혀성을 위해 추천되는 방법은 registration ID가 저장될때 현재의 앱 버전을 저장하는것이다. 그래서 앱이 실행될때 저장된 정보와 현재 앱버전을 비교한다. 만약 두 정보가 일지하지않는다면 저장된 데이터(registrationID)를 폐기하고, 등록 프로세스를 다시한번 실행한다.

Backup and restore: You should not save the registration ID when an app is backed up. This is because the registration ID could become invalid by the time the app is restored, which would put the app in an invalid state (that is, the app thinks it is registered, but the server and GCM do not store that registration ID anymore—thus the app will not get more messages). The best practice is to initiate the registration process as if the app has been installed for the first time.

백업과 저장: 앱이 백업될때 registrationID를 저장하면 안된다. 왜냐하면 registrationID는 앱이 다시 저장될때 만료되기 때문이다. 백업시 registrationID를 저장한다면 앱을 권한이 없는 상태로 만든다(왜냐면 앱은 지가 등록되어있다고 생각하지만 서버와 GCM은 해당 registrationID를 더이상 가지고있지 않기떄문이다. 그래서 앱은 더이상 메시지를 받을 수 없다.) 가장 좋은 방법은 앱이 처음 인트톨될때터럼 초기화 하는 방법이다.

Canonical IDs  예전 ID들

If a bug in the app triggers multiple registrations for the same device, it can be hard to reconcile state and you might end up with duplicate messages. 

만약 버그가 한 디바이스에서 여러 등록을 시켜버린다면,  다시 조정하기가 아주 어렵다 그래서 너는 메시지를 복제하게되는 상황에 처하게 될것이다.

GCM provides a facility called "canonical registration IDs" to easily recover from these situations. A canonical registration ID is defined to be the ID of the last registration requested by your app. This is the ID that the server should use when sending messages to the device.

GCM은  해당 상황에서 쉽게 벗어나게 해주기 위하여 "canonical registration IDs"라고 불리는 기능을 제공한다. conical registrationID는 앱에서 보낸 마지막 등록아이디로 정의되어있다. 이 아이디가 서버에서 디바이스로 보낼떄 써야하는 ID이다.

If later on you try to send a message using a different registration ID, GCM will process the request as usual, but it will include the canonical registration ID in the registration_id field of the response. Make sure to replace the registration ID stored in your server with this canonical ID, as eventually the ID you're using will stop working.

만일 나중에 당신이 다른 registrationID를 이용하여 메지시를 보내려고한다면, GCM 프로세스는 일반적 상황과 같게 요청할것이다. 그러나 그것은 응답(response)의 registration_id필드 안에있는 canonical registration ID를 포함할 것이다. 서버에 저장된 registrationID를 이 conanoical ID로 대체하기위해서 당신이 사용하던 ID는 동작을 멈출것이다.

Automatic Retry Using Exponential Back-Off  Exponential Back-Off를 이요한 자동 재요청

When registration or unregistration fails, the app should retry the failed operation.

등록 또는 등록해지가 실패했을때 앱은 실패한요청을 다시 시도해야한다.

In the simplest case, if your app attempts to register and GCM is not a fundamental part of the app, the app could simply ignore the error and try to register again the next time it starts. Otherwise, it should retry the previous operation using exponential back-off. In exponential back-off, each time there is a failure, it should wait twice the previous amount of time before trying again.

간단한 케이스에서, 너의 앱이 등록을 시도했는데 GCM이 앱의 구성요소가 아닐때, 앱을 앱은 간단하게 에러를 무시하고, 다음번에 앱이 실행될때 다시 시도한다.  그렇지않다면, exponential back-off를 이용하여 미리 재시도를 해야한다. exponential back-off에서 매번 실패가 있다면 다시 시도하기전에 두배로 기다려야한다.

Unregistration 등록해지

This section explains when you should unregister in GCM and what happens when you do.

이 섹션은 당신이 GCM에서 등록을 해지할 시기와 등록을 해지할때 일어나는 일에대해 설명한다.

Why you should rarely unregister   왜 당신은 드물게 등록해지를 해야하는가

You should only need to unregister in rare cases, such as if you want an app to stop receiving messages, or if you suspect that the registration ID has been compromised. In general, once an app has a registration ID, you shouldn't need to change it.

당신은 아주 드물게 등록해지를 해야만한다,  당신이 메시지를 더이상 받기를 원하지 않을때, 또는 registration ID가 제대로 작동하지 못했다고 생각될때 같은 경우 등록을 해지한다. 일반적으로 앱이 한번 regsistration ID를 생성하면 변경할 필요가 없다.

In particular, you should never unregister your app as a mechanism for logout or for switching between users, for the following reasons:

특히, 아래와 같은이유로 당신을 로그아웃시나, 유저를 변경할시 등록해지를 하는 행위를 절대로 하면 안된다.

  • A registration ID isn't associated with a particular logged in user. If you unregister and then re-register, GCM may return the same ID or a different ID—there's no guarantee either way.  registrationID는 로그인한 유저와는 연관되지 않는다. 만약 등록해지 후 재등록을 하면 GCM은 같은 ID를 리턴하거나 다른 아이디를 리턴하는데 둘중 어떤것이 될지는 알 수 없다.
  • Unregistration may take up to 5 minutes to propagate.      등록해지가 될때까지 최대 5분이 소요된다.
  • After unregistration, re-registration may again take up to 5 minutes to propagate. During this time messages may be rejected due to the state of being unregistered, and after all this, messages may still go to the wrong user.  등록해지 이후에  재등록까지는 다시 최대 5분이 소요된다. 이 소요시간동안 메시지는 전달되지 않을것이다. 그리고 이 모든 메시지는 다른 유저에게 갈 수 있다.

To make sure that messages go to the intended user:     메시지가 원하는(intented)유저에게 전달되는것을 보장하기

  • Your app server can maintain a mapping between the current user and the registration ID. 당신의 앱서버는 현재 유저와 registration ID 사이의 매핑을 유지(matain)할 수 있다.
  • The app can then check to ensure that messages it receives match the logged in user. 앱은 로그인한 유저가 메시지를 받있는지 확인할 수 있다.

How unregistration works   등록해지는 어떻게 이루어지는가.

A client app can be automatically unregistered after it is uninstalled. However, this process does not happen right away. What happens in this scenario is as follows:

클라이언트 앱은 제거된(uninstalled)후 자동으로 등록을 해지한다. 이 프로세스는 바로 작동하지는 않는다. 아래의 시나리오에서 어떤일이 일루어지는지 보자

  1. The end user uninstalls the client app. 유저가 앱을 지운다.
  2. The 3rd-party app server sends a message to GCM server. 서드파티앱서버가 GCM에 메시지를 보낸다.
  3. The GCM server sends the message to the GCM client on the device. GCM서버가 클라이언트의 디바이스에 메시지를 보낸다.
  4. The GCM client on the device receives the message and detects that the client app has been uninstalled; the detection details depend on the platform on which the client app is running.  디바이스의 GCM클라이언트는 메시지를 받는다 그리고 클라이언트 앱이 지워진것을 발변한다;  발견에 관한 세부사항은 플랫폼에 어떤 클라이언트앱이 동작하고있는가에따라 다르다.
  5. The GCM client on the device informs the GCM server that the client app was uninstalled.  GCM클라이언트는 GCM서버에 앱이 삭제되었단것을 알려준다.
  6. The GCM server marks the registration ID for deletion. GCM서버는 registrationID에 삭제되었다는 마크를한다.
  7. The 3rd-party app server sends a message to GCM. 서드파티 앱서버가 메시지를 GCM에 전송한다.
  8. The GCM returns a NotRegistered error message to the 3rd-party app server. GCM은 'NotRegistered'에러메시지를 서드파티앱서버에 리턴한다.
  9. The 3rd-party app server deletes the registration ID. 서드파티앱서버는 registrationID를 제거한다.

Note that it might take a while for the registration ID be completely removed from GCM. Thus it is possible that messages sent during step 7 above gets a valid message ID as response, even though the message will not be delivered to the client app. Eventually, the registration ID will be removed and the server will get a NotRegisterederror, without any further action being required from the 3rd-party server (this scenario happens frequently while an app is being developed and tested).     

registrationID가 GCM에서 완전하게 지워지기까지는 시간이 좀 걸린다. 이렇게해서 7단계보다 위로 메시지가 보내지는것이 가능한것은 응답으로 유효한 메시지 아이디를 받는것이 가능하다. 비록 클라이언트앱으로 메시지가 전달되지 않았다고 할지라도. 결국 registrationID는 지워질 것이다 그리고 서버는 notregistered에러를 받게 될 것이다. 서드파티앱서버에서 더나아간 행위가 요구되는것 없이(이 시나리오는 테스트에서 자주 발생한다.) 


반응형
반응형

Google Cloud Messaging for Android

Google Cloud Messaging (GCM) for Android is a service that allows you to send data from your server to your users' Android-powered device, and also to receive messages from devices on the same connection. The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device, and it is completely free.

안드로이드 구글 클라우드 메시징(GCM)은 당신의 서버에서 유저의 안드로이드 장치에 데이터를 보내는 서비스이며 같은 연결(Connection)을 이용하여 안드로이드 장치로부터 메시지를 받을 수 있는 서비스이다.

GCM서비스는 모든면의 메세지쿼리를 다룰 수 있고, 타겟 디바이스에서 구동중인 앱에 메지시 쿼리를 전달할 수 있다, 그리고 전부 공짜이다.



반응형

+ Recent posts