http://Simple Ionic 2 Login with Angular 2

이번에는 앱 개발 이야기를 좀 할께요~

개인적으로 최근에야 앱개발을 경험 해 볼 수 있었고, 안드로이드(자바) 와 아이폰 (Swift 3.0) 으로 각각 개발을 하였습니다.(오픈SDK 를 그대로 사용하지 못하는 단점이 워낙 커서 결국 그냥 네이티브로 결정했습니다). 개발하고 나서 부족한 점을 채우기 위해 또 개발을 추가 할 생각을 하니...가슴 한편이 답답해짐을 느꼈습니다. 내 경우는 매우 특이한 상황인데 기획,웹프론트,백엔드,IoT서비스플랫폼, 전력데이터분석개발에 추가로 네이티브 앱개발 2종도 모두 "혼자" 개발 했기 때문에  디테일이 떨어지며 이것을 고도화 및 유지보수를 위해 다시 건드리기가 좀 겁이 납니다. (빨리 해당분야의 전문인력들이 생겼으면 ㅜㅜ )  특히 UI 를 좀 더 화려하고 동적으로 꾸미고 싶은 경우는 더더욱 그러한데 비록 몇몇 경우는 각각의 네이티브 코드로 개발을 해야겠지만 적어도 UI 는 하나로 통일 하는게 좋겠다 싶어서 평소에 관심있었던 자마린 과 React Native 를 살펴보곤 했습니다.  

아래는 자마린에 대한 장,단점을 번역 해 보았습니다. React Native 보다는 자마린에 높은 점수를 주고 싶으며 아마 자마린으로 이주를 하게 될 거 같기도 합니다. 개인적으로 Javascript 를 안 좋아하기 때문에 JQuery mobile 이나 Ionic 프레임워크도 제외. 제 프로젝트의 경우 다양하고 빠른 정보의 업데이트가 필요한 분야가 아니라서 웹뷰의 활용도가 거의 없습니다. 뽀대와 성능은 네이티브구요.

참고로 이쪽 블로그에는 자마린 개발기가 있습니다. ->  리모릭스 개발 이야기 
자 이제 본문 시작 !! 





Xamarin 의 장,단점  (가장 최근 정보는 업데이트되지 않음) 

https://www.altexsoft.com/blog/mobile/the-good-and-the-bad-of-xamarin-mobile-development/   번역 

이제 앱개발에 있어서 Xamarin을 빼고 얘기 할 수 는 없을 것 같습니다. 전 세계적으로 1.4백만 개발자군을 거느리고 있는 마이크로소프트 테크놀러지에 기반한 이 새로운 툴에 대해서 말해보고자 합니다.

기술적으로 말하면,  Xamarin 은 C# 과 크로스-플랫폼을 위한 .Net 레이어로 쌓여진 네이티브 라이브러리 를 사용합니다. (크로스플랫폼 개발로 만들어지는 네이티브 앱이라는 야그~)

xamarin platform

 다른 모든것들과 마찬가지로 Xamarin 도 자신만의 장점과 단점을 가지고 있으며, 이어지는 글은 당신의 적절한 선택을 위해 훌륭한 정보를 줄 것입니다.

장점 

 왜 Trello, Slack 및 GitHub 를 비롯한 15,000 넘는 회사가 Xamarin 을 선택 했는지 알게 해줍니다.

⊕ 모든 플랫폼을 위한 하나의 기술 스택 

Xamarin 은 다양한 플랫폼에서 작동하는 앱을 만들기 위해 .Net 프레임워크와 C# 을 이용합니다. 그래서 96%의 소스코드를 재사용하여 빠르게 각각의 플랫폼을 위한 앱을 만들 수 있습니다. Xamarin 은 또한 개발 환경사이에 스위칭을 요구하지 않고 그저 Xamarin IDE(for Mac) 과 Visual Studio (for Windows) 를 사용하면 됩니다.  많은 개발자들이 각 개발툴이 지원하는것에  대해 논쟁하고는 있지만 Microsoft 가 책임진 이래로 굉장한 발전이 이루어지고 있습니다. 크로스플랫폼 개발툴은 이제 무료이며 IDE 의 빌트인으로 제공됩니다.   

⊕ 네이티브 급 성능 

웹기술에 기반한 전통적인 하이브리드 앱들과 다르게 ,  자마린으로 개발하면 네이티브로 빌드 됩니다.
성능은 안드로이드와 iOS 네이티브 앱과 비슷하며  더이상 효율,성능이 약점이 아니게 됩니다. 자마린 플랫폼은 테스팅과 앱 성능을 관찰 할 수 있는 완전한 솔루션을 제공합니다.  

⊕ 네이티브 급 사용자 경험 

