본문 바로가기
기타

Preview Driven Development(프리뷰 주도 개발?)

by 나이아카 2024. 11. 23.

 근래 이야기되고 있는 분야인지는 모르겠습니다만, 제가 근래 본 포스트에 Preview Driven이라는 말이 많이 나오곤 했습니다. 그래서 좀 더 살펴보게 되더라구요. 여기서 말하는 Preview라는 이름은 Compose의 @Preview를 통한 그 화면에서 등장한 이름입니다. 그러니까 이 개발 방식은 Android, 그 중에서도 Compose를 사용하는 프로젝트에서 적용해볼법한 방식이라는 것을 의미합니다. 그렇다면 아직 논의된 지 오래되지 않은 개발 방식이겠군요!

 저도 사용해본 적은 없어서 괜찮은지는 잘 모르겠습니다. 하지만 저희 회사에서도 현재 빌드 속도가 굉장히 이슈가 되고 있는 만큼, 이 방법이 도움이 될 수 있지 않을까 생각했습니다.


 

 PDD라고 줄여도 되는지 모르겠는 이 개발 방식은 안드로이드에서는 @Preview를 이용해 화면을 볼 수 있는 Compose에서 사용할 수 있습니다. 물론 그렇다고 오직 안드로이드를 위한 개발방식은 아닌게, SwiftUi에서도 Preview를 이용한 개발 방식에 대한 글들을 볼 수 있었습니다. 

 그러니 Preview를 통해 충분히 UI에 대한 테스트(데이터 변경에 따른 화면의 동작)가 진행이 가능하다면 이 개발 방식을 차용할 수 있다는 것을 의미합니다. 이렇게 프레임워크가 제공하는 프리뷰 기능을 이용해 각 화면을 독립적으로 테스트하는 것(그 범위는 각 프레임워크의 프리뷰의 지원 범위에 따라 조금씩 달라지겠지만)을 PDD라 합니다.

 

 조금 상세하게 안드로이드의 Compose의 ComposeView에는 대부분 @Composable을 통한 ComposeUI와 그 아래에 Preview를 위한 PreviewUI가 하나의 kt 파일에 들어가는 것이 일반적입니다. 그리고 이 PreviewUI는 기본적으로 안드로이드 스튜디오 오른쪽에 UI를 보여주는 역할을 하고 있습니다. 이 Preview에서 UI의 구성이나 변경을 보는 것은 한 번 빌드를 해 둔 이후, Preview 내에서 사소하게 데이터나 UI의 구성의 변경이 일어나더라도 빌드 속도보다는 빠르게 변경됩니다. Preview를 보여주는 화면 내부 동작에서 큰 이슈가 없다면 아마 거의 hot-reload에 가깝게 UI가 변경될 것입니다(물론 아예 빌드를 해줘야 하는 경우가 있는데, 이때는 빌드 속도에 대한 이득이 있다고 볼 순 없겠네요).

@Preview
@Composable
fun SearchScreenPreview() {
    SearchScreen(Modifier.fillMaxWidth(), SearchPreviewViewModel())
}

 위와 같은 검색을 위한 ComposeUI가 있다고 가정해봅시다. 여기 파라미터에는 ViewModel이 들어갈 수도, 아니면 다른 값들이 들어갈 수도 있는데 일단 ViewModel을 사용합니다. 그렇다면 이 ViewModel에도 무언가가 필요하겠죠?

interface SearchViewModel {
    val searchText: MutableStateFlow<String>
    val uiStates: StateFlow<List<SearchUiState>>
    val isLoading: StateFlow<Boolean>
    val actions: SharedFlow<SearchAction>
    /* 여기에는 추가적으로 사용할 여러가지 필드를 넣을 수 있겠죠! */
    
    fun handleEvent(event: SearchEvent)
}

 저는 주로 이런 interface를 이용해서 Screen에 사용할 ViewModel을 구성합니다. 인터페이스인 이유는, SearchScreen에서 사용할 ViewModel의 구성을 미리 작성하는 것도 있지만, Preview에서 사용할 ViewModel을 직접 사용할 ViewModel과 구분하려는 의도도 포함되어 있습니다. 실제 화면에 사용할 ViewModel을 Preview에 넣게 되면 값을 변경하는 것으로 Preview에서 테스트하기 힘드니까요!

 

 일단 이렇게 2개만 구성을 해도(물론 SearchScreen도 원하는 UI대로 구성해야 합니다) Preview를 통해 UI를 확인할 수 있게 됩니다. 저는 보통 PreviewViewModel이라는 네이밍을 사용하는데(여기서는 SearchPreviewViewModel로 사용하겠죠) 여기에서 interface의 필드의 값들을 바꿔주면 Compose Preview에서 바로 확인이 가능합니다.

 이때 

