2019년 10월 30일 수요일

시퀀스맵으로 유저스토리를 만들어 TDD 까지 연계해보자


문서와 설명으로만 프로젝트를 진행하는 경우가 있다. 다들 머리속에는 같은 것을 그리고 있는데 아무도 그걸 구체화 시키지 않는다. 특히나 프로그래머는 뭐든지 로직으로만 생각하는 경우가 있는데, 그렇게 하다보면 로직->테스트코드작성 순으로 생각하게되는경향이 있다.
따라서 로직은 개발자한테 맡기되 고객/기획/디자이너/개발자가 공통된 하나의 스토리를 기반으로 같은 상상을 하게 해주는 좀더 구체화된것이 필요하다.
DDD 의 유비쿼터스언어 또한 언어라는 한계에서오는 제한으로 쉽게 진행되지 못하는경우가 있다.
이것을 애초부터 순서도로 만드는 거다. 인간의 언어에 제한되지 않는 순서도로 만들어서 상상했던 결과물이 최종결과물과 같은 순서도를 가진다면 누구나 수긍할수있는 프로젝트가 될것이다.

순서도를 그리는데는 시간도 걸리고 솔직히 귀찮다.
정말 좋은 PlantUml 을 사용해서 조금이라도 덜 귀찮게 만들수 있다.
단, 쓸데없는 중복코드를 피하기 위해서 별도의 함수파일을 만들자.

장점으로는 빨간색글씨로 TestCaseStory 를 미리 지정하여 , 테스터와 개발자가 동시에 테스트케이스를 작성할수 있다는거다.
10 단위로 되어있는 항목 중간에 1단위의 세부 항목을 넣을수 있다.



methods.txt
@startuml

title "Sequence UML"

!global $current_action = ""
!global $auto_num_step = 10
!global $current_auto_num = 0



!function a($to, $action)
     a($current_action, $to, $action)
!endfunction

!function a($from, $to, $action)
     !if ($action == 0 || $action == 1)
         setautonum($action)
         a($current_action, $from, $to)
     !else
          $from -> $to : $printautonum() $action
          !$current_action = $to
     !endif
   
!endfunction


!function alt_start($condition)
     alt $condition
!endfunction

!function alt_else($condition)
     else $condition
!endfunction

!function alt_end()
    end
!endfunction


!function s($from)
     activate $from
!endfunction

!function e($from)
     deactivate $from
!endfunction

!function setautonum($step)
     !$auto_num_step = $step
!endfunction


!function resume()
     !$auto_num_step = 10
     !$current_auto_num = ( $current_auto_num / 10 ) * 10
!endfunction


!function resetautonum($num)
     !$auto_num_step = 10
     !$current_auto_num = $num - $auto_num_step
!endfunction


!function $printautonum()
     !$outprint = $current_auto_num
     !$current_auto_num = $current_auto_num + $auto_num_step
     !if ($auto_num_step == 0)
          !$outprint = ""
          !$auto_num_step = 10
     !else
          !$outprint =   "<font color=red><b>[TCS1_" + $test1($current_auto_num)    +"]</b></font>"
     !endif
     !return $outprint
!endfunction

!function $test1($step)
     !if (%strlen($step) == 2)
          !return  "0" + $step
     !endif
     !return  $step
!endfunction

!function n($from,$message)
     note right of $from
            $message
     end note
!endfunction



@enduml


Source.txt

@startuml
!include methods.txt


'--- 사용자/앱구분 ---
!$유저 = "유저"
!$유저 = "유저"

'--- 참가화면 ---
!$메인화면 = "메인화면"
!$탭메뉴 = "탭메뉴"

!$쿠폰메인화면 = "쿠폰메인화면"
!$카테고리목록 = "카테고리목록"
!$상점목록 = "상점목록"
!$더보기단순링크 = "더보기_단순링크"
!$쿠폰목록 = "쿠폰목록"

!$앱 = "앱"


box "DPoint앱" #LightBlue
actor $유저
end box

box "메인화면" #LightBlue
     participant $메인화면
     participant $탭메뉴
end box

box "쿠폰화면" #LightBlue
     participant $쿠폰메인화면
     participant $카테고리목록
     participant $상점목록
     participant $더보기단순링크
     participant $쿠폰목록
end box


