2016년 9월 3일 토요일

[퍼온글]Amazon Web Service(AWS) IOT


AWS IoT 디바이스 SDK
AWS IoT에서는 하드웨어 디바이스 또는 모바일 애플리케이션을 쉽고 빠르게 연결할 수 있도록 SDK를 제공합니다. AWS IoT 디바이스 SDK를 사용하면 디바이스에서 MQTT, HTTP 또는 WebSockets 프로토콜을 사용하여 AWS IoT와 연결하고, 인증하고, 메시지를 교환할 수 있습니다. 디바이스 SDK는 C, JavaScript 및 Arduino를 지원하며, 클라이언트 라이브러리, 개발자 안내서 및 제조업체용 포팅 안내서를 포함합니다. 또한, 이를 대체하는 오픈 소스를 사용하거나 자체 SDK를 작성할 수 도 있습니다.
자세한 내용은 AWS IoT 디바이스 SDK 설명서를 참조하거나 SDK를 다운로드하여 시작하십시오.
 디바이스 게이트웨이
AWS IoT 디바이스 게이트웨이를 사용하면 디바이스가 AWS IoT와 안전하고 효율적으로 통신할 수 있습니다. 디바이스 게이트웨이는 게시/구독 모델을 사용하여 메시지를 교환할 수 있으며, 이러한 모델은 1대1 및 1대 다수 통신을 가능하게 합니다. AWS IoT는 이러한 1대 다수 통신 패턴을 통해 연결된 디바이스가 데이터를 해당 주제의 여러 구독자에게 브로드캐스트할 수 있게 해줍니다. 디바이스 게이트웨이는 MQTT, WebSockets 및 HTTP 1.1 프로토콜을 지원하며, 고유 또는 레거시 프로토콜을 지원하도록 손쉽게 구현할 수 있습니다. 디바이스 게이트웨이는 인프라 프로비저닝 없이 수십억 개의 디바이스를 지원하도록 자동으로 확장됩니다.
자세한 내용은 AWS IoT 사용 설명서의 프로토콜을 참조하십시오.
인증 및 권한 부여 
AWS IoT는 모든 연결 지점에서 상호 인증 및 암호화를 제공하므로 디바이스와 AWS IoT 간에 입증된 자격 증명 없이는 데이터가 교환되지 않습니다. AWS IoT는 AWS의 인증 방법(‘SigV4’라고 부름)뿐 아니라X.509 인증서 기반 인증을 지원합니다. HTTP를 사용하여 연결하면 이러한 메서드 중 하나를 사용할 수 있고, MQTT를 사용하여 연결하면 인증 기반 인증서를 사용할 수 있으며, WebSockets를 사용하여 연결하면 SigV4를 사용할 수 있습니다. AWS IoT에서는 AWS IoT에서 생성한 인증서뿐만 아니라 선호하는 인증 기관(CA)에서 서명한 인증서도 사용할 수 있습니다. 원하는 역할 및/또는 정책을 각 인증서에 매핑하여 디바이스 또는 애플리케이션에 액세스 권한을 부여하거나, 마음이 바뀐 경우 디바이스를 직접 조작하지 않고도 액세스 권한을 모두 취소할 수 있습니다.
콘솔이나 API를 사용해 디바이스에 대한 인증서와 정책을 생성, 배포 및 관리할 수 있습니다. 이러한 디바이스 인증서는 AWS IAM를 사용해 구성된 관련 정책으로 프로비저닝 및 활성화하고 해당 정책과 연결할 수 있습니다. 이를 통해 원하는 경우, 개별 디바이스에 대한 액세스를 즉시 취소할 수 있습니다. 또한, AWS IoT는 앱 사용자에 대한 고유 식별자를 생성하고 제한적인 임시 AWS 자격 증명을 가져오는 데 필요한 모든 단계를 처리하는 Amazon Cognito를 사용하여 사용자의 모바일 앱으로부터의 연결도 지원합니다.
자세한 내용은 AWS IoT 사용 설명서의 보안 및 인증 섹션을 참조하십시오.
레지스트리 
레지스트리는 디바이스에 대한 자격 증명을 설정하고 디바이스의 속성 및 기능 같은 메타데이터를 추적합니다. 레지스트리는 디바이스 유형이나 연결 방식과 관계없이 지속적으로 형식이 지정되는 각 디바이스에 고유 자격 증명을 지정합니다. 또한, 예를 들어 센서가 온도를 보고하는지 그리고 데이터가 화씨인지 섭씨인지와 같은 디바이스의 기능을 설명하는 메타데이터를 지원합니다.
레지스트리를 사용하면 추가 비용 없이 디바이스에 관한 메터데이터를 저장할 수 있으며, 최소 7일에 한 번 이상 레지스트리 항목을 액세스 또는 업데이트하기만 하면 레지스트리에 저장된 메터데이터가 계속 유지됩니다.
자세한 내용은 AWS IoT 사용 설명서의 레지스트리 섹션을 참조하십시오.
디바이스 섀도 
AWS IoT에서는 디바이스의 최신 상태가 포함된 각 디바이스의 영구, 가상 버전 또는 "섀도"를 생성하여 애플리케이션이나 다른 디바이스가 메시지를 읽고 해당 디바이스와 상호 작용할 수 있습니다. 디바이스 섀도는 디바이스가 오프라인이더라도 각 디바이스의 최종 보고된 상태와 원하는 이후 상태를 유지합니다. API 또는 규칙 엔진을 사용하여 디바이스의 최종 보고된 상태를 가져오거나 원하는 이후 상태를 설정할 수 있습니다.
디바이스 섀도에서는 언제나 사용 가능한 REST API를 제공함으로써 디바이스와 상호 작용하는 애플리케이션을 손쉽게 구축할 수 있게 해줍니다. 또한, 애플리케이션은 디바이스의 현재 상태를 확인하지 않고도 디바이스의 원하는 이후 상태를 설정할 수 있습니다. AWS IoT는 원하는 상태와 최종 보고된 상태의 차이를 비교하여 디바이스에게 차이를 없애도록 명령합니다.
AWS IoT 디바이스 SDK를 사용하면 디바이스에서 손쉽게 섀도와 상태를 동기화하고, 섀도에서 설정한 원하는 이후 상태를 처리할 수 있습니다.
디바이스 섀도에서는 최대 1년까지 무료로 디바이스 상태를 저장할 수 있습니다. 디바이스 섀도는 최소 1년에 한 번 이상 업데이트하면 영구적으로 유지되며 그렇지 않은 경우 종료됩니다.
자세한 내용은 AWS IoT 사용 설명서의 디바이스 섀도 섹션을 참조하십시오.
규칙 엔진 
규칙 엔진을 사용하면 인프라를 관리할 필요 없이 글로벌 규모로 연결된 디바이스에서 생성된 데이터를 수집, 처리, 분석하고 이를 기반으로 조치를 취할 수 있습니다. 규칙 엔진은 AWS IoT에 게시된 수신 메시지를 평가하고, 정의한 비즈니스 규칙에 따라 다른 디바이스나 클라우드 서비스로 이를 변환 및 전송합니다.규칙은 하나 이상의 디바이스의 데이터에 적용할 수 있으며 하나 이상의 작업을 동시에 수행할 수 있습니다.
또한, 규칙 엔진은 AWS Lambda, Amazon Kinesis, Amazon S3, Amazon Machine Learning, Amazon DynamoDB, Amazon CloudWatch, Kibana와 기본적으로 통합되어 있는 Amazon Elasticsearch Service 등과 같은 AWS 엔드포인트로 메시지를 라우팅할 수 있습니다. 외부 엔드포인트에는 AWS Lambda, Amazon Kinesis 및 Amazon Simple Notification Service(SNS)를 사용해 전달할 수 있습니다.
관리 콘솔에서 규칙을 작성하거나 유사 SQL 구문을 사용하여 규칙을 작성할 수 있습니다. 규칙은 메시지의 콘텐츠에 따라 다르게 동작하도록 작성할 수 있습니다. 예를 들어, 온도 값이 특정 임계치를 초과하는 경우 AWS Lambda로 데이터를 전송하도록 규칙을 트리거할 수 있습니다. 또한, 규칙은 다른 서비스의 데이터와 같이 클라우드의 다른 데이터를 고려하도록 작성할 수 있습니다. 예를 들어, 온도가 5개의 다른 디바이스 평균보다 15% 이상 높으면 조치를 취하도록 할 수 있습니다.
규칙 엔진은 데이터 변환에 사용할 수 있는 수십 개의 함수를 제공하고, AWS Lambda를 사용해 원하는 만큼 추가로 함수를 생성할 수 있습니다. 예를 들어, 다양한 값을 처리해야 하는 경우 수신되는 숫자의 평균을 사용할 수 있습니다. 또한, 규칙은 AWS Lambda에서 Java, Node.js 또는 Python 코드가 실행되도록 트리거할 수 있으므로 디바이스 데이터 처리를 위한 최고의 유연성 및 기능을 제공합니다.