class SearchPreviewViewModel: SearchViewModel {

    /* TODO */
    val searchText: MutableStateFlow<String>
    
    private val _uiStates: MutableStateFlow<List<SearchUistate>> = MutableState(getUiState())
    val uiStates: StateFlow<List<SearchUiState>> = _uiStates.asStateFlow()
    val isLoading: StateFlow<Boolean>
    val actions: SharedFlow<SearchAction>
    
    fun handleEvent(event: SearchEvent)
    private fun getUiState() : List<SearchUiState> {
        //여기에 UiState를 구성하기 위한 조건 등을 표현
    }
}

 위처럼 코드를 작성한다면 이 SearchPreviewModel이 @Preview가 달린 ComposeUI에 파라미터로 들어가게 되면 프리뷰의 로딩과 동시에 getUiState가 호출됩니다. UI가 문제 없이 오른쪽에 잘 표현된다면 getUiState 내부의 코드가 제대로 이루어져서 빌드되었다는 것을 의미하죠. 물론 실패하는 경우 render problem을 통해 에러를 확인할 수 있습니다. 물론 정확하게 어떤 조건인지는 모르겠지만 이슈가 어디서 발생하는 지 확인할 수 없는 경우도 있으니, 그 때는 조금 검증이 조금 어려워진다고 생각하면 되지만, 코드를 한 라인씩 나눠서 테스트해보면 그리 어렵지 않을 겁니다!

 

 되게 여러가지를 이해해야 할 것 같지만, 쉽게 말하자면 프리뷰가 단순하게 UI를 표시해주는 것도 있지만, Preview Compose 내부의 비즈니스 로직이 섞여도 같이 빌드해주면서 거기서 얻을 수 있는 힌트를 기준으로 테스트를 대체하겠다는 것이 주된 의견입니다.

 프리뷰 주도 개발의 다른 글들에서 제일 많이 확인할 수 있는 부분은, 간단한 비즈니스 로직이나 UI를 만드는 작업에 대한 검증을 굳이 TDD로 작업할 때 테스트 코드를 작성해야 하는 가에 대한 의문에서 시작한 경우가 많습니다. 오히려 테스트 코드를 작성함으로서 작업 시간이 늘어나는 문제가 있는데, 이에 대한 부분을 프리뷰의 기능을 통해 대체하겠다는 것이 목적이라고 볼 수 있습니다.

 PDD는 분명 TDD와는 검증에 대한 방식은 다르지만, 같은 결이라고 볼 수도 있지 않을까요.


 사실 driven development라고 되어 있지만, 한 줄로 쉽게 설명하자면 그냥 UI 개발할 때 Preview를 잘 쓰고 ViewModel 연결을 잘 해서 빌드 전에 확인해보자! 인 것 같습니다. 그런데 이제 Preview의 기능을 좀 더 효율적이고 극한으로 사용해보고자 함이 목적이죠. 

 하지만 잘 사용하면 여러 방면에서 무궁무진하게 사용할 수 있는 것 같습니다. 실제로 아래 참조에 달아놓은 글을 보면, 날짜 데이터에 대한 가공을 처리하고 있는데, 이런 애매하게 자주 실수하는 값들을 빌드 없이 Preview에서 확인할 수 있다는 것은 분명 좋은 방법 중 하나라고 생각합니다.

 

 

참조

https://medium.com/whatnot-engineering/preview-driven-development-with-compose-f7a5beee95aa

 

@Preview Driven Development with Jetpack Compose

Necessity is the mother of invention.

medium.com

https://www.emergetools.com/blog/posts/preview-driven-development

 

Emerge Tools Blog | Preview Driven Development

Learn how to leverage Jetpack Compose Previews for testing and mini-apps to build better Android applications

www.emergetools.com

 

댓글