안녕하세요. 배민앱개발팀 고명석입니다.

현재 배달의민족 앱에 적용되어 있는 “오프라인 모드”라는 기능에 대해서 설명해보려고 합니다.

오프라인 모드란?

“오프라인 모드” 기능이란 배달의민족 앱을 서버 응답이 없는 상황에서도 사용할 수 있게 만든 기능입니다.

Google Map, Youtube 같은 여타 다른 앱에서도 구현되어 있는 기능으로, 일반적으로는 해외에 나가거나 장시간 네트워크 없이 활동하는 순간에 앱을 이용할 수 있게 만들어주는 기능입니다. 물론 배달의민족을 해외에서 사용할 수는 없지만, 핸드폰 데이터가 없는 응급 상황에서도 전화 주문을 통해 주문은 할 수 있도록 만든….것이 물론 주된 목적은 아닙니다 :-)

기능의 목적

우리네 개발자들은 서비스를 운영하다 보면 부득이하게 장애라는 상황을 맞이하게 되는데요. 그 순간은 예고 없이 찾아오기 마련입니다. 장애라는 불청객을 조금이라도 준비하고 맞이하기 위해서 “오프라인 모드”를 개발하였습니다.

장애 상황을 피하기 위해 서버에서 많은 대비책을 간구하여도 피치 못하게 장애라는 상황이 올 수 있는데 그때 최후방을 지키고 있는 최소한의 안전망이라고 이해하시면 좋을 것 같습니다.

서버의 응답이 없어도 가장 최근에 서버로부터 받아온 데이터를 기반으로 화면을 구성하여 사용자로 하여금 최소한의 기능을 사용할 수 있도록 하는데 목적이 있습니다.

기본 동작 로직

오프라인 모드의 기본적인 동작은 아래와 같습니다.

api-normal-response

일차적으로 정상적인 API 응답을 앱 클라이언트 내부에 저장합니다.

api-abnormal-response

이후에 API 응답이 비정상적으로 오는 경우에 저장된 API 응답을 이용하여 화면에 출력하는 간단한 기능입니다.

이렇게 간단한 기능이지만 크고 작은 장애 상황에서 큰 역할을 해주었습니다. /토닥토닥

오프라인 모드 적용기

“오프라인 모드” 기능은 두 번 업데이트로 나누어서 적용되었습니다.

1차 업데이트에서는 장애 상황에도 전화 주문은 가능하도록 적용하였으며,
2차 업데이트에서는 1차 업데이트에 적용된 부분을 조금 더 사용자 친화적으로 고도화하는 작업이 적용되었습니다.

1차 적용

1차 업데이트에서는 앱을 실행하고 메인 화면을 거쳐서 가게 목록, 가게 상세 화면에 들어가 주문을 할 때까지 서버 응답이 오지 않는 장애 상황을 고려하고 오프라인 모드를 적용하였습니다.

1차 업데이트의 목표는 ‘서버 응답이 없는 경우에도 전화 주문은 가능하도록 하자’ 였기 때문에 해당 목표를 달성하기 위해서 아래와 같은 작업들을 하였습니다.

  1. 앱 시작 시에 API 응답이 없는 경우에도 앱 진입이 가능하도록 호출 API마다 정책을 정하여 메인까지 진입할 수 있도록 작업을 하였으며,
  2. 메인 이후의 화면들에서 주문을 하기 위해서 최소한으로 동작해야 하는 기능을 정의하고 구현하였습니다. 물론 가게 진입까지 도움을 주는 API만 캐싱하도록 하였습니다.
  3. 앱에 저장되는 데이터는 앱에서 배달 주소가 변경되면 메인화면, 가게목록 데이터도 변경되기 때문에 배달 주소를 기준으로 저장하였습니다.
  4. 가게 상세 데이터의 경우에는 기존에 방문한 가게들만 보여주게 되면 일부 가게만 보여지게 되어 기능이 제한적이기 때문에 가게 목록에서 제공하는 데이터를 기반으로 가게 상세 화면을 보여주는 방식으로 개발을 하였습니다.

