Naver Tech Concert Day-1

05. Material Design의 철학과 적용 사례

머티리얼 디자인의 등장

기존 구글에서는 모바일도 웹도 디자인에 그리 신경쓰는 곳은 아니었음.

2011년부터는 홀로테마로 구글 디자인이 개선됨.

사용자에게는 플랫폼과 무관하게 동일하게 기능을 요구하지만 플랫폼 별로 다른 부분은 부담이 됨.

그래서 다양한 플랫폼을 아우르는 일관된 디자인이 필요하게 됨.

현대적이고 개발자가 이해하기 쉬워야 함.

  • 아날로그 고유 속성에 중점
    • 물리적 속성
    • 형태 변환
    • 움직임
    • 높이, 음영, 객체 간 계층 구조
  • 주요 특성
    • 입체적 표면
    • 의미있는 모션
    • 인쇄물 같은

머티리얼 디자인이 2013, 2014년에 소개되고, 디자인 서포트 라이브러리가 2015년부터 지원됨.

머티리얼 디자인의 아쉬운 점

  • 부족한 엔지니어링 리소스
    • 라이브러리 한계 (네비게이션 드로우, 플로팅 액션 버튼 등)
    • 디자인과 개발 프로세스 간 연결이 자연스럽지 않음
  • 비주얼 표현의 제약
    • 앱들 간의 차이를 나타내는데 제약
    • 모바일(안드로이드)를 위한 디자인으로 간주됨

새로운 머티리얼 디자인

추가된 주요 특성

  • 유연한 기반
  • 크로스 플랫폼

머티리얼 파운데이션

머티리얼 디자인 기반으로 좋은 디자인을 제안하며 생각보다 유연함.

기존에는 높이와 그림자에서 상관관계가 까다로웠으나,

머티리얼 파운데이션에서는 계층을 표현하기 위한 높이와 그림자 쓸 뿐이며, 그림자 색대비 등을 사용자가 표현할 수 있음.

하지만 색대비나 외곽선, 그림자 등을 통해서 서피스를 구분할 수는 있어야 함.

구글에서는 머티리얼 파운데이션을 활용한 프로토 앱을 사례로 만들었음.

예로 Basil 이라는 앱에서 예로 TAB의 변경을 확인할 수 있음.

역시 네비게이션 드로우도 재해석하여 완전히 변형해서 사용할 수 있음.

머티리얼 디자인 가이드 라인

Material Theming

훨씬 많은 자유도와 독창적인 심벌을 지원하기 위해 나옴.

  • 컬러테마 : 컬러 선택시 레이어 등에 색상, 농도 등을 추천함.
  • Typography : 기존 Roboto만 지원했으나, 다른 폰트 특히 한글 폰트도 크기에 맞춰서 나옴.
  • Iconography : 5가지의 타입으로 아이콘 지원.
  • Motion : 애니메이션 등이 지원됨.

Tools

  • Theme Editor : 디자인 작업이 이루어지는 곳, 스케치에 플러그인으로 들어가 있음.
  • Gallery : 디자인 결과물을 볼 수 있는 곳

Components

기존 한국의 쇼핑 앱의 경우 머티리얼이 온전히 지원 못하였으나 이제 지원 가능함.

  • Bottom App Bar
  • Banner
  • Extended FAB (기존 FAB에 텍스트가 들어간 엄청 큰 FAB로 보면 됨)
  • Chips
  • Image Lists
  • Text Fields 2가지 제공
  • Backdrop (Front 레이어와 Back 레이어로 나뉘어 구현.)

안드로이드에서 Material Design Components 사용하기

material compnents Android 깃허브 레파지토리에서 확인 가능.

https://github.com/material-components/material-components-android

완전한 오픈 소스는 아니고 구글 내부에서 어느정도 개발 완료되면 푸시 됨.

Dependencies

dependencies {
    implementation 'com.google.android.material:material:1.0.0'
    // Other dependencies
}
...
// androidx 사용 전이라면 support 28버전 이상 사용
dependencies {
    implementation 'com.google.android.support:design:28.0.0'
    implementation 'com.google.android.support:support-v4:28.0.0'
    // Other dependencies
}