[퍼온글]SKT, 전용망 전국 구축… 저전력 장거리 통신 기술 기반

SKT, 전용망 전국 구축… 저전력 장거리 통신 기술 기반

맨홀 관제ㆍ주차 공유ㆍ응급 알림 등

연말까지 20개 신규 서비스 출시

LGU+는 IoT 사업부 CEO 직속으로
가정용 상품 연내 50여종 확대
지하 통신구 등과 연결되는 길거리 구멍인 ‘맨홀’은 전국에 150여만개나 된다. 통상 검침원들은 일정 기간마다 맨홀 뚜껑을 열고 아래로 내려가 수도나 가스계량기 등을 확인한 뒤 검침 결과를 보고한다. 만약 사물끼리 인터넷으로 연결돼 서로 정보를 주고받는 ‘사물인터넷’(IoT) 기술이 맨홀에 적용된다면 사람이 일일이 맨홀을 찾지 않아도 원격 검침이 가능하다. 그러나 지금까지 이런 아이디어는 현실성이 없었다. 맨홀에 IoT 기능을 구현하려면 통신이 가능한 부품(모듈)을 붙여야 하는데, 이 모듈의 가격이 비싼 데다 맨홀에 적합하게 가공하는 데도 적지 않은 비용이 들어 투자 대비 효율이 낮기 때문이다.

