Server Driven UI, Project Atlas를 소개합니다.
Atlas
그리스 신화를 보면, 제우스를 상대로 싸우다 천구(天球)를 떠받드는 형벌을 받게 된 거인 ‘아틀라스’가 등장합니다. 이 이야기에서 유래되어 Atlas라는 단어는 거인의 이름 뿐만 아니라 ‘지도책’이라는 의미도 갖게 되었죠.
이러한 의미를 바탕으로, 플렉스팀은 Atlas라는 이름의 Server Driven UI 프로젝트를 시작했습니다.
승인 콘텐츠
본격적으로 Atlas를 소개하기에 앞서서, flex 모바일 앱에서 한가지 사례를 들여다보려고 합니다.
위 세가지 화면은 근무, 휴가, 정보 변경 등 구성원이 다른 구성원이나 조직장의 승인이 필요할 때 사용하는 승인 문서 화면입니다. 근본적으로는 같은 화면이라도 어떤 내용에 대한 승인 문서인지에 따라 구성하는 요소와 배치가 현저히 달라질 수 있습니다.
물론 구성을 통일하여 재사용성을 높이는 방법도 고려해볼 수 있지만, 각각의 맥락을 더 명확하게 표현할 수 있는 형태를 취하는 것이 보다 중요한 가치라고 생각하기 때문에 최대한 개별 구성을 살리고자 합니다.
구성원이 많아질수록 팀에게 필요한 역할들이 다양해지고, 자연스럽게 승인이 필요한 일들도 그 종류가 늘어나 승인 문서의 콘텐츠 템플릿 또한 예측하기 어려운 형태로 추가되고, 발전합니다.
그러면 그럴 때마다 새로운 API 형상에 따라 UI 코드를 작성하고, 테스트 과정을 지나, 스토어에 배포하고, 문제가 생길 경우 Hotfix를 진행하는 일련의 과정들을 iOS, Android 각 플랫폼 개발자가 동일하게 거치게 되는 것이죠.
이때, 플랫폼 개발자들의 의도 해석에 따라 동작이 다르게 되는 문제가 생기면서 낭비되는 시간과 비용이 발생하기도 하고요.
Server Driven UI
그래서 Server Driven UI(이하 SDUI)는 어떤 것을 해결해주는 것일까요?
일반적으로, 클라이언트는 하나 혹은 그 이상의 서버 API로부터 데이터를 내려받은 뒤 UI를 표현하기 위한 모델로 변환하거나 비즈니스 로직을 작성하는 UI 매핑 과정을 거쳐 그 결과를 화면에 그려줍니다.
주로 문제가 되는 것은 이 UI 매핑 과정인데, 클라이언트가 데이터를 UI 요구사항에 맞게 가공하는 코드를 작성해서 새로운 버전을 스토어에 게시해야 하기 때문에 앱 업데이트를 할 수 밖에 없게 됩니다.
SDUI는 이 UI 매핑 과정을 클라이언트가 아닌 백엔드가 담당하도록 합니다. flex에서는 해당 과정을 처리하기 위한 별도의 BFF(Backends For Frontends) 레이어를 추가하여, 여러 서버로부터 데이터를 받아 UI로 가공한 결과물을 클라이언트에 전달하게 됩니다.
이때 클라이언트는 그 결과물을 그려주기만 하면 되는 것이죠.
fxm
SDUI를 체계적이고 효율적으로 만들기 위해서는 플랫폼간에 강력한 규칙으로 합의된 포맷이 필요합니다.
서버에서도 들여다볼 수 있는 소스가 필요하고, 클라이언트에서도 문제 없이 해석할 수 있는 인터페이스가 있어야 의사소통의 낭비 없이 SDUI를 시작할 수 있기 때문입니다.
최근 플렉스팀은 flex 모바일 앱의 디자인 시스템을 새롭게 설계하여 ‘fxm’이라는 이름으로 재정의했고, Atlas에서 SDUI의 기반을 구축하기 위한 인터페이스로 채택했습니다.
fxm을 통해 우리는 flex 모바일 앱의 모든 UI 요구사항을 구성할 수 있고, Atlas를 통해 모든 fxm 컴포넌트를 모델화한다면 이론적으로는 Atlas가 flex 모바일 앱의 모든 화면을 커버할 수 있게 됩니다.
fxm에서 목록 콘텐츠에 보여주는 FxRow라는 이름의 컴포넌트를 간략히 살펴보면 제목, 설명, 왼쪽 영역 등 각 슬롯에 보여주기 위한 속성들을 위와 같이 정의하는데,
이는 모두 iOS, Android 각 플랫폼에 동일한 스펙으로 명세하고 있기 때문에 같은 JSON 인터페이스로 모든 플랫폼이 동일한 형태로(때로는 플랫폼에 더 자연스러운 형태로) 화면에 표시할 수 있습니다.
Atlas에서는 flex 모바일 앱을 표현하기 위한 거의 모든 컴포넌트들을 JSON 포맷으로 표현했습니다. 여기에는 여러가지 컴포넌트가 이미 조합된 단위의 컴포넌트는 물론이고 Text, Icon, 혹은 Stack, Box처럼 Atomic한 단위의 컴포넌트까지 포함되어 있습니다.
Events, Variables(w. Kotlin DSL)
하지만 단순 UI 명세만 가지고는 완전한 화면을 구성하기 어렵습니다.
어떤 버튼을 클릭했을 때, 어떤 배너가 화면에 노출되었을 때 화면을 구성하는 요소가 변화하거나 사용자의 입력에 따라 적절한 메시지를 보여주어야할 수 있어야 하는 것이죠.
위 코드는 서버측 코드 실제 예시입니다.
Atlas는 백엔드 코드 작성의 편의성을 위해 JSON을 직접 작성하지 않고 Kotlin DSL 형태로 제공합니다. 이는 우측의 코드와 같이 최종적으로 API 응답에서 JSON으로 변환되어 클라이언트에 내려주게 됩니다.
코드를 대략 훑어보면 두 부분을 주목할 필요가 있습니다.
- FxRow 컴포넌트를 클릭했을 때 정해진 명세에 따라 API 요청을 수행
username
이라는 변수에 사용자의 이름을 두어 목록에 표시
Atlas는 위와 같이 컴포넌트별 이벤트 처리와 변수 표현까지 포함하고 있어 사용자와 실제로 상호작용이 이루어지는 화면을 구성할 수 있습니다.
이 코드는 어떨까요?
어떤 동작은 단순히 하나의 이벤트만 처리하는 것이 아니라 여러 이벤트를 동시에, 혹은 순서대로 처리할 필요가 있습니다.
코드에서는 serialEvents {}
, parallelEvents {}
블록을 조합하여, FxRow 컴포넌트를 클릭했을 때 API 요청을 수행한 뒤 clicked
라는 이름의 변수를 true
로 설정하고, API 요청 완료
라는 토스트를 보여주는 시퀀스를 표현하고 있습니다.
Atlas는 화면을 구성할 때 주로 사용되는 몇가지 이벤트들을 정의하고 있습니다.
JSON으로 표현하기 어려운 간단한 연산 과정들은 FxEvaluateJs 이벤트를 통해 Javascript를 실행하거나, FxLogEvent 이벤트를 통해 수집하고 싶은 사용자 행동 지표를 원하는 요소로부터 수집할 수도 있습니다.
Custom Components
UI와 각종 이벤트들을 여러가지 형태로 조합할 수 있기는 하지만, 사전에 정의된 컴포넌트들로만 화면을 구성하는 경우 비교적 단순한 동작들만 처리할 수 있고, 복잡하거나 개별 플랫폼 동작에 의존적인 요소들은 표현하기 어렵습니다.
그렇기때문에 어느정도 수준의 자유도를 보장하기 위해 개별 도메인 개발자가 직접 정의할 수 있는 형태의 컴포넌트 지원이 필요합니다.
Android에서 Atlas를 사용하는 예시 중, Custom View를 표현하는 클라이언트 코드입니다.
로컬 기기의 데이터로부터 UI를 표현해야하거나, 외부의 이벤트에 따라 상태를 매우 유동적으로 갱신해야하는 경우 등에서는 클라이언트 각 플랫폼에서 각자 구현한 컴포넌트에 이름을 부여해서 Atlas에 정의되지 않은 UI를 표현할 수 있습니다.
이때, 서버에서는 { "type": "FxCustomView", "name": "CheckInCard" }
처럼 name
속성만 갖는 컴포넌트를 JSON에 내려줍니다.
같은 형태로, 각 플랫폼이 요구하는 코드들을 가지고 비즈니스 로직을 처리해야하거나 현실적으로 JSON으로 표현할 수 없는 이벤트들을 Custom Event로 내려줄 수 있습니다.
예를 들어 이미지상 위의 서버 코드처럼 Custom Event의 이름을 CheckIn 내려주면, 아래의 클라이언트 코드에서는 해당 이름의 이벤트를 수행하는 함수를 작성하기만 하면 됩니다.
Hands On
현재 flex 모바일 앱에서 볼 수 있는 알림 화면입니다.
이 알림 화면은 꽤 복잡한 동작들을 수행하고 있습니다.
- 알림 읽음 여부에 따른 빨간 점 노출 연동
모두 읽기
버튼으로 모든 알림 읽음 처리2건 더보기
버튼으로 바로 아래에 같은 토픽의 알림 2건 펼치기- 스크롤을 내리면 API를 통해 추가 목록 요청 후 페이징 처리
- …
플렉스팀 모바일 스쿼드는 이 모든 동작을 수행하는 알림 화면을 Atlas로 100% 전환했습니다. (2024년 12월 버전 기준)
클라이언트에서 알림 화면을 보여주기 위한 도메인 관련 코드는 한 줄도 포함되지 않았습니다.
flex 고객이시라면, 클라이언트 코드 없이 완전한 기능을 수행하는 알림 화면을 지금 바로 사용해보세요.
Conclusion
물론 Atlas는 아직은 완전한 프로젝트가 아니기 때문에 더 높은 수준의 SDUI를 달성하기 위해 앞으로도 어려운 문제들이 있을 것입니다.
Atlas는 모든 화면을 대체하기 위한 프레임워크를 목표로 하고 있지 않습니다.
정적이면서도 빠른 변화가 필요한 곳에서 아주 뾰족하게 사용되는 임팩트를 기대하고 있습니다.
플렉스팀은 언제나 flex 사용자 모두가 지체 없이 서비스를 제공 받을 수 있도록 노력하고 있으며, Atlas는 앞으로 적재적소에서 그 크고 작은 노력들에 큰 발판이 될 것으로 생각합니다.