== TCS1 : 앱기동후 쿠폰탭을 클릭하여 쿠폰메인화면으로 이동 하는 유저스토리 ==
a($유저, $메인화면, "앱기동")
a($탭메뉴, "쿠폰버튼클릭")
     a($쿠폰메인화면, "화면오픈")
     s($쿠폰메인화면)
          a($카테고리목록, "카테고리목록표시",0)
          n($카테고리목록,"기본1개목록표시")
                 
          s($카테고리목록)
               a($카테고리목록,"기본1개목록표시",1)
               resume()
               a($카테고리목록,"기본2개목록표시")
               a($카테고리목록,"기본2개목록표시")
               resetautonum(100)
               box "test1" #LightBlue
                    a($카테고리목록,"기본2개목록표시")
                    a($카테고리목록,"기본3개목록표시")
               end box
               resume()
               alt_start("해당카테고리의 쿠폰이 1개이상있을시")
                    a($카테고리목록 , "일반카테고리목록표시")
               alt_end()
               a($카테고리목록 , "카테고리\n자동선택")
                    activate "카테고리목록"

               a($메인화면, $탭메뉴, "메뉴변경")

               alt_start("해당카테고리가없거나\n처음 시동시")
                         a($카테고리목록, $카테고리목록, "전체항목선택")
               alt_else("이전에 선택한 탭이 있었고\n 해당항목이 존재할경우 ")
                         a($카테고리목록, "지정된항목선택")
               alt_end()
               deactivate "카테고리목록"
          e($카테고리목록)
     e($쿠폰메인화면)

@enduml



2019년 10월 21일 월요일

IOS 의 GCD ( Grand Central Dispatch) 로 쓰레드처리를 편하고 안전하게.

쓰레드의 락, 동기화 이런거 신경쓰지 않고 GCD를 사용하여 메인 쓰레드에 단순히 dispatch 하면 걍 실행된다능.

헤더파일에서

@interface SingleToneSample : NSObject
+ (instancetype) sharedInstance;
@end


처럼 간단하게 공개용 함수만들고 구현파일에서는

+(instancetype)sharedInstance {
    static SingleToneSample *shared = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shared = [[SingleToneSample alloc] init];
        
    });
                  
    return shared;
}

처럼 실체를 만들면된다.


참고

https://padgom.tistory.com/entry/iOS-%EA%B8%B0%EB%B3%B8-GCDGrand-Central-Dispatch-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

Cocoa Touch Framework 을 이용해서 공통모듈 만들기

안드로이드에서 aar 화일을 만들어 쓰듯이, Xcode 6 부터는 개발자가 Framework 프로젝트를  만들어서 여러프로젝트에 공통으로 사용할수 있도록 되었다.

1.일단 워크스페이스부터 따로 만든다.
2.새 프로젝트를 만들어야 하는데 [cocoa touch framework] 를 선택해서 새로 만든다.
 맨 마지막 프로젝트 폴더 선택하는 부분에서  add to 와 group 선택박스를 아까 생성한 워크스페이스로 선택한다.
3.프로젝트 구성을 보면 프레임헤더화일, 테스트 , 프로덕트가 있고 안에 .framework 파일이 있는데 아직 빌드를 안해서 빨강색이다.
4.프레임헤더를 열어보면 맨마지막줄에 public , 공개로 사용할 헤더를 적어주면 외부에서 해당 기능을 사용할수 있게된다라고 되어있다.
#import <myframework/Car.h> 라고 하자
5.이제 새화일->코코아터치 클래스 를 선택해서 Car.h , Car.m 을 만들자.
6.car 클래스는 평소대로 하고싶은 코딩을 한다.
7.이제 중요.
8. Car.h 를 선택하면 오른쪽 속성 판넬에 [Target MemberShip] 항목에 프레임이름과 private|public|project 가 있다.  외부에서  car 클래스에 접근하려면  하려면 public 으로 해야 된다.
9.그위의 Location 도 Relative to Group 으로 지정한다.
10. 왼쪽의 프로젝트 파란 놈을 클릭하고 항목에서 [Build Active Architecture Only] 를 No 로 해주어야 다른 플랫폼에서도 작동할수 있게된다.
11.프레임워크 프로젝트에서 빌드를 한다. 이떄 호환성을 위해서 에디터 상단의 빌드 디바이스를 [제너릭 디바이스] 로 지정하고 빌드한다.
12.왼쪽의 products/myframework.framework 파일이 생성되면 왼쪽으로 가는 화살표를 클릭해서 해당 폴더에서 파일을 복사해논다.
13.이제 아까만든 프레임워크를 사용할 프로젝트를 만든다. 워크스페이스, 프로젝트 폴더는 따로 만들어서 완전히 새로운 프로젝트를 구성한다.
14.새로운 프로젝트를 만들었으면 프레임워크를 보관할 임의의 폴더(그룹)를 만든다(임시로 framework 라고 만들었다. )
15. 만든 폴더에 아까의 프레임워크를 붙여넣는다.
16. 프레임워크를 사용하려면 m 파일에서 프레임워크에서 공개(public)으로 지정한 헤더를 임포트해서 해당 클래스를 사용하면된다.

