AND Android 1차 세미나

한포도·2024년 10월 28일
0

AND-ANDROID

목록 보기
1/1
post-thumbnail

명령형 UI와 선언형 UI, 그리고 Jetpack Compose란?

안드로이드 개발을 시작하면서 UI를 구성하는 방식에는 명령형 UI와 선언형 UI라는 두 가지 접근 방식이 있습니다. 이번 글에서는 이 두 가지 UI 방식의 차이점과 Jetpack Compose에 대해 알아보겠습니다.

1. 명령형 UI와 선언형 UI

UI는 사용자가 시스템과 상호작용하는 중요한 요소입니다. 안드로이드에서 UI를 구성하는 방법은 크게 명령형 UI와 선언형 UI로 나눌 수 있습니다.

명령형 UI - "어떻게 (HOW)"

명령형 UI는 개발자가 직접 명령을 통해 화면을 제어하는 방식입니다. 예를 들어 XML을 사용해 뷰를 정의하고, setText()와 같은 메서드를 통해 화면 요소를 갱신합니다. 이 방식은 세밀한 제어가 가능하지만, 코드가 복잡해지고 상태 관리가 어렵다는 단점이 있습니다.

명령형 UI에서는 UI의 각 요소를 명령을 통해 수동으로 업데이트하기 때문에, 여러 요소의 상태를 유지하고 일관성을 관리하는 것이 까다로울 수 있습니다. 이러한 방식은 변화가 많은 UI나 복잡한 상호작용을 구현할 때 코드가 길어지고 유지보수가 어려워질 수 있습니다.

선언형 UI - "무엇을 (WHAT)"

선언형 UI는 화면의 최종 상태를 선언하는 방식입니다. 데이터가 변경되면 시스템이 UI를 자동으로 업데이트합니다. Jetpack Compose가 대표적인 선언형 UI 도구입니다. Compose에서는 @Composable함수로 UI를 정의하고, 데이터가 변경될 때마다 Compose가 자동으로 화면을 갱신해줍니다. 이는 코드 가독성을 높이고 유지보수를 쉽게 해줍니다.

선언형 UI에서는 UI를 어떻게 업데이트할지 신경 쓸 필요 없이, 데이터의 상태만 관리하면 됩니다. 상태가 변경되면 Compose가 이를 감지하고 필요한 부분만 재구성해서 효율적으로 UI를 업데이트합니다. 이로 인해 코드의 복잡도가 낮아지고, 변화가 많은 UI에서도 안정적인 구현이 가능합니다.

명령형 UI vs 선언형 UI

  • 명령형 UI: 개발자가 직접 UI 상태를 관리하며, 코드의 세밀한 제어가 가능하지만 복잡도가 높습니다.

  • 선언형 UI: 최종 상태만을 선언하고, 시스템이 상태 변화에 따른 UI 업데이트를 처리해 가독성과 유지보수가 용이합니다.

2. Jetpack Compose란?

Jetpack Compose는 2021년에 출시된 안드로이드 개발을 위한 선언형 UI 도구입니다. Kotlin을 기반으로 해서 간결하고 직관적으로 UI를 구성할 수 있고, 상태 변화에 따른 UI 업데이트를 자동으로 처리해주는 반응형 UI를 제공합니다. 또한 기존의 XML 뷰와 상호작용할 수 있어서 유연하게 사용할 수 있습니다.

Compose의 주요 특징

  1. 선언형 UI: UI 상태와 구조를 선언적으로 표현해서 코드의 가독성을 높입니다.

  2. Kotlin 기반: 코루틴과 확장 함수 등 Kotlin의 다양한 기능을 활용할 수 있습니다.

  3. 재사용 가능한 컴포넌트: 작은 단위의 컴포넌트를 통해 복잡한 UI를 쉽게 구성할 수 있습니다.

  4. 반응형 UI: 상태 변경에 따라 UI가 자동으로 반응하며 업데이트됩니다.

  5. 기존 앱과의 호환성: XML과 Compose를 함께 사용할 수 있어서, 점진적인 마이그레이션이 가능합니다.

Compose를 사용하면 기존 명령형 UI에 비해 코드의 양을 줄이고, 유지보수를 용이하게 만들 수 있습니다. 특히, Kotlin의 장점을 적극 활용해서 간결하고 직관적인 UI 구성이 가능합니다.

3. Compose 기본 컴포넌트와 레이아웃

Compose의 기본 컴포넌트로는 Text, Button, TextField 등이 있고, Column, Row, Box 같은 레이아웃 컴포저블을 통해 UI 요소를 배치할 수 있습니다. 각 컴포넌트는 Modifier를 사용해 크기, 색상, 패딩 등을 조정할 수 있고, @Preview 어노테이션을 통해 에뮬레이터 없이도 미리보기를 할 수 있습니다.

Modifier의 중요성

Modifier는 컴포저블에 스타일이나 동작을 부여하는 데 사용됩니다. 예를 들어 Modifier.padding(16.dp)를 사용해 컴포넌트에 여백을 줄 수 있습니다. Modifier의 순서는 최종 결과에 영향을 미치기 때문에 순서에 주의해야 합니다.