자마린은 플랫폼 자체 UI 요소를 사용함으로써 사용자 경험이 강력해집니다. 간단한 크로스 플랫폼 앱은 Xamarin.Forms 툴을 사용하여 빌드되는데 app UI 컴포넌트들을 플랫폼 특정 인터페이스 요소로 변환합니다. Xamarin.Form 을 사용하면 앱 개발 속도가 향상되며 , 비지니스 향 프로젝트에 좋은 선택이 될 겁니다. 아직 여분의 추상레이어에 기인하여 성능에 아주 조금 문제를 줄 수 있습니다. 커스텀 app UI 와 높은 성능을 위하여  Xamarin.iOS 와 Xamarin.Android 를 분리하여 사용 할 수 도 있습니다. 

⊕ 전체 하드웨어 서포트 

자마린을 이용하면 기능적으로 대부분의 네이티브 레벨의 앱을 만들 수 있습니다. 모든 하드웨어 호환 이슈를 제거 하였으며, 플랫폼 사이에서 기능적으로 공통 디바이스와 함께  작업 하기 위하여 플러그인과 특정 APIs 를 사용 할 수 도 있습니다. 플랫폼 특정 APIs 에 접근하기 위해서 자마린은 네이티브 라이브러리들과 링크 할 수 있도록 지원합니다. 이건 작은 수고로 네이티브 레벨 기능들을 더 잘 사용할 수 있게 해줍니다. 

단점 

그러나 여전히 몇가지의 단점이 있는데요.

Θ 최신에 업데이트된 기능보다는 조금 늦은 지원 

이것은 Xamarin 개발자 팀에 전적으로 달려 있습니다. 자마린 같은 크로스플랫폼 용 도구가 최신 iOS 및 Android 릴리스에 대한 즉각적인 지원을 제공하는 것은 사실 불가능합니다. 변경 사항을 구현하거나 새로운 플러그인을 도입하는 데 시간이 좀 걸립니다.

Θ 오픈 소스 라이브러리를 사용하는데 제한 

네이티브 개발은 오픈 소스 기술을 광범위하게 사용합니다. Xamarin을 사용하면 플랫폼과 개발자 및 소비자 모두는 플랫폼에 의해 제공되는 컴포넌트과 몇몇  .Net 오픈 소스 리소스에서 제공하는 구성 요소 만 사용해야합니다. (역주 : Telerik 같은 유명 컴포넌트 회사에서는 이미 Xamarin 용 컴포넌트 가 출시되어있습니다). Android 및 iOS 모바일 앱 개발만큼이나 선택의 폭이 풍부하지는 않지만 Xamarin 구성 요소는 수천 개의 맞춤 UI 컨트롤, 다양한 차트, 그래프, 테마 및 기타 강력한 기능을 제공하여 앱에 추가 할 수 있습니다. 몇 번의 클릭. 여기에는 Stripe과 같은 내장 지불 처리, 비컨 및 웨어러블 통합, 푸쉬 서비스, 클라우드 스토리지 솔루션, 멀티미디어 스트리밍 기능 등이 포함됩니다.

Θ Xamarin 에코시스템 문제 

분명히 Xamarin 커뮤니티는 iOS 나 Android보다 훨씬 작습니다. 따라서 숙련 된 Xamarin 개발자를 찾는 것이 어려울 수 있습니다. 하지만 이 플랫폼은 Microsoft의 지원에 힘 입어 다음과 같이 성장하고 있습니다. 다양한 소스의 정보를 기반으로하는 Xamarin 커뮤니티는 전세계 모바일 개발의 10 %를 차지합니다. Xamarin 엔지니어의 수는 iOS 또는 Android 네이티브 커뮤니티와 아직 비교할 순 없지만 이 플랫폼은 개발자에게 광범위한 지원을 제공합니다. 즉,이 기술에 익숙하지 않은 사람들을 위한 리소스와 실습을 제공하는 훌륭하고 풍부한 교육 플랫폼인 Xamarin University가 있습니다. 이 지원을 이용하면 숙련된 C # / .Net 엔지니어의 학습 곡선이 최소화됩니다.  (역주: 영어가 모국어 만큼 편해야한다는게 함정.. ;;) 

Θ  UX architecture 에 있어서 약간의 문제.

멋진 네이티브 UX로 iOS 및 Android 용 훌륭한 앱을 개발하려는 경우 가장 큰 문제는 플랫폼 간 UX 아키텍처의 큰 차이입니다. 이것은 Xamarin이 당신에게 큰 어려움을 줄 수도 있는 문제입니다. 이러한 차이가 난이도의 80 % 이상이기 때문에 Xamarin이 제공 할 수있는 최대 값은 실제로 다루는 문제의 20 %로 제한됩니다.

Xamarin이 해결하지 못하는 이 문제를 사소하게 바라 볼 순 없습니다. UX 코딩, 애니메이션, 리소스, 동기화,보기, 워크 플로우 등의 차이는 iOS와 Android 사이에서 뚜렷이 구분 될 지 모릅니다

Even if you target only one mobile platform, the benefit of knowing .NET cannot help you with something as simple as loading an image.  You learned about the .NET Bitmap class, GDI, etc.?  That knowledge is really not very useful for mobile apps.  So a key issue here is that Xamarin touts “leveraging existing .NET knowledge”, however this comes with the huge asterisk.  A significant part of your .NET knowledge won’t apply here.