직접 Material components 빌드하여 사용하기(포함된 샘플 앱은 빌드 안됨;)

git clone https://github.com/material-components/material-components-android.git

./gradlew uploadArchives -PmavenRepoUrl="file://localhost/<path_to_aars>"

즉 커스텀이 가능함.

커스텀 뷰, 커스텀 스타일, 헬퍼 등으로 구성됨.

Material Button의 예

<!-- 일반 버튼 -->
<Button
        android:id="@+id/material_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/cat_button_label_enabled" />
<!-- 아이콘 버튼 -->
<Button
        android:id="@+id/material_icon_button"
        style="@style/Widget.MaterialComponents.Button.Icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/cat_button_label_enabled"
        app:icon="@drawable/ic_dialogs_24px" />

결론

Material Design이 빡빡한 컨셉에서 유연하고 유저 커스텀이 가능해졌음.

'IT > 행사' 카테고리의 다른 글

[행사] Naver Tech Concert Day-1 06  (0) 2019.01.07
[행사] Naver Tech Concert Day-1 05  (0) 2019.01.07
[행사] Naver Tech Concert Day-1 03  (0) 2019.01.04
[행사] Naver Tech Concert Day-1 02  (0) 2019.01.04
[행사] Naver Tech Concert Day-1 01  (0) 2019.01.04

Naver Tech Concert Day-1

04. 디자인 1도 모르는 개발자, UX디자인 시작하기

  • 발표자 : 최유리 (N Tech Service / NTS UX디자인실 설계&콘텐츠운영디자인)
  • 동영상 : https://tv.naver.com/v/4412357/list/272653
  • 슬라이드 : https://www.slideshare.net/NaverEngineering/13-1-ux-ux-121402323
  • 세션설명 : 통계에 따르면 2018년 1분기에는 앱스토어에 약 220만개, 구글플레이에 약 380만개의 앱이 등록되어 있다. 이 치열한 경쟁속에서 사용자에게 오래도록 사랑받는 앱이 되려면 UX디자인은 선택이 아닌 필수다. UX디자인은 디자이너만의 영역이 아닌 개발팀 모두가 함께 만들어내야하는 가치이다. UX디자인에 관심을 갖고 참여한 개발자가 서비스 성공에 어떤 역할을 해 내는지 알아보자.

잘 나가는 앱을 만들고 싶다면? UX 디자인에 참여 필요.

사용자에게 중요한 건? 내 삶에 어떤 가치를 주는 가.

사용자에겐 서비스에 들어간 기술과 시간과 노력엔 관심이 없음.

UX 디자인은 일종의 프레임워크라 할 수 있음.

Focused on product

Focused on user

디자인적 사고는 문제를 발견해 해결 방법을 제시하는 것.

모두는 디자이너라 할 수 있음.

Lean UX Cycle

PLAN -> think -> make -> check -> think -> make

Lean UX 경험내용 1

UX 디자인 분석 단계를 개발팀과 함께 진행.

Key Feature 워크샵.

결과 : 기능의 목적과 목표를 이해하고 구현 가능한 스펙을 정의하여 품질 완성도가 올라감.

Lean UX 경험내용 2

UX 디자인 워크샵.

서비스 목표와 전략 수립. 핵심 기능 도출.

결과 : 사용자 가치 중심으로 스펙 변경, 플랫폼 전체를 바라보는 시각 형성.

UX Design을 개발자와 함께 함으로 목표와 가치 도출하고 사용성 테스트를 통해 문제점 발견이 용이함.

그 결과로는 기술 중심에서 사용자 중심으로 사용자에게 의미 있을만한 것을 제공하기 위해 집중함.

UX 디자인 함께 하면 좋은 점

  • 공동의 목표 세워, 자발적이고 주체적인 의사결정 가능
  • 시간과 비용 중심이 아닌 사용자 가치 중심의 스펙 정의가 가능
  • 밀접한 협업 가능
  • 신속한 결과 도출 및 검증 가능
  • 낭비를 줄이고, 위험요소 미리 감지 가능
  • 서비스 질이 좋아짐

UI와 UX 디자인

User Interface

  • Technical
  • 어떻게 작동하는가? 어떻게 보이는가?
  • 사용편의성, 일관성, 심미성