#import <myframework/Car.h>
...
    Car *car = [[Car alloc] initWithName:@"audi"  year:1990];
    [car info];
17.이상태에서 빌드시에 에러가 나오기도 하는데  x86_64 관련에러는 프레임워크로 돌아가서 프로젝트 설정에 [Build Archtecture Active Only] 를 No 로 설정하고 다시 빌드후에 라이브러리를 다시 현재 작업 프로젝트에 던져 놓으면 된다.
18.이제 실행을 시켜보면  image not found 이 나온다.
18. 속성의 general 항목의ㄹ embedded binaries 항목에 myframework.framework을 추가하면 된다.

 x86_64  관련 에러가 계속 뜨고, 삽질을 계속함..

참고사이트

http://theeye.pe.kr/archives/2254
https://qiita.com/kakipo/items/3cd87e00bc96bc3888b2
https://qiita.com/sachiko-kame/items/be548a7942e6c22a1828

정적라이브러리형태로 배포하기
http://theeye.pe.kr/archives/2750


-추가로 framework 파일에 이미지등을 넣고 싶을때는 이렇게 해본다
1.프로젝트폴더밑에 jpg/testimg.png 를 만들고 넣는다.
2.프로젝트속성 Build Phases에 Copy Files 속성을 추가하고 jpg 폴더를 던져넣는다. 그리고 Destination 은 Frameworks 로 지정한다.
3.프레임워크의 파일내에서 해당 이미지를 사용해본다.

-(UIImage*)image2
{
    NSBundle *b = [NSBundle bundleForClass:[self class]];
    return [UIImage imageNamed:@"Frameworks/jpg/img.png" inBundle:b compatibleWithTraitCollection:nil];

}
4. 빌드한다.
5.사용하고자 하는 프로젝트에서 프레임워크내의 메소드를 호줄해서 UIImageView에 적용해본다.


    [_img setImage:[car image2]];



2019년 10월 12일 토요일

Android NDK 작성법 CMakeLists.txt 사용 -2

1 . Native c++ 프로젝트로 시작하면 CMakeLists, cpp 폴더 등 자동 설정된 채로 프로젝트를 시작할수있다.
2 . CMakelist.txt 의 설명은 여기를 참고 *https://crmn.tistory.com/80
    굳이 CMake 를 배우려면 https://www.tuwlab.com/ece/27234
3 . CMakelists 에 사용할 라이브러리 추가

add_library(
        hello-libs 
        SHARED
        hello-libs.cpp)
4 . Activity 에서는

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
        System.loadLibrary("hello-libs");
    }

    public native String getHello();
5.끝.


Android NDK 작성법 -1

C 소스와 연동하기 위해서는 NDK 연동해야 되는데 걍 귀찮네..

일단
고전적인 방법 

1. 액티비티 클래스에서 먼저 static 으로 만들고자 하는 ndk 모듈을 로딩한다.
JniTwo 라는 이름은 C++ 모듈이름으로 Android.mk 에 [ LOCAL_MODULE := jniTwo ] 라고 나중에 똑같이 적으면 된다.

    static {
        System.loadLibrary("jniTwo");
    }

2. 모듈을 로드했으면 액티비티 클래스에서 쓸 함수를 이름만 정의한다.

 private native String getStr(String str);

3. src->main->jni 폴더를 만든다.
4. 그 안에 cpp 파일을 만든다. * 헤더는 나중에 수동을 만들거다.

//
// Created by kimtaeho on 2019-10-12.
//

#include <string.h>