그러나 ‘저전력 장거리 통신 기술’이 도입되면 얘기가 달라진다. 이 기술은 한 번에 보낼 수 있는 데이터 양이 적고 속도가 느린 대신 저전력ㆍ저비용ㆍ긴 도달 거리의 특성을 갖고 있다. 스마트폰으로 고화질 동영상을 볼 때처럼 대용량 데이터가 아닌 소량의 단순 정보를 주고받는 것이 목적이어서 ‘소물(小物)인터넷’으로도 통한다. 이 기술이 맨홀에 적용될 경우 기존 대비 최대 10%의 비용만으로도 원격 검침을 할 수 있다.

전국에 300여만개가 깔린 가로등도 마찬가지다. 지금처럼 단순히 가로등을 켜고 끄는 것뿐 아니라 주변 상황에 따라 밝기를 조절할 수 있다.

SK텔레콤은 4일 이러한 저전력 장거리 통신기술 기반의 IoT 전용망 ‘로라 네트워크’를 전국에 구축하고 IoT 사업을 본격화한다고 밝혔다. 지난 3월 전국망 구축 계획을 발표한 지 3개월 만이다. 지금까지 SK텔레콤은 기존 이동통신용 LTE망의 일부를 활용한 IoT 전용망(LTE-M)을 운영해 왔는데, 여기에 로라 네트워크까지 갖춰 세계 최초로 두 개의 전용망을 함께 제공하는 업체가 됐다. 이를 활용해 2017년 말까지 IoT 전용망에 400만개 이상의 기기가 연결되도록 한다는 게 SK텔레콤의 목표다.

다양한 IoT 서비스와 상품도 잇따라 선보일 예정이다. 이달 가스 원격 검침(AMI) 사업을 시작으로 초ㆍ중학생들이 위급 상황에 처했을 때 알려주는 착용형(웨어러블) 기기인 ‘세이프 워치’ 사업, 도로의 맨홀 관제 사업, 실시간 주차 공간 공유 사업 등 연말까지 총 20개의 신규 서비스가 출시된다.

