[Jetpack Compose] Compose란 무엇일까

너 오늘 코드 짰니?·2023년 8월 22일
2

Android Jetpack Compose

목록 보기
1/3

본 글은 Android developers' Jetpack Compose 공식문서를 참고하여 작성되었습니다.

Jetpack? Compose?

먼저 Compose에 대해 논하기 전에 Jetpack에 대해 알아야 합니다. 우리가 안드로이드 개발을 한다는 것은 보편적으로 Android OS 내에서 동작하는 응용프로그램을 개발하는 행위를 의미합니다. 응용프로그램을 만들기 위해 우리가 모든것을 다 코딩할 수 는 없겠죠? 마치 소고기를 먹기위해 소를 키우는일부터 시작하지 않고 마트에 가서 고기를 사오는 것처럼 안드로이드에서도 응용프로그램을 개발하기 위해 유용한 툴과 라이브러리들을 제공합니다.

구세대에는 이를 Support Library라고 불렀으며 현세대에 좀 더 편리하고 빠른 강력한 도구들로 리뉴얼한 라이브러리 모음을 Jetpack이라 부르는 것입니다.

Android Jetpack은 androidx.* 형태로 패키징되어 제공됩니다. 또한 android support library는 28.0.0 버전 이후로 더이상 업데이트 되지 않으므로 새로운 기능을 개발할 때에는 androidx 패키지를 활용하여 개발해야 할 것입니다.

// com.android.support.~~~ 로 시작하는 패키지들이 support library입니다.
dependencies {
        implementation "com.android.support:support-v4:$libraryVersion"
        implementation "com.android.support:appcompat-v7:$libraryVersion"
        implementation "com.android.support:design:$libraryVersion"
}

