2016년 9월 3일 토요일

[퍼온글]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