P.S


근데 왜 최근 자마린 한글 번역서는 하나도 없는지 모르겠군요. 무료이며 비쥬얼 스튜디오라는 강력한 툴과 C#으로 무장한 자마린을 활용하고자 하는 사람들이 많을텐데 말이지요.. C# 은 자바했으면 어렵진 않을거고



1. Ionic App 안의 AngularJS 에서 토큰기반 인증 개발하기 

 

여기서 알아볼것은 아래와 같다. 

  • 사용자 로그인 및 유져세션 저장  ( 토큰 기반 인증 !)
  • 인증 상태 와 사용자롤 기반의 라우트 보호 
  • 인가안된 요청 알림 및 새로운  로그인 요청

여기의 예제구현은 Ionic App 이지만  많은 부분의 로직은 AngularJS 거나 마찬가지다.  따라서  사용자인증시스템을 AngularJS 에 넣던 하이브리앱에 적용하던 상관없이 이 기사가 유용할것이다. 함 즐겨볼까~?

(굉장히 많은 코드가 나열될것인데  이 기사 끝에  완전한 프로젝트에 대한 링크가 있다.)


프로젝트 초기 setup 하기!!

언급했듯이 , 우리는 아이오닉 프로젝트를 만들거고, 옵션은 blank (tabs 하지말고) 로 하자. 
이미 bower 는 인스톨됬다고 치고 , 아래  커맨드라인을 실행시켜서 프로젝트를 만들자.

(bower 는 npm install bower 하면 설치할수있다) 

만들어진 프로젝트에서   www/js/  폴더를 찾아서 다음 세가지 파일을 만들자  controllers.jsservices.js and constants.js.

index.html 의 헤더에 다음 파일들을 포함하고

추가적으로 app.js 에 ngMockE2E 디펜던스 추가.

다음으로  www/templates/  를 만들고 안에  아래 html 파일  추가 

login.htmlmain.htmldashboard.htmlpublic.htmladmin.html.

이쯤하면 일단  초기세팅은 됬고 , 이제 인증 코딩을 시작해보자~


공통 상수 만들기!!

일단 우리는 어디에서나 접근할수있는 몇가지 상수를 정의해야한다. 이것들은 이벤트나 권한(롤)을
위한 문자열 정의로서  constants.js 파일에 다음을 넣자.


뷰 만들기 !!

우리가 만들 앱은 로그인뷰 와 3개의 탭으로 구성된 간단한 모양새인데 , 탭들은 유저인증에 의해 보호되고있다.
로그인을 하지않고서는 저 탭들의 뷰에 라우팅 할 수 없다는 말이다. (기사 마지막쯤 하이라이트가 나온다.) 

index.html 을 열고 다음과 같이 변경하자.

우리는 라우트로 연결된 뷰를 보여줄수있는 네이게이션 뷰와 바를 가지고있다.  
각 뷰와 연결될 컨트롤러들을 controller.js 파일을 열어서 다음과 같이 추가한다.

login 뷰는 다음과 같이 2개의 입력필드를 가질것이고 로그인 액션을 위한 하나의 버튼을 갖는다.
login.html 을 열어서 아래와 같이 코딩해넣자.

다음 뷰는 탭들의 추상뷰인데 , 3개의 탭들은 라우트로 연결되있고 ,
nav-view 안에 연결된 뷰를 로드할것이다. main.html 을 열어서 아래와 같이 추가해넣자.

사용자가 로그인했을때 보여지는 첫뷰는 대시보드이다. 이 뷰는 환영인사 및 로그아웃버튼과 3개의 다른 요청버튼들로 
이루어져있다. 화면은 보이겠지만 모든 액션은 해당 컨트롤러와 서비스가 만들어지기전까진 작동하지 않을꺼다. 
dashboard.html 을 열고 아래와 같이 코딩해보자.

public.html 을 열어서 아래와 같이 코딩하자. 참고로 public 과 위의 dashboard 는 사용자 롤 기반.

마지막으로 admin.html 를 아래와 같이 코딩해넣자. 참고로 이것은 관리자 권한을 가지고있다.

아직까지는 실제 인증에 대한 어떠한 코드도 들어가있지 않다. 

기본 라우팅 구현 

우리 데모앱을 위한 라우팅은 매우 간단하다. 위에서 본것처럼 로그인뷰 및 3개의 탭뷰 정도?
여기서 특별한것은 37~39라인의 admin 탭과 연결된 데이타오브젝트정도인데, 이것은 USER_ROLES.admin 인 유저만 접근할수있게 한다. 지금 당장은 작동하지 않을건데 먼저 app.js 에 다음을 추가하자.   


angular-mocks 을 추가했고 , 그에 따라 하나 다른 기능을 app.js 에 추가해야한다.

