원티드 안드로이드앱을 처음 접하게 되면 홈 화면(=메인화면)에 수많은 회사들과 그 회사들의 채용 정보를 볼 수 있습니다. 하지만 우리가 고민한 것은 다양한 채용정보도 있지만 우리가 제공하고자 하는 가치가 무엇이고, 어떻게 하면 사용자에게 좀 더 효과적으로 전달할 수 있을까에 대한 고민이 있었습니다. 앱 실행시 우리 서비스가 어떤 가치를 제공하고 그것을 통해 사용자들이 무엇을 얻을 수 있는지에 대하여 쉽게 전달하는것을 목표로 이 과제를 시작하였습니다.

Walkthrough

Walkthrough 디자인에 대한 명확한 정의를 설명하기 어렵습니다. 사용자에게 서비스를 쉽게 풀어서 설명하는 방법이라는 목적 아래에 그것을 UX/UI적으로 제공하는 형태가 특졍 형태를 지칭하지 않기 때문입니다. 초기 화면 진입 후 사용자의 스텝을 유도하여 간접적으로 사용 방법을 숙지시키는 dynamic walkthrough형태도 있고, 서비스가 제공하고자 하는 가치를 좌/우 (혹은 상/하)로 넘기면서 확인할 수 있는 static walkthrough형태, 실제 서비스를 이용하는 중간중간에 어떤 선택(혹은 제스쳐)을 하면 알리고자 하는 기능을 사용할 수 있다고 안내해주는 coach mark 형태 등도 Walkthrough의 형태로 분류하고 있습니다.

원티드앱 실행 화면 매칭모드 기능 안내 화면
Static walkthrough Coach mark

처음 Walkthrough 에 대한 아이디어를 논의할 때 의사소통을 위한 용어의 정리가 필요했습니다. Walkthrough 외에 Onboarding 기타(Intro, Splash, Guide 등)도 등장!!등의 용어가 혼재되어 커뮤니케이션 이슈가 있었고, 내부적으로는 워크스루라는 용어를 사용하는 것으로 정리 하였습니다.

이번에 작업한 부분은 앱 실행 시 서비스에 대한 안내를 해주는 static walkthrough형태에 대한 작업을 정리해보고자 합니다.

요구사항

워크스루 기능을 개발하는데 있어서 요구되는 요구사항은 아래와 같았습니다. 해당 요구사항들은 모두 개발적인 관점에서 고려해야 하는 항목들이며, 각 요소들을 실제 어떻게 처리하였는지 간략히 정리해 보았습니다.

A/B 테스트를 할 수 있어야 한다.
이메일 입력이 좀 더 편해져야 한다.
안내 페이지 하단 indicator 효과 처리

A/B 테스트를 할 수 있어야 한다.

A/B테스팅 환경을 구축하기 위하여 Firebase 원격구성을 사용하였습니다. 예제 코드가 거의 전부여서 특별히 추가 처리도 한 부분이 없이 손쉽게 A/B테스팅 환경을 구축 하였습니다. Firebase 원격구성 속성정보를 읽어오는 로직은 앱 실행 시 초기 서버에서 읽어올 때 확실하게 해두어야 할 필요가 있어, 어쩔수 없이 초기 진입화면에 로딩 UI가 추가되었습니다.

다만 몇 가지 주의사항이 있습니다. 먼저, RemoteConfig fetching 코드를 보면 아래와 같습니다.

public void fetchFirebaseRemoteConfig() {
        long cacheExpiration = FETCH_CACHE_ExPIRATION; // 1 hour in seconds
        // If developer mode is enabled reduce cacheExpiration to 0 so that
        // each fetch goes to the server. This should not be used in release
        // builds.
        if (mRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
            cacheExpiration = 0;
        }
        mRemoteConfig.fetch(cacheExpiration)
                .addOnSuccessListener(aVoid -> {
                    mRemoteConfig.activateFetched();
                })
                .addOnFailureListener((e) -> {
                    e.printStackTrace();
                });
    }

만약 디바이스에 설치된 Google Play Service 가 11.0.4 버전을 실행하지 못할 경우에는 fetching 시 등록한 OnSuccess, OnFailure Callback 모두 불려지지 않는 현상이 발생됩니다. 해당 현상을 막기 위하여 어쨌거나 callback이 오는데까지 일정 시간 대기하고 성공 / 실패의 응답이 다 없을 경우 실패로 간주하고 처리하는 로직이 추가가 필요합니다. fetch 로직을 실행하고 응답이 없는 경우를 추가적으로 Timer / TimerTask 를 이용하여 회피하였습니다.

그리고 Firebase 원격구성 속성을 테스트 하는데 있어 FirebaseRemoteConfigFetchThrottledException 이 발생할 경우가 생길 수 있는데(개발 진행간 한번 정도 발생했었습니다.) 이 경우 원격 구성 정보를 변경해도 클라이언트에서 정상적으로 갱신이 되지않는 현상이 발생되어 작업에 흐름이 끊어졌습니다. 차한잔의 여유. 해당 에러는 일정 시간이 지나면 다시 정상적으로 동작하게 되니 크게 걱정할 필요는 없습니다.