// androidx.~~~ 로 시작하는 패키지들이 jetpack library입니다.
// 이전의 support library들은 androidx.legacy에 포함되기 때문에 모두 사용가능합니다.
dependencies {
        implementation 'androidx.legacy:legacy-support-v4:1.0.0'
        implementation 'androidx.appcompat:appcompat:1.0.0'
        implementation 'com.google.android.material:material:1.0.0'
        implementation 'androidx.recyclerview:recyclerview:1.0.0'

Jetpack의 구성요소

Jetpack라이브러리는 통합적으로 안드로이드 응용프로그램을 개발하기 위한 도구들이 지원되므로 매우 많은 라이브러리가 포함되기 때문에 이곳에서 전부 설명할 수 없습니다.
그래도 가장 많이 사용되고 대표적인 것들을 몇가지 뽑아보자면 아래와 같습니다.

  • LiveData: 데이터의 변화를 관찰하고 알림을 받을 수 있는 라이브 데이터 객체를 제공합니다. 이를 통해 UI와 데이터 사이의 연결을 쉽게 관리할 수 있습니다.

  • ViewModel: UI 관련 데이터를 관리하고, 구성 변경과 같은 수명 주기 이벤트에 대해 데이터를 보존할 수 있도록 돕습니다.

  • Room: SQLite 데이터베이스를 사용하여 로컬 데이터를 저장하고 관리하는 데 도움을 주는 라이브러리입니다.

  • Navigation: 앱 내 탐색을 관리하고 사용자 이동 경로를 정의하는 데 도움을 줍니다.

  • Paging: 대용량 데이터 집합을 로드하고 표시하는 데 사용되는 라이브러리입니다.

  • WorkManager: 비동기 작업을 관리하고 예약하는 데 사용되며, 예를 들어 백그라운드에서 데이터 동기화나 작업 예약에 유용합니다.

  • Data Binding: UI 컴포넌트와 데이터 모델을 연결하여 코드 중복을 줄이고 앱의 유지 보수성을 향상시키는 데 도움을 줍니다.

LiveData ViewModel Room같은 것들은 이미 개발할 때 종종 사용해오던 것들입니다. 나도 모르게 Jetpack library들을 자연스럽게 사용하고 있었던것 같은데 최근들어 Jetpack에서 새로운 문제를 개선하기 위한 업데이트가 일어나고 있습니다.

그것은 바로 UI 렌더링 방식의 변경점인데요, Jetpack Compose가 바로 그 주인공입니다.

Compose란 무엇일까

Jetpack에서 UI작업을 개선하기 위하여 나온 라이브러리가 Compose입니다.

기존의 UI 렌더링 작업은 xml 파일로 구조를 정의하고 코틀린 코드에서 xml 파일을 바인딩시켜 하나하나 기능을 구현하는 방식을 사용했습니다. 즉, UI 디자인과 코드가 분리된 형태였으며 UI 의 구조가 복잡해질 수록 코드량이 늘어나고 가독성이 떨어지는 단점이 존재했습니다.

Compose를 사용한다면 코드량이 훨씬 줄어들 뿐더러 UI적인 요소를 모두 kotlin코드로 통합할 수 있습니다. 또한 머티리얼디자인을 유연하게 구현할 수 있으며 애니메이션을 쉽고 빠르게 적용할 수 있는 장점이 있다고 하는데, 공식문서에 의하면 Compose의 특징은 아래와 같습니다.

  • 선언적 UI : Compose는 선언적인 방식으로 UI를 정의하기 때문에, 어떻게 보일지를 명시적으로 정의하기 쉽습니다. UI를 kotlin으로 설명만 하면 compose에서 알아서 처리하므로 UI를 직관적이고 빠르게 개발하고 변경할 수 있습니다.

  • 재사용성 : Compose에서는 컴포넌트를 재사용하기 쉽게 만들 수 있습니다. 작은 컴포넌트를 조합하여 복잡한 UI를 구축할 수 있습니다.

  • 코드 길이 감소 : Compose는 코드의 길이를 줄여주고, 개발자가 더 적은 타이핑을 할 수 있도록 합니다.

Compose 찍먹 해보기

본격적으로 컨텐츠를 시작하기 전에 간단하게 Compose가 어떤식으로 사용되는지 체험만 해보겠습니다.

Compose에 맞춰 기본 틀이 구성되어 있는 Empty Compose Activity로 프로젝트를 생성합니다.
(글 작성일 기준 Material3 디자인이 Preview로 풀려있는데 머티리얼 디자인의 트렌드도 변화하고 있는것 같습니다. 조만간 한번 다뤄봐야겠네요 😉)

위 방식으로 프로젝트 생성하면 아래와 같은 코드를 만들어줍니다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Compose_practiceTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Greeting("Android")
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

setContent함수는 UI를 그리는 함수인것 같고 Surface는 background를 정의하는 컨테이너라고 주석으로 작성되어 있네요. Surface함수 안에 Greeting 함수를 보면 @Composable어노테이션이 달린 것을 볼 수 있습니다.
@Composable 어노테이션을 사용하면 Compose에서 UI를 그리는데 활용하는 함수로써 동작하게 됩니다.

SetContent안에 있는 Compose_practiceTheme이 무엇인지 찾아보니

프로젝트 구조가 왼쪽과 같이 되어있고 기본적으로 ui/theme 디렉토리가 생성되어 있었습니다.
프로젝트명이 Compose_practice 이므로 커스텀 테마가 자동으로 생성되어 있는걸 확인할 수 있었어요. 이외에도 color나 shape에 대해 각종 값들이 정의되어 있는데 이전에 xml방식에서는 res 폴더 안에 xml로 정의되었던 것들이 코틀린 코드로 정의되어 사용된다는 차이점이 있는것 같습니다!

무엇보다 가장 신기했던건

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    Compose_practiceTheme {
        Greeting("kingkingasdf 아랄랄랄ㄹ라")
    }
}

처럼 @Preview 어노테이션을 달고 화면구성함수를 짜게 되면 Run configuration에서 preview로 화면을 빌드할 수 있는데 코드를 변경할 때 마다 실시간으로 휴대폰화면에 변화가 반영되는것이 너무 좋았습니다.