이것은  $httpBackend  mock  기본 세팅이다.  우리의 일반 라우팅 요청은 통과시키고 (Ajax 요청에만 반응하도록) 
우리는 우리의 뷰에 접근할수있다. 지금 한번 serve / deploy 해보면 3개의 탭을 가지고 로그인된 모을 볼수있다. 
/main/dash  fallback 라우트 되어있다.  

user-authentication-interface

여기까지는 인증에 관해 별다른 코드가 없다. 자 진짜 사용자 인증에 관해서 알아보자. !!


사용자 인증 서비스 !!

지금 우리는 3개의 탭을 가진 탭바 인터페이스를 가지고있다. 하나는 데이터 오브젝트를 가지고있는데 그것은 오직 admin 롤을 가진 사용자한테만 허가되있다. 우리는 현재  다른 어떤 사용자 권한 서비스도 가지고 있지 않다.

추가해보자!! 

인증은 사용자가 로그인을 시작했을때 시작된다. 우리는 사용자 이름과 비밀번호를 획득할테고 , 서버로부터 토큰을
받는데 사용된다.  우리는 사용자 신용서를 로컬 스토리지내부에 저장할것이다.  우리는 사용자 정보 (이름 및 롤) 를 가지고있는 신용서를 사용할것이다. 중요한것은  $http.defaults.headers.common['X-Auth-Token']  을  설정한다는 것이다. 이 얘기는 앞으로 우리가 서버에 요청하는 모든것은 이 토큰 정보를 가지고 사인된다는 의미이다. (서버는 이것을 활용하는 로직을 만들어야겠지~) 

서비스의 로그아웃은 모든것을 되돌려 놓는데  (토큰을 삭제하고 세팅 초기화) destroyUserCredentials 를 호출한다.
보안된 기능을 호출한다던가, 라우팅할때 다음 2가지 함수에 의해서 검증되는데 

isAuthenticated
이것은 기본 인증 상태이다. 네가 사용자 권한을 만들때 항상 필요하다. 현재 유저가 로그인되었는지 아닌지 알려준다.

isAuthorized
이것은 특정한 라우트나 행동을 막기위한 허가 상태를 나타내는데 
USER_ROLES.public 를 가지면 이것에 알맞는 페이지나 행동만 할수있음을 나타낸다.

마지막으로 우리의 서비스가 만들어질때마다 자동적으로 로컬 스토리지로 부터 토큰을 가져와서 loadUserCredentials 가 호출된다. 결국 앱이 실행(?)될때, 저장소에 토큰이 존재하면 자동적으로 인증처리가되고 기능을 사용할수있게 된다.

services.js 에 다음을 추가해보자!

우리는 만약 우리가 요청을 비정상적인  토큰으로 요청한다면 우리는 경고를 줄것인데  그 기능을 위해서는
"인터셉터"가 필요하다. 인터셉터는 response 에러를 알려줄거고 우리의 앱에 브로드캐스트 할것이다.
services.js 에 다음을 추가하자.! 

우리가 서버에 요청할때마다 401 이나 403 을 리턴하는데 우리는 그 메세지를 브로드캐스트한다. 
우리는 어떻게 우리가 이런 메세지를 핸들링할수있는지 아래 컨트롤러에 관련 기능을 추가할때 볼수있다.


컨트롤러 만들기!


우리는 AppCtrl 을 추가할것이고 , 그것은 우리가 브로드캐스트한 모든 이벤트를 받고 핸들링 하는걸 보여준다. 
controllers.js 에 다음을 추가하자.  ($on 은 리스너이다)

인가되지 않았다는  이벤트를 받거나 허가되지 않은 요청에 대해서 사용자에게 알린다.
만약 우리가 인증되지 않았다는  이벤트를 받으면 우리는 AuthService.logout() 을 호출하고 로그인페이지로 바꾼다.
우리는 현재 사용자를 세팅하기위한  스코프평션을 가지는데 이것은 모든 자식 스코프에서 후에 사용될수있다.

다음은 LoginCtrl 이다. 우리의 로그인페이지와 연결되는데 로그인폼의 데이터와 액션과  연동된것을 볼수있다.
controllers.js 파일에 다시한번 추가하자.

로그인할때 우리는 AuthService 를 호출하며 만약 모든것이 정확하면 우리는 현재 사용자이름을 저장하고 대시보드상태로 이동한다. 대시보드상태는 로그인되어진 상태에서만 이동 가능하다. (이걸 하기위한 기능은 기사 마지막쯤에 등장)

마지막 컨트롤러는 DashCtrl 이며 이것은 4개의 기능을 수행한다. controllers.js 에 다음을 추가한다.

저런 요청은 허가없이 또는 로그인된 상태가 아닌 상황에서 (즉 그의 세션이 없어졌거나 타임아웃된 상황) 
무엇이 발생하고 언제 사용자가 리소스접근을 시도하는지 알려준다.  지금 당장은 작동하지 않을것이다.
작은 Mock 백엔드 객체를 추가해보자!!