User eXperience

  • Emotional
  • 어떻게 느끼는가?
  • 사용자 가치, 사용자 환경(Context), 만족도, 재접근

Experience

  • 오가닉 경험(Organic Experience) : 즉흥의, 즉석의 등 의도가 없는 순수한 경험
  • 설계된 경험(Designed Experience) : 사용자가 고려되고 계획던 경험. 사용자가 경험했으면 하는 감정을 정의.

사용성보다 사용자 가치가 더 우선적

효율적인 UX 디자인 프로세스 = Lean UX + Agile UX

애자일 UX 방식은 초기 비용이 높으나 후반으로 갈 수로 낮고 상대적으로 워터폴은 비용 뿐만이 아니라 리스크도 높아짐.

Lean UX Cycle은 경험과 측정을 근거로 현상의 원리를 밝히는 과정

가설을 세우고, 분석하고, 설계하고, 그것을 테스트한 후 실행에 옮김.

PLAN : 공동의 비전과 목표

  1. 프로젝트의 목표는?
  2. 내가 이 프로젝트를 통해 얻고자 하는 것은?
  3. 우리의 주요 고객은 누구인가?
  4. 프로젝트 진행에 걸림돌이 되는 것은? 위험요소는?
  5. 서비스의 성공적인 완성은 무엇으로 판단할 것인가?

THINK : 사용자를 이해하고 니즈를 구체화

Pain vs Gain

MAKE : 사용자 경험 전략과 가치를 정의

Elevator Pitch

  • 제품 고유의 특징
  • 사용자 가치
  • 핵심 기능

Kano Analysis

CHECK : 핵심 기능의 실현 가능성을 평가

NUF(New/Useful/Feasible) Test

Usability Test

'IT > 행사' 카테고리의 다른 글

[행사] Naver Tech Concert Day-1 05  (0) 2019.01.07
[행사] Naver Tech Concert Day-1 04  (0) 2019.01.04
[행사] Naver Tech Concert Day-1 02  (0) 2019.01.04
[행사] Naver Tech Concert Day-1 01  (0) 2019.01.04
[행사] 앱쇼코리아 2018 참석기  (0) 2018.12.21

Naver Tech Concert Day-1

03. MVVM with Grab Architecture

  • 발표자 : 정승욱 (Grab / 안드로이드 개발)
  • 동영상 : https://tv.naver.com/v/4637223
  • 슬라이드 : https://www.slideshare.net/NaverEngineering/12mvvm-grab-architecture-mvvm
  • 세션설명 : 구글이 Android Architecture Component 의 ViewModel 을 발표하면서 다양한 시각의 MVVM 구현이 제시되고 있습니다. 여전히 많은 사람들이 혼동하는 MVVM 구현에 대해 올바른 안드로이드 MVVM 구현을 공유하고자 합니다. 이를 위해 안드로이드에서 어떠한 기본 작업이 선행되어야 하는지, 다양한 문제 상황에 대한 해결책에 대해 알아보고 MVVM 이 Grab 에서 어떻게 활용되고 있는지 알아보겠습니다.

국내 MVVM 이해도 오류가 많음. (국내 포스팅 등...)

예로 아래의 경우 뷰에서 옵저빙을 하는 부분이 문제임.

class MainViewModel {
    val title LiveData<String>
}
...
class MainActivity {
    val viewModel: ViewModel
    val textView: TextView
    fun onCreated() {
        viewModel.title.observe(this) {
            textView.text =it
        }
    }
}

Android Architecture Component의 ViewModel

AAC의 ViewModel은 MVVM의 ViewModel과는 무관함.

AAC의 ViewModel은 Activity와 Fragment의 Life Cycle 의존성을 낮추는 것.

LiveData는 Repository로부터 데이터 변화 반응/적용이 목적이며 ViewModel은 LiveData로부터 View에 필요한 데이터를 관리함.

MVVM의 ViewModel

View와 ViewModel 연결 최소화

ViewModel은 데이터의 변화를 View에 전달

View는 화면 정보의 변화를 ViewModel에 전달

위에서 잘못된 코드는 아래와 같이 변경되어야 함.

class MainActivity {
    val viewModel: ViewModel    
    fun onCreated() {
        dataBinding.setVariable(BR.vm, viewModel)
    }
}