이를 위해 SK텔레콤은 월 기본료 350~2,000원(부가세 별도)의 ‘로라 IoT요금제’를 내놨다. 매 시간 한 번씩 정보를 제공하는 가스 검침기는 1회당 평균 64바이트의 데이터를 사용하므로 한 달 350원을 내는 최저 요금제를 이용하면 된다.
전 세계 IoT 시장은 지난해 약 80조원에서 2020년 344조원 규모로 성장할 전망이다. IoT로 연결된 기기 수도 지난해 50억개에서 2020년 약 268억개로 폭증할 것으로 예상된다. 때문에 IoT 시장을 차지하려는 국내 통신업체들의 경쟁에도 불이 붙었다.

가정용 IoT 서비스를 선도하고 있는 LG유플러스는 현재 온도 조절기, 문 열림 감지 등 28종인 가정용 IoT 상품을 연내 50여 종으로 확대할 계획이다. 서비스 상용화 1년만에 34만가구를 넘어선 가입자 수도 연말까지 50만 가구로 늘린다는 목표다. 이를 위해 LG유플러스는 지난 1일 ‘IoT서비스 부문’을 ‘IoT사업 부문’으로 명칭을 바꾸고, 기존 신사업 추진 부서에서 최고경영자(CEO) 직속 부서로 옮기는 조직 개편을 단행하면서 사업 추진에 힘을 싣고 있다.

이서희 기자 shlee@hankookilbo.com
[출처] SKT Iot망|작성자 동시사랑

2016년 8월 28일 일요일

[퍼온글]Inner class에서 local variable에 접근하려면 final이어야 하는 이유

안드로이드 개인 프로젝트를 진행하는 중에 옆에 있던 동기 누나가 생긴 오류로 코드를 들여다보았다.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);      
        fragmentManager=getFragmentManager();
        fragmentTransaction=fragmentManager.beginTransaction();
        ContentsViewFragment contentsViewFragment=new ContentsViewFragment();
        fragmentTransaction.add(R.id.fragment_container,contentsViewFragment);
        fragmentTransaction.commit();
        // 1. Action bar에서 navigation drawer toggle버튼을 클릭하면 navigation list가 나옴
        //    -> navigation list에 eventlistener 설정
        //    -> selectCategory()
        upperToolbar=(Toolbar)findViewById(R.id.upper_toolbar);
        setSupportActionBar(upperToolbar);
        // 2. 하단에 Action bar로 home, search, write, mypage 버튼 구성 및 eventㅣistener로 각 fragment로 연결
        //    -> selectMenu()
        //    -> home : ContentsViewFragment
        //    -> search: before search; BeforeSearchFragment, after search; ContentsViewFragment, action bar 검색어 입력 모드로 연결
        //    -> write: WriteCategoryFragment
        //    -> mypage: MyPageFragment
        //bottomToolbar는 standalone으로 구현
        bottomToolbar=(Toolbar)findViewById(R.id.bottom_toolbar);
        bottomToolbar.inflateMenu(R.menu.menu_bottom_bar);
        bottomToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener(){
@Override
public boolean onMenuItemClick(MenuItem item) {
        switch(item.getItemId()) {
        case R.id.home:
        ContentsViewFragment contentsViewFragment=new ContentsViewFragment();
        fragmentTransaction.replace(R.id.fragment_container,contentsViewFragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
        break;
        case R.id.search:
        BeforeSearchFragment beforeSearchFragment=new BeforeSearchFragment();
        fragmentTransaction.replace(R.id.fragment_container,beforeSearchFragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
        break;
        case R.id.write:
        WriteCategoryFragment writeCategoryFragment=new WriteCategoryFragment();
        fragmentTransaction.replace(R.id.fragment_container,writeCategoryFragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
        break;
        case R.id.mypage:
        MyPageFragment myPageFragment=new MyPageFragment();
        fragmentTransaction.replace(R.id.fragment_container,myPageFragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
        break;
        }
    return true;
  }
});
}
        });

 activity_main이 fragment로 화면을 바꾸어 주는데, 아래에 Toolbar로 변경할 수 있도록 구성했다. onMenuItemClick()에 switch문에서 id값에 따라 fragment를 바꿔준다. 코드를 보면 setOnMenuItemClickListener() 안에 new Toolbar.OnMenuItemClickListener() 로 Anonymous class가 선언되고 그 클래스의 onMenuItemClick() method 내에서 switch 구문을 구현한 것이다. 