mOCK  REQUEST / RESPONSE 코드를 위한 BACKEND HTTP 구현

이미 mock backend 가 app.js  에 있는데  몇가지 더 추가해보자. 

우리는 Mock responses 를 만들었다. 그것은 DashCtrl 에 의해 사용되며  이것에 의해 우리는 쉽게 어떻게 우리의 앱이 만약 401 , 403 을 만났을때 반응하는지 알아볼수있게 한다. 우리의 앱은 거의 끝났다. 하지만 진짜 중요한게 하나있다.


모든 상태 변경을 가로채다!!

지금까지 코딩된것으로는 사용자가 인증됬는지 체크하는 기능이 없다. 이것은 URL 을 바꾸는 누구던 아무문제없이 대쉬페이지로 접근할수있다는 말인데,  여기서 AngularJS 식의 방법으로 해결해보자. 우리는 라우트 변경 이벤트를 잡아낸다. 이것은 새로운 상태로 이동할때 마다 일어날것이다.  이때 인증에 관련된 처리를 하는데 app.js 를 열고 아래와 같이 추가한다.

변경을 캐취할때 2가지를 확인하는데 . 1. 사용자가 올바른 롤을 가지고있나? 
2. 사용자가 인증되어 있나? 이다. 

인증,인가를 확인한후에 적절한 처리를 하고있다.  완전한 소스는 아래에서 얻을수있다. https://github.com/saimon24/devdactic-ionic_login


서버쪽은 http://brad2014.tistory.com/266 포스트를 참조해 구축할수있다.




http://devdactic.com/user-auth-angularjs-ionic/  번역


로그인 시스템 만들기  (맛보기 버전) 

레퍼런스

https://github.com/saimon24/devdactic-ionic_login

http://devdactic.com/user-auth-angularjs-ionic/



클라이언트  구현  


// app.js 에서 login 상태 설정 

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider

  .state('login', {

      url: '/login',

      templateUrl: 'templates/login.html',

      controller: 'LoginCtrl'

  })


// template 에 login.html 추가  

<ion-view view-title="Login" name="login-view">

  <ion-content class="padding">

      <div class="list list-inset">

          <label class="item item-input">

              <input type="text" placeholder="Username" ng-model="data.username">

          </label>

          <label class="item item-input">

              <input type="password" placeholder="Password" ng-model="data.password">

          </label>

      </div>

      <button class="button button-block button-calm" ng-click="login()">Login</button>

  </ion-content>

</ion-view>



// 컨트롤러에서 login 함수 호출  ,  LoginService 를 DI 받고 있으며, 호출 성공,실패에 대한 콜백함수 등록되있다.

angular.module('starter.controllers', [])

.controller('LoginCtrl', function($scope, LoginService, $ionicPopup, $state) {

    $scope.data = {};

    $scope.login = function() {

        LoginService.loginUser($scope.data.username, $scope.data.password).success(function(data) {

            $state.go('tab.dash');

        }).error(function(data) {

            var alertPopup = $ionicPopup.alert({

                title: 'Login failed!',

                template: 'Please check your credentials!'

            });

        });

    }

})



// 서비스에서 ajax 를 통해서 서버에 로그인 호출 

.service('LoginService', function($q, $http) {

    return {

        loginUser: function(name, pw) {

            var deferred = $q.defer();

            var promise = deferred.promise;  // 프라미스 객체가져와서 

             // Ajax 호출 : 프라미스 객체 반환됨.

            var reqPromice = $http.post('http://192.168.1.191:8080/login', {username: name, password: pw});

     

 // 서버 로그인 호출  성공시    

     reqPromice.success(function(data){

                console.info("login Success !");

                deferred.resolve('Welcome ' + name + '!');  // resolve 를 호출하여 promise 객체의 success 실행

             });

             

           // 서버 로그인 호출 실패시 

            reqPromice.error(function(data){

               console.info("login fail !");

               deferred.reject('Wrong credentials.');                

            });


            promise.success = function(fn) {

                promise.then(fn);  // 서비스를 호출하는쪽에서 등록한 콜백함수를 호출해줌. 

                return promise;

            }

            promise.error = function(fn) {

                promise.then(null, fn);

                return promise;

            }

            return promise;

        }

    }

})



서버구축 


인증서버는 Node 로 구축한다.  Node 는 1편에서 설치했다. 

여기서는 Node 를 좀더 편하게 웹서버로서 사용가능하게 해주는 express 모듈을 설치해본다. 아래와 같이 설치하라. 

(여기서는 PACKAGE.JSON  (프로젝트  패키지 관리 파일)  를 활용하지 않는다) 


위처럼 다음 모듈도 설치한다.  

body-parser

cookie-parser

express-session


서버 실행은 다음과 같다. 

node run express_auth_session.js


이제 서버 코드를 살펴보자 

// 필요한 모듈을 가져온다. 

var express = require('express');

var bodyParser = require('body-parser');

var cookieParser = require('cookie-parser');

var session = require('express-session');