Modifier를 사용하면 컴포넌트의 배치, 크기, 여백, 클릭 동작 등을 손쉽게 정의할 수 있습니다. 여러 Modifier를 체인으로 연결해 사용하고, 순서에 따라 적용 결과가 달라질 수 있습니다. 예를 들어 padding을 먼저 적용할지, clickable을 먼저 적용할지에 따라 사용자 경험이 달라질 수 있습니다.

4. Compose와 Activity 생명주기

Compose UI는 안드로이드의 Activity와 함께 동작하며, Activity의 생명주기를 고려해서 안정적인 UI를 제공해야 합니다. Activity의 주요 생명주기 콜백은 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()가 있습니다. 이 콜백들을 적절히 활용해서 메모리를 해제하거나, 데이터 업데이트를 관리하는 것이 중요합니다.

예를 들어, onCreate()에서는 UI 초기화를, onPause()onStop()에서는 리소스 해제를, onResume()에서는 데이터를 다시 불러오는 작업을 할 수 있습니다. Compose와 Activity 생명주기를 잘 연동하면, 사용자가 앱을 나갔다가 돌아오더라도 자연스럽고 끊김 없는 UI를 제공할 수 있습니다.

Compose는 상태 기반의 UI이기 때문에 Activity의 생명주기와 상태 관리를 함께 고려해야 합니다. 이를 위해 remember나 rememberSaveable 같은 상태 관리 도구를 활용해서 Activity가 일시 중지되었다가 다시 시작될 때도 UI 상태를 유지할 수 있습니다. 이러한 도구들은 Compose의 강력한 상태 관리 기능을 뒷받침해서 사용자가 앱을 사용하는 동안 일관된 경험을 제공합니다.

상태 관리 도구

Compose에서의 상태 관리는 UI의 일관성을 유지하는 데 중요합니다. remember는 컴포저블이 재구성될 때 상태를 기억하게 해주고, rememberSaveable은 상태를 장기적으로 저장해서 Activity나 화면 회전 등으로 컴포저블이 재생성될 때도 값을 유지합니다. 이런 도구들을 통해 사용자는 화면 전환이나 기기 회전 시에도 끊김 없는 경험을 할 수 있습니다.

5. 실습: 간단한 로그인 화면 구현하기

이제 Compose를 활용해 간단한 로그인 화면을 구현해보겠습니다. TextField를 사용해 사용자 입력을 받고, Button을 통해 로그인을 시도하는 형태로 구성할 수 있습니다. Modifier를 활용해 패딩과 정렬을 설정하고, @Preview를 통해 UI를 미리 확인하면서 개발할 수 있습니다.

  1. TextField: 사용자 이름과 비밀번호를 입력받는 입력 필드를 생성합니다.

  2. Button: 입력된 정보를 기반으로 로그인 동작을 수행하는 버튼을 만듭니다.

  3. Modifier: 각 컴포넌트에 패딩과 여백을 추가해서 깔끔한 UI를 구성합니다.

@Composable
fun LoginScreen() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        var username by remember { mutableStateOf("") }
        var password by remember { mutableStateOf("") }

        TextField(
            value = username,
            onValueChange = { username = it },
            label = { Text("아이디를 입력해주세요") },
            modifier = Modifier.fillMaxWidth()
        )

        Spacer(modifier = Modifier.height(8.dp))

        TextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("비밀번호를 입력해주세요") },
            modifier = Modifier.fillMaxWidth(),
            visualTransformation = PasswordVisualTransformation()
        )

        Spacer(modifier = Modifier.height(16.dp))

        Button(
            onClick = { /* 로그인 로직 */ },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("로그인")
        }
    }
}

위의 예제처럼 Compose를 사용하면 간결한 코드로 UI를 구성할 수 있고, 선언형 접근 방식을 통해 데이터 상태에 따라 화면이 자동으로 갱신됩니다.

6. Compose의 한계와 고려사항

Jetpack Compose는 매우 강력한 도구지만 몇 가지 한계점도 있습니다. 대표적으로 선언형 UI의 특성상 모든 상태를 데이터로 관리해야 하기 때문에 상태 관리가 복잡해질 수 있습니다. 특히 대규모 애플리케이션에서는 상태 관리의 구조를 잘 설계하지 않으면 코드의 유지보수가 어려워질 수 있습니다.

또한, 기존 명령형 UI에서 Compose로 전환하는 과정에서 XML 기반의 레이아웃과 Compose의 레이아웃을 혼합해 사용하는 경우 호환성 문제나 복잡한 통합 작업이 발생할 수 있습니다. 이러한 문제를 해결하려면 Compose의 도입을 점진적으로 진행하고, 필요한 경우 기존의 View와 Compose를 혼합해서 사용하는 게 좋습니다.

마무리

이번 글에서는 명령형 UI와 선언형 UI의 차이점, 그리고 Jetpack Compose의 주요 개념과 기본적인 사용법에 대해 알아봤습니다. Compose를 활용하면 더 간결하고 유지보수하기 쉬운 코드를 작성할 수 있고, 상태 변화에 따라 자동으로 UI를 갱신할 수 있어 현대적인 안드로이드 개발에 매우 유용해요. 사실 당연히 컴포즈 처럼 짜는줄..

남은 세미나를 통해서 어엿한 안드로이드스러운 개발자가 될때까지 화이팅!

profile
응애 개발맨
post-custom-banner

0개의 댓글