코드를 실행하니 Inner class에서 local variable에 선언 된 변수에 접근하려니 에러가 발생했는데 그 내용이 'Inner class가 local variable에 접근하고 있다. 해결하려면 local variable을 final로 선언해야 한다' 라는 내용이었다.
 onMenuItemClick()의 switch 구문에서 onCreate()에서 선언된 contentsViewFragment 변수에 접근하면서 생긴 오류였다.

그 이유가 무엇일까 찾아보다가 깊이 있는 분석이 필요함을 느꼈다.

먼저 Inner Class의 개념에 대해 정확히 파악할 필요가 있었다. Java에는 Nested Class 가 있는데, 이 안에 Inner Class와 Lamda Expression이 포함된다. Inner Class는 다시 Local Class와 Anonymous Class가 있다. Java에서는 왜 Nested Class가 필요해졌으며, Inner Class에는 Local Class와 Anonymous Class가 분류되었을까? 이것에 대한 이해가 없이는 그 아래에 대한 이해가 힘들 것 같았다.

Nested Class가 왜 등장하게 되었는지 살펴보니
1. It is a way of logically grouping classes that are only used in one place
 개념적으로 하나의 클래스 B가 오직 다른 클래스 A에서만 유용하다면, B 클래스는 A 클래스 안에서 사용하는 것이 좋다는 것이다. 굳이 다른 곳에서 쓰는 일이 없는데 클래스로 빼낼 필요가 있을까라는 말인 듯 하다. 클래스로 만든 다는 것은 재사용성을 높이기 위함이 있으니까..

2. It increases encapsulation
 B 클래스가 A 클래스의 멤버에 접근해야 한다. 그러려면 public으로 선언하거나 protected로 선언해서 상속을 받아야 할 것이다. 하지만 inner class로 선언해두면 private으로 선언할 수 있다. 그리고 B class는 안에 있기 때문에 외부(outside world)로부터 숨을 수 있다.

3. It can lead to more readable and maintainable code
 좀 더 가독성이 좋고 유지보수하기 쉬운 코드가 된다고 한다. 

Nested Class는 2개의 카테고리로 나뉘는데 static nested class와 non-static nested class(inner class)로 나뉜다. Inner class는 enclosing class의 멤버가 private이더라도 접근할 수 있다.



Inner class의 경우 추가적으로 2가지 타입이 더 있다. Inner class는 method 안에서 선언할 수도 있는데, method 안에 선언하면 local class라고 부르고, class name 없이 method body 안에 선언하면 anonymous class라고 부른다.

Local class는 enclosing class의 멤버에 접근할 수 있다. method 내에 선언하는 class를 local class라고 하니 정확히는 method 내에 선언 된 변수를 의미하는 듯 하다. 그런데 Local class는 오직 final로 선언된 local variable에만 접근할 수 있다. 
"When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter."

Local Class가 local variable 또는 parameter에 접근(Java 8부터는 parameter에도 접근할 수 있다)하려고 하면 그 변수를 captured 한다는데 정확히 무슨 뜻인지 모르겠다. 복사한다는 뜻일까?

Anonymous Class도 Local Class와 마찬가지로 enclosing class의 member에 접근을 하려면 final로 선언이 되 있어야 한다고 했다.




이제 JVM 내부에서 어떻게 동작이 되길래 final에 접근하는지에 대한 고민이 필요했다.

http://www.slipp.net/questions/278 에서도 같은 고민의 글이 있어서 참고를 했다.

위에 읽은 글과 블로그의 내용을 바탕으로 이해한 것은 Anonymous Class나 Local Class에서 local variable에 접근을 하면 그 변수 값을 복사(captured)해서 사용하기 때문에 2개의 변수가 생겨서 값이 불일치 하는 상황이 생길 수 있다. 따라서 final로 선언해서 그런 일을 방지하려고 하는 것이다.
 위의 블로그에는 thread safe에 관해서도 얘기를 하고 있는데 거기까지는 이해가 되지 않고 있다. 좀 더 자세히 생각해봐야 할 것 같다.

[출처]http://ybin.tistory.com/8