이메일 입력이 좀 더 편해져야 한다.

이메일 주소 형식의 경우 사용자가 서비스 사용을 위하여 입력해야 할 행동을 너무 많게 만드는 큰 요인이었습니다. 기존에 제공하던 이메일 로그인 방식에 입력이 불편함을 인지하고 있었고, 그것을 어떻게 효율적으로 처리할 지에 대하여 고민하였습니다.

사용자 입장에서 단말에 등록된 계정을 얻어와서 표시해주는 기능을 생각하였는데 이 경우 GET_ACCOUNTS 퍼미션이 불가피하게 추가가 필요하게 됩니다. 이럴 경우 권한 요청 패턴 UI 가 추가적으로 들어가야 되므로 오히려 사용자에게 UI 가 복잡해 질 수 있다고 생각했습니다. 앱에서 추가 권한 사용 등록 없이 사용자 이메일 주소를 얻어올 수있는 방법에 대하여 연구하여 2가지 방법을 찾았습니다.

AccountPicker 사용
Google Credential 사용

AccountPicker 의 경우 계정 등록 기능이 제공되어 더 단순한 UI를 제공할 수 있는 사실 안이뻐서 Credential API를 이용하여 이메일 선택 Dialog를 제공할 수 있도록 작업하였습니다. 예제 소소를 참조하면 이메일만 얻어오는 부분은 충분히 사용할 수 있습니다.

몇 가지 유의사항이 있는데, GoogleApiClientGoogleAPI사용을 위한 객체를 생성할 시 ConnectionCallback을 등록하게 되는데, Activity Lifecycle상 onResume 타이밍에 onConnected 콜백이 다시 호출됩니다. 따라서, 사용자 액션에 대한 동작코드를 직접 처리하는 로직은 해당 코드 안에 넣는 것이 정신건강에 이롭습니다.

또 한가지는, CredentialRequest 를 이용하여 인증 처리 로직의 응답 결과는 CredentialResponseResult로 전달받는데 정상 여부를 판단하는 State선택 가능한 이메일 리스트가 없어서 발생하는 에러 상태 값은 정의되어 있지 않습니다. (Error message는 있는데…) 이런 이유로 Result State가 정상이 아니면서 Resolution이 없다면 모두 처리 실패 Toast를 추가하였습니다.

안내 페이지 하단 indicator 효과

디자이너의 페이지의 하단 인디케이터 표시 요구사항은 명확했습니다.

Opera VPN’ 앱과 동일한 인디케이터 표시

Android ViewPager를 이용하여 swipe를 감지하여 그 offset 만큼 indicator 를 그려야 했고, 몇 가지 라이브러리를 검토하다가 SpringIndicator 의 구조를 참조하여 구현하였습니다.

IndicatorView는 FrameLayout을 상속받아서 구현되어 있고, 해당 뷰 내부에 동작방식은 크게 2개의 자식 뷰로 구성되어 있습니다.

페이지 수 만큼 Indicator dot 을 나타내는 뷰 그룹 (LinearLayout)
Pager Scrolling 이벤트에 맞춰서 dot을 표시하는 뷰

라이브러리에서는 Pager의 Swipe이벤트로 Offset이 변경될 때, dot을 표시하는 뷰는 각 페이지의 뷰를 나타내는 뷰 그룹의 자식 뷰 위치정보를 이용하여 사용자 행동에 반응하는 인디케이터의 위치를 계산하고 최종적으로 View의 onDraw시점에 Canvas에 직접 그리는 구조로 동작하고 있습니다. Spring형태처럼 페이지가 이동되는 효과를 표현하기 위하여 그려야 할 점을 두개로 설정하고 그 각 점을 그리고 점과 점 사이를 path를 그리는 형식으로 구현 되어있습니다. 이를 응용하여 offset을 활용하여 각 페이지의 dot의 위치정보를 이용해서 onDraw 시점에 Canvas 를 이용해서 직접 그리는 작업을 추가하였습니다.

마치며

앱 서비스 안내를 추가한 3.8.2 버전이 앱스토어에 출시 되었습니다. Walk-Through UX 는 분명히 사용자에게 우리의 가치를 알리는데 효율적이고 도움이 될 것이라고 생각하고 있으며, 로그인을 할 때 사용자들이 좀 더 편리하게 사용할 수 있었으면 좋겠다는 목표로 작업을 하였습니다. 앱 서비스 중간중간 Coach Mark 도 고도화를 하는 등 쓰기는 쉽게 할 수 있도록 많은 고민을 하고 있습니다. 원티드 서비스를 사용하면서 어려운 부분이 있다면 알려주시면 사용하기 편리한 서비스로 개선될 수 있도록 노력하겠습니다.


참조