var crypto = require('crypto');


// 비밀전호를 해쉬화하고 문자열로 반환해준다.

function hashPW(pwd){

  return crypto.createHash('sha256').update(pwd).

         digest('base64').toString();

}


// express 모듈 설정

var app = express();

app.use(bodyParser.urlencoded({ extended: true }));

app.use(bodyParser.json());

app.use(cookieParser('MAGICString'));

app.use(session());


// 세션에 사용자가 설정되있다면 REST 호출 허용한다.

app.get('/restricted', function(req, res){

  if (req.session.user) {

        ...

  } else {

      req.session.error = 'Access denied!';

      res.send(200, {

             message: 'Acess denied ';

        });    

  }

});


//  로그아웃을 호출하면 세션에서 삭제해준다.

app.get('/logout', function(req, res){

  req.session.destroy(function(){

    res.send(200, {

     message: 'loggedOut sucess'

    });    

  });

});


//  로그인 동작 

app.post('/login', function(req, res){

  if (req.body.password === "mypass"){// 비밀번호 확인 , body-parser 이용 req.body 사용.

    console.info("success login");

   

    req.session.regenerate(function(){

      req.session.user = req.body.username;

      req.session.success = 'Authenticated as ' + req.body.username;

    });


    res.send(200, {

     message: 'loggedIn sucess'

    });    


  } else {

    console.info("success fail");

    req.session.regenerate(function(){

      req.session.error = 'Authentication failed.';

    });


    res.send(401, {

       message: 'loggedIn fail'

      });    


  }

});

app.listen(8080);  // express 실행 ( 8080번 포트로 ) 



여기까지하고 테스트해보면 

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8090' is therefore not allowed access.    

이건 동일 근원 법칙을 어긋나서 그런데 간단히 말해서  rest 서비스를 요청할때 이곳 저곳 서버에 요청할수 없는걸 말한다. 

(현재 페이지가 읽혀진 서버에만 요청가능)  해결하는 가장 쉬운 node  방법은 npm install cors 을 통해 모듈을 다운받은후에

var cors = require('cors');

var app = express();

app.use(cors());

이렇게 설정해두는것이다. ( 스프링 REST  서버도 마찬가지고 대부분 쉽게 해결하는 방법이 있다) 


IONIC 프로젝트 살펴보기 


tabs 기반의 기본 프로젝트 ( $ ionic start myApp tabs ) 는 다음과 같다.  하나씩 살펴보자 


├── bower.json     // bower dependencies
├── config.xml     // cordova configuration
├── gulpfile.js    // gulp tasks
├── hooks          // custom cordova hooks to execute on specific commands
├── ionic.project  // ionic configuration
├── package.json   // node dependencies
├── platforms      // iOS/Android specific builds will reside here
├── plugins        // where your cordova/ionic plugins will be installed
├── scss           // scss code, which will output to www/css/
└── www            // application - JS code and libs, CSS, images, etc.


www
├── css            // css
├── img            // 이미지
├── js             // 컨트롤러 
├── lib            // 아이오닉 관련 라이브러리들 
├── templates      // 뷰       
└── index.html     


index.html

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8">

    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">

    <link href="css/style.css" rel="stylesheet">


    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above

    <link href="css/ionic.app.css" rel="stylesheet">

    -->


    <!-- ionic/angularjs js -->

    <script src="lib/ionic/js/ionic.bundle.js"></script>


    <!-- cordova 스크립트 (this will be a 404 during development) -->

    <script src="cordova.js"></script>


    <!-- 포함될 어플리케이션 js 들, 프런트엔드 MVC 패턴   -->

    <script src="js/app.js"></script>

    <script src="js/controllers.js"></script>

    <script src="js/services.js"></script>

  </head>

  <body ng-app="starter">  // AngularJS  ng-app 디렉티브 선언  'starter' 은 메인  모듈 이름이다.

    <!--

      The nav bar that will be updated as we navigate between views.

    -->

    <ion-nav-bar class="bar-stable">

      <ion-nav-back-button>

      </ion-nav-back-button>

    </ion-nav-bar>

    

   <!--

      아래 뷰 디렉티브에 /templates 폴더에 있는 html 파일들이 보여집니다 

    -->

    <ion-nav-view></ion-nav-view>

  </body>

</html>



app.js

// angular.module 은 생성, 등록 및 Angular 모듈들을 불러오기위한  전역공간이다. 

// 'starter' 는  angular 모듈 예제의 이름이다.  ( index.html 의 body  태그에 속성으로 세팅되있다.) 

// 두번째 파라미터는  'requires' (의존 객체들)  의 배열이다. 

// 'starter.services' 는 services.js 에 구현되어있다.

// 'starter.controllers' 는 controllers.js 에 구현되어있다.


angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])

.run(function($ionicPlatform) {

  $ionicPlatform.ready(function() {

    // 디폴트로 엑세서리 바를 숨긴다 (엑세서리 바를 보이고 싶으면 이것을 지우시오)

    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {

      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

    }

    if (window.StatusBar) {

      // org.apache.cordova.statusbar required

      StatusBar.styleLightContent();

    }

  });

})