JNIEXPORT jstring JNICALL Java_com_example_myapplication_MainActivity_getStr(JNIEnv *env, jobject thiz, jstring str) {
    char buf[255];
    char appendMsg[] = " JNI Hello";

    const char *ch1 = env->GetStringUTFChars(str, 0);
    strcpy(buf, ch1);
    strcat(buf, appendMsg);

    return env->NewStringUTF(buf);

 }

5. 액티비티 클래스에서 함수를 사용해본다.

        TextView ttt = (TextView)findViewById(R.id.ttt);
        ttt.setText(getStr("Kim"));

6. Android Studio Setting 에서 Tools->External Tools 에 새로 생성해서 다음과 같이 적는다.

Program : C:\Program Files\Java\jdk1.8.0_191\bin\javah.exe

Arguments : -classpath "$Classpath$" -v -jni $FileClass$

Working Directory : C:\workspace\MyApplication2\app\src\main\jni
7. 이 상태에서 Build->make Project 를 해본다.
8. 모듈을 로드하는 Activity Class 에서 마우스오른쪽 [External Tools] 에서 6에서 생성한 것을 선택하면 복잡한 h 파일이 생성된다. 해당 파일의 맨 밑에 cpp 에서 만든 함수가 정의되어 있는것을 확인하고 파일이름을 적당히 바꾸고 cpp 에서 include 한다.
9. jni 폴더에 Android.mk 를 만들어 모듈이름고 소스 파일이름을 지정한다.


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := jniTwo
LOCAL_SRC_FILES := Two.cpp
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)

10. build.gradle(app) 에 다음과 같이 추가.

import org.apache.tools.ant.taskdefs.condition.Os



// Project Structure에서 설정한 NDK 경로를 읽어 들여 Return합니다.
def getNdkBuildPath() {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())

    def command = properties.getProperty('ndk.dir')
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        command += "\\ndk-build.cmd"
    } else {
        command += "/ndk-build"
    }
    return command
}


Android {

 ...



    sourceSets.main {
        // Compile된 Native Library가 위치하는 경로를 설정합니다.
        jniLibs.srcDir 'src/main/libs'
        // 여기에 JNI Source 경로를 설정하면 Android Studio에서 기본적으로 지원하는 Native
        // Library Build가 이루어집니다. 이 경우에 Android.mk와 Application.mk를
        // 자동으로 생성하기 때문에 편리하지만, 세부 설정이 어렵기 때문에 JNI Source의
        // 경로를 지정하지 않습니다.
        jni.srcDirs = []
    }

    ext {
        // 아직은 Task 내에서 Build Type을 구분할 방법이 없기 때문에 이 Property를
        // 이용해 Native Library를 Debugging 가능하도록 Build할 지 결정합니다.
        nativeDebuggable = true
    }

    // NDK의 ndk-build 명령을 이용하여 Native Library를 Build하기 위한 Task를 정의합니다.
    //noinspection GroovyAssignabilityCheck
    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        if (nativeDebuggable) {
            commandLine getNdkBuildPath(), 'NDK_DEBUG=1', '-C', file('src/main').absolutePath
        } else {
            commandLine getNdkBuildPath(), '-C', file('src/main').absolutePath
        }
    }



    // App의 Java Code를 Compile할 때 buildNative Task를 실행하여 Native Library도 같이
    // Build되도록 설정합니다.
    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn buildNative
    }

    // NDK로 생성된 Native Library와 Object를 삭제하기 위한 Task를 정의합니다.
    //noinspection GroovyAssignabilityCheck
    task cleanNative(type: Exec, description: 'Clean native objs and lib') {
        commandLine getNdkBuildPath(), '-C', file('src/main').absolutePath, 'clean'
    }

    // Gradle의 clean Task를 실행할 떄, cleanNative Task를 실행하도록 설정합니다.
    clean.dependsOn 'cleanNative'



}

11. gradle.properties 에 추가


android.useDeprecatedNdk=true


2019년 10월 11일 금요일

Android Decompile 해서 다시 apk 로 만들어보기

-1 apktool 명령어로 해보기