안드로이드에서 DataBinding 사용에 문제 사항들

  1. LifeCycle
  2. Databinding으로 다 표현하기 힘든 View 이벤트
  3. Resource 등 Context를 접근해야 하는 경우

LifeCycle

그랩에서는 LifeCycle 문제를 위해 RxBinder를 만들어 사용함. (Trello의 RxBinder 참조)

class ViewModel(val rxbinder: RxBinder) {
    init {
        rxbinder.bind(ON_DESTROYED) {
            Observable....
        }
    }
}
...
class RxBinder {
    val map: Map<Event, CompositDiposable>
    fun apply(lifeEvent: Event) {
        map[lifeEvent]?.clear()
    }
    fun bind(lifeEvent: Event, body:()->Disposable) {
        map[lifeEvent].add(body())
    }
}
...
open class RxActivity{
    val rxbinder: RxBinder
    fun onCreated() {
        rxbinder.apply(ON_CREATED)
    }
}

View 변화 감지

GlobalLayoutChangeListener 등은 데이터 바인딩으로 구현이 어려움.

위의 경우 2-way 바인딩 구현해야 하며 3개의 function을 구현해야 하며 이해가 어려움.

이를 위해 2-way 바인딩 구현보다는 usecase를 만들어 회피 사용함.

class GetVisibleAreaUsecase(view1) {
    fun observe(): Observable<Rect> {
        return Observable.create {e->
                                  e.onNext(view1.height)
                                  view1.addGlobalLayoutChange{
                                      e.onNext(view1.height)
                                  }
		}.distictUntilChanged()
    }
}
...
class ViewModel(usecase:GetVisibleAreaUsecase) {
    init{
        usecase.observe().subscribe{
            /* do something */
        }.bindUntil(rxbinder)
    }
}

Resource 접근

ResouceProvider 라는 랩핑을 만들어 context를 전달해 사용

class ResourceProvider(context: Context) {
    fun string(resId: String) = context.resource.getSting(resId)
}

ActivityResult는 매니저를 만들어 Activity에서 메소드 실행시 ViewModel에서 구독됨.

class Activity {
    val resultManager
    fun onActivityResult() {
        resultManager.onResult()
    }
}
...
class ResultManager{
    fun listen(observer)
    fun onResult()
}
...
class ViewModel(resultManager) {
    init{
        resultManager.listen {
            // do something
        }
    }
}

위의 모든 것이 구현된다면 대략...

class ViewModel(rxbinder, usercase, resultManager) {
    init{
        // many things are here
    }
}
...
class Activity: ResultableRxActivity {
    fun onCreated() {
        dataBinding.setVariable(BR.vm, viewModel)
    }
}

실제 액티비티의 역할은 아래 정도?

액티비티에서 DataBinding과 DI만?

class MainActivity: RxResultableActivity{
    @Inject lateinit var vm: MainViewModel
    fun onCreated() {
        dataBinding.setVariable(BR.vm, vm)
    }
}

그랩에서는 단일 Layout을 조각내기로 함.

한 레이아웃을 뷰를 나눠 각각을 노드화하여 처리.

각 뷰 별로 바인딩 노드가 되고, 각 노드에 ViewModel이 인젝션됨.

바인딩 노드는 부모뷰와 ViewModel을 받음.

1. Activity

class ConfirmActivity{
    fun onCreated() {
        BackButtonNode({parentView}).dependency(root).build()
        TaxiTypeNode({parentView}).dependency(root).build()
        ExtraInfoNode({parentView}).dependency(root).build()
        PayConfirmNode({parentView}).dependency(root).build()
        //...etc...
    }
}

2. 5번 TaxiTypeNode

class TaxiTypeNode(parentView:()->ViewGroup): BindingNode{
    @Inject lateinit var vm: ViewModel
    fun build() {
        depdency.inject(this)
        binding(parenteView(), vm)
    }
}

3. BindingNode

open class BindingNode {
    fun binding(parentView: ViewGroup, vm: ViewModel) {
        val binding = ViewBinding.inflate(vm.layoutId, parentView)
        binding.setVariable(BR.vm, vm)
    }
}

4. Root Parent XML