실시간으로 Preview로 화면을 보면서 UI 구성을 빠르게 할 수 있다는게 정말 큰 장점으로 다가왔어요. (xml로 했을 때는 화면 렌더링이 느려서 속터졌던 적이 한두번이 아니었던거 같은데;;)

이제부터 Preview를 기준으로 레이아웃을 구성해보겠습니다.

레이아웃 구성

data class Message(val author: String, val body: String)

@Composable
fun MessageCard(msg: Message) {
    Text(text = msg.author)
    Text(text = msg.body)
}


@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    Compose_practiceTheme {
        MessageCard(
            msg = Message("Colleague", "Hey, take a look at Jetpack Compose, it's great!")
        )
    }
}

MessageCard함수로 Text 뷰를 2개 띄운 예제입니다. 기존 xml에서는 기본적인 구조가 정의되기 때문에 자동으로 TextView가 서로 겹치지 않고 바로옆에 붙어서 출력됐지만 Compose에서는 구조가 정의되지 않아서 Text 뷰가 겹쳐 나오게 됩니다.!

따라서 Compose에서 레이아웃을 구성하기 위해서는 구성요소간 구조를 Column과 Row로 정의해줄 필요가 있습니다.

@Composable
fun MessageCard(msg: Message) {
    Column{
        Text(text = msg.author)
        Text(text = msg.body)
    }
}

Coposable 부분을 Column으로 감싸주기만 하면 세로로 Text 뷰가 정렬되어 나오게 됩니다.

Modifier

Column과 Row를 사용하여 조금 더 복잡한 레이아웃을 만들어보겠습니다.

@Composable
fun MessageCard(msg: Message) {
    Row{
        Image(
            painter = painterResource(R.drawable.ic_launcher_background),
            contentDescription = "Contact profile picture",
        )

        Column{
            Text(text = msg.author)
            Text(text = msg.body)
        }
    }

}

Row와 Column을 계층적으로 쌓아 마치 LinearLayout 2 개를 중첩시킨 것과 같은 레이아웃을 만들 수 있습니다.

이제 Text나 Image를 좀 더 커스텀할 수 있는 방법을 알아보겠습니다.
이미지의 크기나 모양을 바꾸고싶다면 Modifier라는 수정자 클래스를 사용해야 합니다.

@Composable
fun MessageCard(msg: Message) {
    Row{
        Image(
            painter = painterResource(R.drawable.darong),
            contentDescription = "Contact profile picture",
            modifier = Modifier
                // Set image size to 40 dp
                .size(40.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape)
        )

        // Add a horizontal space between the image and the column
        Spacer(modifier = Modifier.width(8.dp))

        Column{
            Text(text = msg.author)
            Text(text = msg.body)
        }
    }

}

Modifier를 사용하면 동작을 정의하거나 모양을 바꾸는 등 다양한 일을 할 수 있는데요 이는 마치 xml디자인을 할 때 <ImageView> 태그 안에 width height padding 과 같은 다양한 속성을 지정해주는 작업과 유사합니다.

Modifier에는 더욱 더 많은 기능이 있는데

  • 애니메이션
  • 클릭이벤트
  • 정렬
  • 패딩
  • 그래픽 그리기

등의 기능이 있으므로 공식문서를 참고하여 다양한 기능을 구성하는데 활용할 수 있습니다.

Spacer의 경우 공간을 띄워주는 역할을 합니다.

이상으로 Compose가 무엇이고 어떻게 동작하는지 간단하게 알아보았습니다. 더 디테일하고 다양한 기능을 가지는 레이아웃을 그리려면 Modifier나 다양한 함수와 클래스에 대해 더 알아야 하므로 앞으로 천천히 하나씩 포스팅 해나갈 예정입니다.

profile
안했으면 빨리 백준하나 풀고자.

0개의 댓글