1.java -jar apktool_2.4.0.jar d 앱이름.apk
2.압출풀린 폴더가 생긴다.
3.Manifest.xml 에 application 태그에  android:debuggable="true"  을 추가함.
4.java -jar apktool_2.4.0.jar b 앱이름폴더
5.임시키를 만듬
"C:\Program Files\Java\jre1.8.0_191\bin\keytool.exe" -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
6.그 키로 jar 싸인
"C:\Program Files\Java\jdk1.8.0_191\bin\jarsigner.exe" -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore com.nttdocomo.android.dpoint_2019-09-24.apk alias_name
7.에뮬레이터에 던져넣기.


-2 java 원본보기
dex2jar
- apk파일이나 apk파일에 포함된 classes.dex파일을 .jar파일로 변환



사용법

1.dex2jar 폴더 안에 apk 파일 넣기
2.해당 폴더에서 명령창 띄어 jar 파일 생성
dex2jar.bat [디컴파일할 apk]:bat 파일에 던져넣어도됨.
3.JD-GUI 에서 보기

https://programist.tistory.com/entry/Apktool%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-apk-%ED%8C%8C%EC%9D%BC-%EB%94%94%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EB%B0%8F-%EB%A6%AC%ED%8C%A8%ED%82%A4%EC%A7%95


-3 bytecode-viewer
https://brunch.co.kr/@c4u/23

2019년 9월 29일 일요일

cocoapods 아이폰 라이브러리관리 프로그램

 gradle 처럼 라이브러리 관리툴이 있었네.
1.sudo gem install cocoapods
2.pod setup 해서 초기설정한후에
3.일단 해당 프로젝트 폴더에서 pod init 하면 pod file 이 생성됨
4.pod 파일을 열고

  # Pods for withpods2
  pod 'Alamofire', '5.0.0-rc.2'

식으로 입력
5.pod install 하면 라이브러리 설치됨
6.하얀 프로젝트 파일을 열어서 작업하면됨

참고 : https://blog.yagom.net/534?category=412990

2019년 9월 28일 토요일

모놀로식 아키텍쳐 vs 마이크로 아키텍쳐

최근 Docker , React 등의 새로운 것들을 보면 컨퍼넌트 라는 개념으로 구성하도록 강제하고 있다.
예전에는 하나의 시스템은 하나의 아키텍쳐 라는 개념이었는데, 최근에는 하나의 시스템은 여러 서비스로 나뉘고 곧 여러 아키텍쳐가 모여서 구성한다는 개념이 유행이다.

아래는 아키텍쳐의 비교이다.

참조 :

https://jins-dev.tistory.com/entry/MicroService%EB%9E%80-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC?category=760149


https://jins-dev.tistory.com/entry/%EC%A0%84%ED%86%B5%EC%9D%98-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EB%AA%A8%EB%8D%B8-%EB%AA%A8%EB%86%80%EB%A6%AC%EC%8B%9DMonolithic-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98?category=760149


2019년 9월 27일 금요일

Smoke Test 란

새로 추가된 기능으로 인해 기존의 핵심기능에 영향을 미치는지 개발팀내부에서 한번 쭉 돌려보는 테스트를 말함.
개발자가 각자 단위 테스트를 끝낸후에  개발팀내에서 QA 팀에 넘기기 전에 미리 간단하게 테스트해봐서 문제가 없는지 검증하는 단계이다.
QA 가 결합테스트를 통해 문제점을 발견하기 전에 개발팀에서 미리 문제점을 인지하고 빠르게 고쳐내서 QA 의 인력과 자원 낭비를 줄일수 있도록 한다.

테스팅이 프로젝트의 90%가 아닐까 생각해본다.

참조 :
https://angel927.tistory.com/77?category=222018


https://translate.google.com/translate?hl=ja&sl=ko&tl=ja&u=https%3A%2F%2Fjins-dev.tistory.com%2Fentry%2F%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8F%84-%EC%95%8C%EC%95%84%EC%95%BC%ED%95%A0-%EB%AA%87%EA%B0%80%EC%A7%80-SW-%ED%85%8C%EC%8A%A4%ED%8C%85%EC%9D%98-%EC%A2%85%EB%A5%98&anno=2


 http://blog.naver.com/PostView.nhn?blogId=wisestone2007&logNo=220868861867&parentCategoryNo=&categoryNo=39&viewDate=&isShowPopularPosts=true&from=search

2019년 9월 3일 화요일

Android Enterprise Experience 안드로이드 엔터프라이즈 모드를 간단하게 경험해보게 해준다