.config(function($stateProvider, $urlRouterProvider) {


  // 더 배우려면 여기로   https://github.com/angular-ui/ui-router

  // app 이 할수있는 다양한 상태를 셋업하라.

  // 각각의 상태들의 컨트롤러들은 controllers.js 파일에서 발견할수있다.

 $stateProvider


   // the tabs directive 를 위한 추상상태를 셋업하라.

    .state('tab', {

    url: "/tab",           // 경로 

    abstract: true,

    templateUrl: "templates/tabs.html"   // 연관 템플릿 뷰 

  })


  // 각각의 탭은 그것의 nav 히스토리 스택을 갖고있다.

  .state('tab.dash', {

    url: '/dash',

    views: {

      'tab-dash': {

        templateUrl: 'templates/tab-dash.html',   // 연관 템플릿 뷰 

        controller: 'DashCtrl'                            //  연관 컨트롤러 

      }

    }

  })


  .state('tab.chats', {

      url: '/chats',

      views: {

        'tab-chats': {

          templateUrl: 'templates/tab-chats.html',   // 연관 템플릿 뷰 

          controller: 'ChatsCtrl'                             //  연관 컨트롤러 

        }

      }

    })

    .state('tab.chat-detail', {

      url: '/chats/:chatId',

      views: {

        'tab-chats': {

          templateUrl: 'templates/chat-detail.html',   // 연관 템플릿 뷰 

          controller: 'ChatDetailCtrl'                       //  연관 컨트롤러 

        }

      }

    })


  .state('tab.account', {

    url: '/account',

    views: {

      'tab-account': {

        templateUrl: 'templates/tab-account.html',  // 연관 템플릿 뷰 

        controller: 'AccountCtrl'                            //  연관 컨트롤러 

      }

    }

  });


  // if none of the above states are matched, use this as the fallback

  $urlRouterProvider.otherwise('/tab/dash');


});


tabs.html

<!--

tabs-positive  을 사용하여 tabs 를 아이콘과 라벨을 가지고 만든다. 

각각의 탭의 자식인 <ion-nav-view> 디렉티브는 그 자신소유의 네비게이션 히스토리를 가질것이다. 

-->

<ion-tabs class="tabs-icon-top tabs-color-active-positive">


  <!-- Dashboard Tab -->

  <ion-tab title="Status" icon-off="ion-ios-pulse" icon-on="ion-ios-pulse-strong" href="#/tab/dash">

    <ion-nav-view name="tab-dash"></ion-nav-view>

  </ion-tab>


  <!-- Chats Tab -->

  <ion-tab title="Chats" icon-off="ion-ios-chatboxes-outline" icon-on="ion-ios-chatboxes" href="#/tab/chats">

    <ion-nav-view name="tab-chats"></ion-nav-view>

  </ion-tab>


  <!-- Account Tab -->

  <ion-tab title="Account" icon-off="ion-ios-gear-outline" icon-on="ion-ios-gear" href="#/tab/account">

    <ion-nav-view name="tab-account"></ion-nav-view>

  </ion-tab>



</ion-tabs>



tab-dash.html

<ion-view view-title="목록">

  <ion-content class="padding">

    <div class="list card">

      <div class="item item-divider">Recent Updates</div>

      <div class="item item-body">

        <div>

          There is a fire in <b>sector 3</b>

        </div>

      </div>

    </div>

    <div class="list card">

      <div class="item item-divider">Health</div>

      <div class="item item-body">

        <div>

          You ate an apple today!

        </div>

      </div>

    </div>

    <div class="list card">

      <div class="item item-divider">Upcoming</div>

      <div class="item item-body">

        <div>

          You have <b>29</b> meetings on your calendar tomorrow.

        </div>

      </div>

    </div>

  </ion-content>

</ion-view>




IONIC 프레임워크 시작하기 


Ionic Framework = Cordova + Angluar.js + Ionic UI 

한글소개 :  http://blog.saltfactory.net/239

메인         : http://www.ionicframework.com/

특징 ) 

1. 모바일 앱을 개발하기에 최적화된 UI가 기본적으로 제공한다. 

2. HTML으로 UI를 만들고 JavaScript의 데이타 업데이트를 빠르게 적용할 수 있다.

3. MVC 개발을 할 수 있는 환경을 제공한다.

4. 네이트브 자원을 사용할 수 있는 plugins 사용을 허용한다.

5. 크로스 플랫폼 빌드를 제공한다.

6. Node.js 기반으로 개발할 수 있는 환경을 지원한다.

7. 활발한 개발자 포럼을 지원하고 있다.



 개발환경 구축하기  (on Windows) 

 

