Jetpack Compose 데이터 저장 시스템

Slot Table, Change List 소개

Ji Sungbin
성빈랜드
5 min readMay 18, 2022

--

Photo by Wolfgang Hasselmann on Unsplash

Jetpack Compose 에는 핵심 데이터들을 저장하기 위한 2가지의 저장소가 있습니다. 부제목에서부터 알 수 있듯이 Slot Table 과 Change List 이며 차례대로 알아보겠습니다.

Slot Table

이는 Android Developers 미디엄에서 “Under the hood of Jetpack Compose — part 2 of 2” 라는 제목으로 예전에 이미 소개됐습니다. 이를 통해 많은 분들이 Slot Table 의 존재와 Gap Buffer 에 대해 알고 계실거라 생각합니다. 만약 위 아티클을 보지 못해 Gap Buffer 라는 개념이 생소하시다면 “Gap Buffer 자료구조 간단히 알아보기” 글을 통해 확인하실 수 있습니다.

슬릇 테이블은 발생한 컴포지션에 대한 정보들(예: 컴포지션동안 발생한 일, 사용된 인자, CompositionLocal, 호출된 다른 함수 등등)이 저장되는 공간입니다. 즉, 값이 remember 되고 리컴포지션이 되기 위해 필요한 정보들이 추척됩니다.

시작하면서 말했듯이 슬릇 테이블은 Gap Buffer 자료구조를 기반으로 한 빠른 선형 접근에 최적화된 메모리 구조입니다. 이는 다음 2가지의 선형 배열로 이루어져 있습니다.

  • group: 컴포저블의 그룹에 대한 메타데이터를 제공하는 그룹 필드에 대한 값만 저장됩니다. 따라서 IntArray 로 구현됩니다. (컴포저블 그룹에 대한 key 라고 생각하시면 됩니다)
  • slot: 각각 컴포저블 그룹에 대한 관련 데이터를 저장합니다. 실제 컴포지션 관련 데이터가 저장되는 곳이며, 다양한 데이터들이 저장될 수 있기에 Array<Any?> 로 구현됩니다. (컴포저블 그룹에 대한 value 라고 생각하시면 됩니다)

그룹은 항상 슬릇 범위에 연결돼 있으므로 그룹 배열에 저장된 각 그룹은 슬릇 배열에서 슬릇을 찾고 해석하는 방법을 설명합니다. 테이블에서 읽고 쓰기를 위한 SlotReader 와 SlotWriter 가 존재합니다. SlotReader 는 여러개가 활성화 될 수 있고, SlotWriter 는 하나만 활성화가 가능합니다. 이는 경쟁 상태 방지를 위한 것이며, 동일 이유로 SlotWriter 가 비활성 상태일 때만 SlotReader 의 활성화가 가능합니다.

슬릇 테이블에서 발생하는 모든 작업마다 cursor 를 해당 위치로 옮기느라 O(N) 이 걸리는건 매우 비효율 적입니다. 따라서 슬릇 테이블은 Anchor 라는 개념을 도입하여 랜덤 액세스를 활성화 시킵니다.

이 Anchor 를 이용하여 랜덤 액세스를 활성화 시켜 커서를 조정하는 O(N) 시간을 없애게 됩니다.

슬릇 테이블은 왜 Gap Buffer 를 이용해 구현됐을까요? 아래와 같이 isColumn 값에 따라 루트 레이아웃을 동적으로 변경시켜 보여주는 컴포저블이 있습니다.

초기엔 isColumn 값이 true 이므로 Column 을 기준으로 슬릇 테이블의 갭이 형성됩니다.

isColumn 값이 false 로 변경돼 루트 레이아웃이 Row 로 변경된 경우에는 루트 레이아웃이 변경됨으로 하위 아이템들의 개수가 기존과 동일할 것이라고 확신하지 못해 새로운 루트인 Row 를 기준으로 Gap 을 처음부터 다시 할당합니다. 즉, 이 시점에서는 O(N) 이 소요됩니다.

하지만 실제 UI 에서는 이렇게 루트 레이아웃이 동적으로 변경되는 상황이 많이 없으므로 초기 갭 할당 이후로는 모든 작업이 O(1) 로 진행될 가능성이 높습니다. 따라서 컴포즈 개발팀에서는 슬릇 테이블의 데이터 저장 방식으로 Gap Buffer 를 채택하였습니다.

Change List

Change List 는 아마도 처음 보시는 분들이 많을겁니다. 컴포즈 내부를 보더라도 깊게 들어가보지 않았다면 처음 봤을 확률이 큽니다. Change 는 슬릇 테이블에 기록된 정보를 가지고 컴포저블 트리를 업데이트 하는 작업을 의미합니다.

컴포저블이 방출(컴포지션)될 때마다 슬릇 테이블을 보고, 현재 사용 가능한 데이터들을 토대로 컴포저블에 반영할 변경 사항들을 Change 로 모델링해 Change List 에 추가합니다.

컴포지션이 끝나면 구체화(실제 UI 로 그리는 과정)될 시간이 되며 Change List 에 쌓인 Change 들을 실행합니다. 이러한 과정을 통해 미리 반영할 사항들을 만들어 두고 바로 적용함으로써 방출 과정이 매우 빠르게 진행됩니다.

Change(List) 역시 슬릇 테이블에 저장됩니다.

끝!

이번 글에서는 간단하게 Slot Table 과 Change List 에 대해서 알아보았습니다. 감사합니다.

[목차로 돌아가기]

안드로이드 개발자 분들을 위한 카카오톡 오픈 채팅방을 운영하고 있습니다.

--

--

Ji Sungbin
성빈랜드

Experience Engineers for us. I love development that creates references.