위와 같이 2018년 2월에 오프라인 모드를 적용하여 서비스하였습니다. 사용하고 있는 배달의민족 앱의 버전이 iOS는 6.4.0, 안드로이드는 8.5.0이 넘는 버전을 사용하고 있다면 오프라인 모드 적용 버전을 사용하고 있는 것입니다.

2차 적용

2018년 8월 말에는 팀 워크샵을 통해 아이디어를 도출하고, 그 중 우선 순위가 가장 높은 것을 중심으로 1차 적용 버전을 좀 더 고도화하는 작업을 아래와 같이 진행하였습니다

배민 라이더스 목록에도 적용

우선 1차 적용 버전에는 배민 라이더스 가게 목록에는 오프라인 모드를 적용하지 않아서 목록에 장애가 발생한 경우에 가게 상세페이지에 접근할 수 없는 문제가 발생하였습니다.

이를 해결하기 위해 배민라이더스 가게 목록에도 추가로 오프라인 모드가 적용되었습니다.

baera-old baera-new

광고 상품 표시

그리고 가게 목록 화면에서 오프라인 모드가 동작하게 되면, 모든 가게가 광고를 하지 않은 일반가게 형태로 나오게 되어있어서 광고주 입장에서는 조금 슬픈 UI가 노출되고 있었는데

이를 해결하기 위해서 서버로부터 광고상품 만료시간을 받아서 오프라인 모드가 동작하는 시점에 광고 중인 가게는 광고 목록에 표시될 수 있도록 변경되었습니다.

shop-list-old shop-list-new

메뉴 정보도 표시

그리고 가게 상세 화면에서도 기존에는 오프라인 모드 동작시에 메뉴 없이 전화 주문만 가능했던 화면에서 메뉴 데이터가 저장되어 있다면 메뉴 정보가 나올 수 있도록 변경하였습니다

shop-detail-old shop-detail-new

오프라인 상태 안내 UI 추가

마지막으로 오프라인 모드 동작 시에 현재 상태를 사용자가 알 수 있도록 안내하는 UI를 추가하였습니다.

offline_toast

물론 오프라인 모드가 동작하는 시점에 사용자가 해당 상황을 인지할 수 없게 하는 것도 개발자 입장에서는 괜찮을 것(?) 같지만, 오프라인 모드에서 화면을 보여주기 위해 사용하는 데이터들이 과거에 저장된 데이터라서 부정확할 가능성이 존재하기 때문에 정상적인 주문을 위해서는 사용자에게 현재 상태에 대해서 명확하게 알려주는 편이 낫다고 생각되어 UI를 추가하였습니다.

적용 결과

이렇게 2번에 업데이트를 거쳐서 현재의 오프라인 모드 기능이 완성되었고 현재도 계속 고도화하는 작업을 하고 있습니다.

물론 해당 기능이 동작하지 않는 장애 없는 상황이 가장 행복한 상황이었겠지만, 지구는 돌고 있고 서버도 돌고 있기 때문에 크고 작은 장애 상황이 발생하였고 그때마다 오프라인 모드는 최소한의 안전망의 역할을 충분히 하였습니다.

오프라인 모드를 적용하여 얻게된 효과는 다음과 같았습니다.

  1. 부분적인 장애 상황에서도 정상 상황과 거의 비슷하게 사용자들이 앱을 사용하여 주문할 수 있었으며,
  2. 이는 장애 상황에도 배달의민족 앱을 통해 주문을 받고 계신 사장님의 피해를 최소화하는 효과도 같이 얻을 수 있었습니다.
  3. 추가로 장애를 대응하기 위한 시간을 확보할 수 있었습니다.

글을 마치며

해당 기능이 기술적으로 뛰어나고 혁신적인 기능은 아니지만, 서버에서 발생할 수 있는 장애를 대비하는 역할이 비단 서버개발자만의 역할이 아니라 클라이언트 개발자들도 충분히 작업하여 대비할 수 있음을 보여주는 단적인 사례라고 생각되어 공유합니다.

우리 모두 장애 없는 세상을 이루어내어 크게는 인류 공영에 이바지하고 작게는 동료들의 숙면을 보장할 수 있는 세상이 왔으면 하는 아주 작은 소망을 내비치며 글을 마무리하고자 합니다.

God_be_with_you

오늘도 무사히!