<FrameLayout>
    <FrameLayout android:id="@+id/parent1" />
	<FrameLayout android:id="@+id/parent2" />
</FrameLayout>

노드화의 장단점

  • 장점 : Node 제어로 View 플러그인화 가능
  • 단점 : BackKey, Save/Restore Instance 등 다양한 처리 구현

위 구조는 작은 사이즈에서 중간 규모의 앱에서는 과도하며, 인터랙션이 많거나 View 자유도, 재활용이 높은 앱에 권장함.

정리

View는 XML

DataBinding 필수요소

감지하기 어려운 뷰 변화는 ViewUsecase

LifeCycle, Result 위한 처리 필요

Resource 접근은 Wrapper 처리

Node 예제는 Optional

Q&A

Q : 그랩에서는 AAC 사용 안하는지?

데이터 용도로 맞지 않고 라이프사이클 처리도 직접 함으로 Room, LiveData, AAC의 ViewModel 등은 사용 안함.

Q : 노드 사용 사례는?

루트 노드에서 라우터가 하위 노드를 컨트롤하며, 하위 노드를 구성하도록 지시함.

Q : 이재원님(MS Expert)의 안드로이드의 MVVM 오류에 대한 내용이 반영되었는지?

반영된 내용임.

Q : RxBinding이 그랩에서 자체적으로 만든건지?

외부(Trello)에서 아이디어만 가져오고 자체 구현함.

Q : Activity에서 ViewModel을 직접 참조할 일이 없다는데? Activity에서 반응에 대한 부분을 ViewModel에 전할때는?

데이터 바인딩으로 처리됨.

Q : 노드의 상대적인 위치는 어떻게 지정?

루트노드에서 Parent 대비 상대적인 위치가 지정되어 있음.

Q : 전통적인 Activity와의 차이는?

레이아웃 부분이 static으로 지정되어 있지만, 노드에서는 노드 단위로 다른 화면에서도 재활용이 가능함.

Q : 빈 레이아웃에 attach/dettach 하는 방식이 Fragment와 비슷한데?

그랩에서는 Fragment를 사용안함. onRestore 시 등 재생성 충돌등의 문제가 있어 별도로 노드 처리함.

Q : 기본 선수 지식은?

DataBinding(2-way까지), MVP에 대한 깊은 경험, MVP에서 MVVM으로 변화에 대한 이해 필요.

Q : ViweModel에서 Resource ID를 가지는 이유는?

ViewModel에서 어떤 리소스와 매칭되는지 판단을 했지만, 편의상 Node보다 ViewModel에서 가지고 있음.

Q : 2-way 바인딩 사용 사례는?

2-way 바인딩이 한번 이상 재사용시에는 2-way 바인딩을 빼서 사용을 권고함.

Q : DataBinding이 MVVM에 필수인데 Anko의 경우는?

Anko같은 경우는 네이티브 코드이고 Anko로 작성한다 해도 중간에 추상화 코드가 나오는 게 아니라 현재 구현된 상태가 최선인 듯. 현재로썬 Anko와는 궁합이 좋지 않음.

Q : AlertDialog는 어떻게 처리?

AlertDialog도 노드로 처리

Q : 싱글 액티비티에서 히스토리 관리는?

상위 노드에서 관리하며, 히스토리 관리하는 모듈이 있음.

Q : 그랩은 모두 싱글액티비티임?

메인 플로우들은 싱글 액티비티이나 페이먼트, 리워드 등은 아님. 그래서 onResult 처리가 필요했음.

Q : Trello RxLifeCycle에서 추가된 기능은?

자체적으로 필요한 부분만 추가되고 Trello에서는 필요한 것만 빼서 씀

Q : MS 제안한 MVVM 의도대로 분업이 되었는지? (XML은 디자이너, ViewModel은 엔지니어)

그랩에선 디자이너는 UX/비주얼(7:3정도) 디자이너로 나뉘며, xml이나 ViewModel 모두 엔지니어가 작업

Q : Save Instance 상태는 어떻게 관리하는지?

노드별로 저장해서 상위 노드에 전달하고 복원 시작시 하위 노드에 다시 전달함. 복잡한 부분이라 라이브러리화해서 사용 중.


+ Recent posts