1. 자바 JDK 설치 ( 1.7 버전 ) 

     SDK 설치후 PATH 설정까지 하세요.


 2.  Apache Ant 설치 

    안드로이드 나  Cordova 빌드시 필요합니다. 설치하고 PATH 설정까지 하세요.

     http://mirror.tcpdiag.net/apache//ant/binaries/apache-ant-1.9.4-bin.zip


 3.  안드로이드 SDK  설치  

  3-1. http://developer.android.com/sdk/index.html   에서 윈도우용  설치하시고 아래 처럼 두개 폴더를  패스 설정하세요.

  %Android SDK%\platform-tools;

  %Android SDK%\tools;

  3-2. cmd 창에서 android 명령어를 치면 다음과 같은 창이 나옵니다. 타겟 19, 21,22,24 버전 설치 (원하는 버전 설치) 

 


4. npm (node.js) 설치 

  https://nodejs.org/#download 에서 INSTALL 클릭 


node-v0.12.4-x64.msi 설치  ( 계속 NEXT 로 설치 ) 

 

  설치후에 CMD 창에서 npm 타이핑후 엔터치면 다음과 같이 나와야함. 



5.  Cordova 인스톨 

$ npm install -g cordova

6. 이제 npm 을 이용하여 ionic 을 설치합니다.  

$ npm install -g ionic  <-- 이거 타이핑해주면 알아서 설치합니다.!

Windows users: we strongly recommend Visual Studio Community for development which comes with everything you need.



7. 프로젝트 만들기 


$ ionic start M-MOS tabs      <-- 만들고싶은 폴더쪽으로 이동후 실행 !! M-MOS 는 프로젝트명 


blank / tabs / sidemunu 중 선택해서 기본 구성의 프로젝트를 만듭니다. M-MOS 는 제가 만드는 프로젝트 이름입니다.

아래와 같은 구성을 가진 프로젝트가 만들어졌습니다.


8. 프로젝트 실행   (IOS 모드 or 안드로이드 모드) 

$ cd M-MOS
$ ionic platform add ios or android 
$ ionic build ios or android           

$ ionic emulate ios or android    // 에뮬레이션을 통한 앱 실행  
$ ionic run ios or android  -device      // 기기를  통한 앱 실행 

$ ionic serve // 내장서버가 동작하면서 브라우저에서 실행 // 내장서버가 동작하면서 스마트폰에서 폰갭 앱 받아서 실행 $ ionic serve --lab // --lab붙히면 모바일화면하고 같아진다. 이거 써라~


 ionic serve 로 동작한 웹 앱은 웹 자원의 수정 사항이 있을 경우 자동으로 reloading을 하게 되어서 변경된 내용을 바로 웹에서 적용해서 변경된 사항을 확인할 수 있다. dash의 내용을 수정하기 위해서 www/templates/tab-dash.html의 파일을 열어서 다음과 같이 수정한다.

<ion-view title="목록">  // "Dashboard" -> "목록" 으로 변경 

  <ion-content class="padding">

     ....

     ....

  </ion-content>

</ion-view>


HTML 파일을 수정하면 ionic serve는 변경된 파일을 감지하고 reloading를 실행한다. 그래서 브라우저에서 refresh 필요 없이 브라우저로 이동하면 다음과 같이 변경된 내용이 적용된 것을 확인할 수 있다. 웹브라우저에서는 네이티브기능은 확인할수없다.


PATH들 예 ) 

%JAVA_HOME%\bin;

%ANT_HOME%\bin;

%Android SDK%\platform-tools;

%Android SDK%\tools;

C:\Users\brad\AppData\Roaming\npm 


 하이브리드 앱을 만들어보는게 목적으로 매우 심플한 어플리케이션이 될것입니다.


IoT 엣지디바이스가 전기스위치 및 미터기(전력 계량기) 라고 가정하고 ,


1.인증기능   

2. 스위치를 켜고 끄는 기능  (숫자를 입력하여 켜기,  QR 코드를 입력받아서 켜기, 등록된거 선택해서 켜기) 

3. 해당 스위치의 현재 상태 ( 전기의 파워와 미터) 를 디스플레이 하는기능


의 간단한 기능을 가진 하이브리드앱을 만들어 보겠다. 

프런트엔드는 아이오닉 프레임워크를 사용할 예정이며, 백엔드는 Vert.x or Spring 을 사용할 예정이다.


p.s 엣지 디바이스와 진짜 통신이 되기 위해서는  웹서버 -> 디바이스로  연결하게 해도 되고 , 직접  와이파이 다

이렉트 등을 통해 스마트폰 -> 디바이스 이렇게   연결될수도있겠지만~ 하이브리드앱 -> 웹 서버 -> 중계서버 -> 

인텔리전스 서버  -> 집중화서버 -> 컨트롤러 -> 엣지디바이스  이렇게 복잡하게 연결할수도 있겠다.

      

다음과 같은 순서대로 개발하면 될거 같다. 


IONIC 프레임워크 설치

로그인 시스템 만들기  

스위치 켜고 / 끄기

스위치 상태 보여주기

구글/아이폰 마트에 앱 올리기  


+ Recent posts