컴포즈의 UI 노드 구성 방법과 useUnmergedTree
안드로이드 UI 테스트를 작성하다 보면, 노드를 찾는 함수 안에 useUnmergedTree 인자가 들어가 있는 경우를 볼 수 있다. 이는 모든 onNode- 함수와 onAllNodes- 함수 안에 들어가 있는 것을 볼 수 있는데, 그만큼 중요한 인자임을 알 수 있다. 다음은 대표적인 두 개의 함수이다.
이 인자가 중요한 이유는 컴포즈가 UI 노드를 구성하는 방법과 연관되어 있다. xml 기반으로 작성되던 View 시스템에서는 각 View가 하나의 UI 노드가 되었지만, 컴포즈에서는 효율성을 위해 UI 노드를 하나로 합칠 수 있으면 합치는 방식(merge)을 취한다. 이를 통해 두 개의 Composable 혹은 세 개의 Composable이 하나의 UI 노드를 구성할 수 있게 된다.
useUnmergedTree 살펴보기
예를 들어 Button 컴포저블 안에 두 개의 텍스트를 넣은 후 useUnmergedTree가 false일 때 UI 노드가 어떻게 출력되는지 살펴보자.
@Test
fun useUnmergedTreeFalse() {
// Given
composeRule.setContent {
Button(onClick = {}) {
Text(text = "Hello")
Text(text = "World")
}
}
// When
composeRule.onRoot(useUnmergedTree = false).printToLog("MY TAG")
// Then
// ...
}
그러면 실행 결과는 다음과 같이 나온다. 결과에서 Hello와 World가 Button 컴포저블과 함께 하나의 UI 노드로 합쳐져 Text가 "Hello, World"로 보이는 것을 볼 수 있다.
따라서 이런 경우 다음 코드를 통해 UI 노드를 찾을 경우 버튼 전체가 찾아지게 된다.
composeRule.onNodeWithText("Hello")
하지만, 종종 일부 UI 노드만을 찾아야 되는 경우가 있다. 예를 들어 "Hello" Text 컴포저블만 찾아야 되는 경우 위와 같이 최적화가 되어버리면, 필요한 UI 노드를 찾을 수 없게된다. 이런 경우를 위해 Compose는 useUnmergedTree의 값을 true로 설정함으로써 최적화되지 않은 UI 노드를 볼 수 있는 방법을 제공한다. 먼저 다음 코드를 통해 useUnmergedTree가 true일 때 UI 노드가 어떻게 구성되는지 살펴보자.
@Test
fun useUnmergedTreeTrue() {
// Given
composeRule.setContent {
Button(onClick = {}) {
Text(text = "Hello")
Text(text = "World")
}
}
// When
composeRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")
// Then
// ...
}
그러면 다음과 같은 결과를 볼 수 있다.
Button 컴포저블과 두 개의 Text 컴포저블이 더이상 합쳐지지 않고, 여러 개의 컴포저블로 보이는 것을 볼 수 있다.
Unmerged Tree 사용해 UI 노드 찾기
최적화되지 않은 UI 트리를 사용해 UI 노드를 찾는 방법은 간단하다. 모든 onNode- 혹은 onAllNodes- 함수에는 useUnmergedTree 인자가 포함되어 있으므로, 이 값을 true로 설정해 최적화되지 않은 UI 트리를 사용해 UI 노드를 찾을 수 있다. 다음은 onNodeWithText에 useUnmergedTree = true를 적용한 예시이다.
composeRule.onNodeWithText(text = "Hello", useUnmergedTree = true)
정리
컴포즈는 최적화를 위해 복수의 UI 노드를 합친다. UI 테스트 시에는 UI 노드가 합쳐지지 않은 상태로 확인해야 할 정보가 필요할 수 있으며, 이런 경우 useUnmergedTree = true를 사용하면 된다.