일단 자세한 설명은 https://qiita.com/garupon/items/844770b1eb48ac004ced 여기서 참고.

최근 안드로이드에 기업용 솔류션이 따로 있었다는것을 알게되었다.
지금까지는 안드로이드는 그냥 사용자들이 사용하는거고, 원격제어 솔류션들은 자체적으로 뭔가 해서 모바일 기기를 원격제어(?)를 한다고 막연하게만 생각하고 있었는데, 구글에서는 예전부터 안드로이드를 제한된 리소스를 통해 특정 기업,단체 등이 보안에 신경쓰면서 사용할수 있도록 기능을 제공해주고있었다.

모바일 장치 제어 솔류션은 MDM (https://www.otsuka-shokai.co.jp/words/mdm.html)이라는 것으로  주로 원격에서 사용자 모바일 장비를 제어하기 위해서 제공하는 솔류션을 말한다.

구글에서는 MDM기능을  AE(Android Enterprice) 라는 이름으로 제공하는데 정식명칭은 EMM(Enterprise Mobility Management)라고 한다. EMM 의 기능자체는 누구나 이용할수있지만,  EMM솔류션을 이용하여 좀더 큰 서비스를 제공하는 추천업체들을 심사하여 AER(Android Enterprise Recommended)이라고 해서 구글 엔터프라이즈 홈페이지에 대빵 만하게 홍보해주고 있다.


AE를 이용 했을때 기업에서 뭐가 좋냐고 하면

  • 기기의 초기화, 설치시에 업무용 앱 자동설치 등을 한방에 할수있다.
  • 기기의 분실, 외부침입자의 조작에 대해 원격에서 초기화,리셋 할 수 있다.
  • 안드로이드의 모든 기능을 원격으로 제어할수 있다. (화면 녹화등은 불가)
그렇다. 영업사원, 단기사원등에게 업무용 폰을 지급할때 사용하는 거다.

관리자 로서의 가장 좋은점은 다수의 기기를 초기화 할때, 관리자가 일일이 안해줘도(또는 일일이 한다고 해도) 빠르고 간편하게 초기화하고 업무앱을 자동으로 설치해서 새로운 직원에게 건네줄수 있다는 점이 되겠다.

AE에서는 사용자의 모바일장비를 어떻게 제어할건지에 대해 4가지 방식을 제공한다.
  • Work Profile(BYOD) : 모바일장비는 개인것을 쓰되, 업무용앱과 개인용앱을 별도로 구분지어 이용할수있게한다. 예를 들어 같은 메일앱도 업무용아이콘이 붙은 것은 회사용도로, 그렇지 않은 것은 개인용도로 쓰인다. 이 모드에서는 관리자가 원격으로 개인의 모바일 장비에 대한 제어(원격 초기화, 화면락등) 이 불가능하다.  소프트웨어 적인 제어만 가능하다고 생각하면된다.
  • Fully managed Device : 모바일 장비의 하드웨어,소프트웨어 모든 기능을 관리할수 있도록 한다. Device Owner Mode 라고 하는데,  일반앱에서 할수없는 장비제어,관리등의  API등을 이용할수 있다.  주로 기업에서 장비를 원격으로 제어하기 위해서 직원에게 이 모드로 지정된 모바일장비와 관리자가 제어가능한 기업의 앱을 장비에 설치해서 언제든지 원격에서도 장비를 제어 할수 있도록 하는 용도로 쓰인다. (예를 들어 분실시에 장비초기화, 계정삭제, 화면 락 등 제어를 원격으로 가능하다.)
    물론 안드로이드는 Device Owner Mode와  관련 API만 제공할뿐 서버측 원격제어프로그램과 장비에 들어갈 클라이언트용 앱은 기업에서 만들어야 한다. 
  • Fully managed device with work profile
    COPE 라고도 하며 장비자체는 기업의 관리하에 두지만, 개인적으로 사용하고 싶은 영억을 구분해서 사용할수도 있도록 하는 모드이다. 영업사원이 회사의 폰을 장기적으로 사용하고 할때, 본인만이 필요한 업무용 앱또는 사용을 하고자 할때 이 모드를 적용하면 좋다.
  • Dedicate device
    POS 등과 같은 COSU(하나의 앱만 실행가능한 모드) 라고 생각하면된다.  Device Owrner Mode 의 API를 사용해서, 사용자가 장비의 이것저것 조작하다가 다른 앱이 뜨거나, 안드로이드 바탕화면으로 돌아거거나 하는 것을 막을 수 있다.
잘은 모르겠지만 이렇단다. 즉 3개는 장비까지 제어할수있고,  1개는 그냥 업무용과 개인용분리만 한거란다.

AE 솔류션은 Android 5 이상이면서 구글 개발자 서비스라는 앱이 설치되어있어야한다.

AE 사용방법

모바일 장비를 AE 하기위한 방법에는  G-suite 계정,  NFC, QR코드, Zero-Touch, DPC-indentifier , AER 업체를 통한 방법 등이 있다.
Work Profile만 할때는  주로 G-suite 계정방법만 사용하고, Device Owner Mode로서 장비 전체를 제어 하고자 할때는 G-suite 계정(초기화시에 계정입력),NFC, QR코드,Zero-Touch, DPC-identifier 방법을 사용한다.

 각각의 방법은 안드로이드 OS 지원에 따라 가능한것과 불가능한것이있따.
  • G Suite 계정
    G suite 를 이용하고 있는 기업에서 사용자의 Gsuite 계정을 설정해서 로그인하면 Work Profile이 된다. 만일  단말의 초기화 시에 Gsuite 계정을 기기의 계정으로 입력하면 Device Owner Mode로 된다.
  • NFC
    NFC가 지원되는 단말에서 NFC접촉을 통해 단말을 초기화 하고 전용앱을 설정한다. Device Owner Mode가 된다.
  • QR코드
    안드로이드 7 부터는 장비초기화 화면의 웰컴이미지 를 6번 연속터치하면 QR코드를 읽는 카메라화면이 나오며 이때 초기화 내용이 들어간  QR코드를 읽으면 초기화가 ㄷ진행되면서 Device Owner Mode가 된다.
  • Zero-Touch
    구글과 계약되어 있는 AER에 한해서 제공되는 것으로 구글서버에서 장비의 정보를 넣어두면 자동으로 단말이 초기화 설정이 되는 것이다. Android 8 부터 제공한다.
  • DPC-identifier
    AER 업체마다 각업체의 솔류션을 이용하기 위해서 장비의 초기화시에 구글 계정입력화면에서 각 업체의 전용태그 ( afw#demo, afe#samsung 등) 과 같이 입력하면 해당기업의 관리하에 있는 장비로 초기화가 진행된다. 특정기업이나 단체를 위해 구글에서 승인받은 업체만 사용가능하다.
  • AER 업체의 agent
    EMM 솔류션을 제공하는 업체의 앱을 구글에서 검색해서 설치하면 Work Profile에 적용된다.
읽어도 뭔소리인지 모르는 나 같은 사람들을 위해 구글에서는 간단하게 놀아볼수 있는 사이트를 제공한다.

Android Enterprise Experience 


이 사이트에서는 Enterprise 가 최소한 뭐를 할수 있는지 알게해준다.  구글이 만든 심플한 관리도구화면에서 업무용앱을 지정하거나 화면캡춰제한, 스크린락제한 등을 걸어볼수 있고,  같은 설정을 여러개의 장비에서 똑같이 초기화 되는 상황을 재현해볼수있다.
또한 비공개 앱, 웹앱을 추가 지정할수 있어서 회사내부에서만 사용하는 앱을 사용자장비에 설치해볼수도있다.

단 DPC-identifier(  afw#demo ) 로만 가능하다. 

순서대로 나열해 보면
일단 AEE 화면

이렇게 새로운 계정(또는 기존계정에 연결) 해서 초기화 안내화면 까지 간다.

그리고 모바일장비에서 








 AEE화면에서 slack등을 추가해서 초기화가 끝난 모바일장비에서 slack을 설치할수 있도록 한다.





모바일 장비에서 이제 슬랙을 다운로드 하고 설치할수 있다. AE 모드에서는 구글스토어에 들어가도 관리자가 지정한 앱에서만 다운로드가 가능하다. 또한 사용자 프로필도 전혀 다른 모양이다.



사실, 본격EMM모드에서는 Device Owner 로서 모바일장비의 전체적인 부분을 관리할수 있다.
또한 DPC 라이브러리를 직접 앱에 포함시켜서 별도의 Google Device Policy 앱을 다운로드 하는 절차를 생략할수도 있다.