본문 바로가기

안드로이드 Android

안드로이드 개발 (7) Compose 를 사용하는 이유

안녕하세요 Loner입니다. 

구글 IO 2018에서 처음 Compose가 공개 되었고, 3년 동안 제작기간을 거친 Compose는 현재 Beta 버전 입니다.

Compose는 Kotlin으로 제작되는 라이브러리 이며 선언형 프로그래밍 방식으로 UI를 그립니다. 

 

하지만 오랫동안 ui를 xml에 익숙한 안드로이드 개발자는

왜 compose라는 새로운 UI Tool를 만드는지 의아해 할것입니다.

 

1. 기존 Android UI 제작 특징

UI의 속성같은 경우

Xml에다가 UI 속성을 정의를 하는경우가 있고,

Class에서 프로그래밍으로 정의를 하는 경우가 있습니다.

 

android:text="Hello World"

 

textView.text = "Hello World!"

두개의 파일로 어디서든지 속성을 정의할 수 있습니다.

 

안드로이드는 기본적으로 Xml를 통해서 ui만든 다음에 

class(Activity or Fragment or Dialog 등등)에서 ui를 컨트롤 합니다.

 

xml의 ui들을 클래스에서 사용할 셋팅이 필요합니다.

(findViewById, ViewBinding,DataBinidng)

 

셋팅 후 액티비티에서 ui를 어떻게 컨트롤 할지 정의를 해야합니다. 

 

이 과정에서 불필요한 반복 코드 (보일러 플레이트 코드 )가 매우 많이 생성되고 

코드 작성시 내가 의도하지 않는 UI를 만들거나 실수로 UI를 잘못 정의하는 경우가 있습니다.

 

그래서 xml로 작업하고 액티비티에서 컨트롤 하는 작업은 ui 생산속도의 저하를 일으킵니다.

 

그리고 

다른 작업자가 내 코드를 보거나 오랜시간이 지나서 다시 유지보수를 하는일이 생기면

그 작업자는 xml과 class를 오가며 살펴봐야 하는경우가 생기는 일부터 불편해집니다.

(xml의 id를 살펴보고 class 에서 사용한 변수명을 체크하는 경우 등등..)

 

무엇보다 가장 큰 이유는 기존 명령형 UI 제작 방식은 개발자가 직접 set,get를 사용해야해서

내부 동작까지 모든걸 만들어야하는 과정이 있고 사람이 직접 로직을 만들기 때문에 그로인해 작은 실수들이

발생하여 버그 및 불필요한 작업 시간이 매우 소요 됩니다. 

 

위와 같은 불편함을 해결 해줄 새로운 UI 제작 방식이 바로 Compose 인것 입니다. 

 

참고 기사 

http://www.codingworldnews.com/news/articleView.html?idxno=1457 

 

구글, ‘젯팩 컴포즈’ 공개…안드로이드 코딩 속도 빨라진다 - 코딩월드뉴스

구글이 안드로이드 코딩 속도를 향상시킬 수 있는 개발 툴인 젯팩 컴포즈(Jetpack Compose)를 공개했다. 앱의 UI 생성 과정이 간소화돼, 개발자들의 안드로이드 앱 개발 속도가 이전보다 더욱 빨라질

www.codingworldnews.com

 

Compose는 Kotlin으로 제작이 되었기 때문의 코틀린의 특징을 이용해서 

선언형 프로그래밍으로 UI를 만듭니다. 

 

선언형 프로그래밍은 아주 심플한 정의를 내려본다면

컴파일러에게 UI를 이렇게 저렇게 그려라 선언을 해서 만드는 방식 입니다.

 

기존에 UI를 만드는 방식은 

findViewById()와 같은 함수를 사용하여 트리를 탐색하고 

button.setText(String), container.addChild(View) 또는

img.setImageBitmap(Bitmap)과 같은 메서드를 호출하여 노드를 변경 했었습니다.

이러한 함수는 위젯의 내부 상태를 변경합니다.

 

위와 같은 방식은 실수를 범하기 쉽고, 개발자가 직접 어떻게 구현할지

적어줘야하기 때문에 신경써야할 부분이 매우 많습니다.

Typeface face = Typeface.createFromAsset(getAssets(),
            "fonts/epimodem.ttf");
textView.text = "hello"
textView.setTypeface(face)

 

선언형 프로그래밍은

"헬로우 월드 텍스트 적어줘!" 라는 식의 말을 하듯이 선언을 합니다. 

구현 방법은 신경쓰지 않고 무엇을 만들지 명령을 내리는 방식입니다. 

 

//글자 "hello Word "
Text("hello Word")

 

구현 방법은 적지 않고

만드라는 명령만 내리기 때문에 훨신 직관적인 문법으로 작성됩니다. 

UI의 상태는 패러미터안에서 지정할 수 있습니다.

 Text(
       text = "A day wandering through the sandhills " +
            "in Shark Fin Cove, and a few of the " +
            "sights I saw",
       style = typography.h6,
       maxLines = 2,
       overflow = TextOverflow.Ellipsis
 )

 

Compose 심플한 가이드 

Compose에 관해 자세한 내용은 다음 포스팅에서 이어질 예정입니다. 

 

Compose 에 대해 다시 설명을 하자면 

1) Compose는 Kotlin으로 제작된 UI 제작 도구

2) Compose는 불필요한 보일러플레이트 코드가 줄어듬

3) Compose는 직관적인 코드로 UI를 만들 수 있음 

4) Class 에서 실시간 미리보기 지원 

 

결론)

1~4번 특징 때문에 버그가 일어날 확률도 줄고 적은 코드로 UI 구현이

가능해서 생산성이 빨라지고 유지보수하기 쉬움 

 

미리 맛보기로 간단한 튜토리얼을 진행해보겠습니다. 

 

 

다운을 받아서 아래와 같이 그레들리를 설정해줍시다. 

 buildFeatures {
        // Enables Jetpack Compose for this module
        compose true
    }

그레들리에 위 코드를 추가해줍시다.

아래는 그레들리 전체 모습 

android {
    defaultConfig {
        ...
        minSdkVersion 21
    }

    buildFeatures {
        // Enables Jetpack Compose for this module
        compose true
    }
    ...

    // Set both the Java and Kotlin compilers to target Java 8.

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }

    composeOptions {
        kotlinCompilerExtensionVersion '1.0.0-beta07'
    }
}

그 다음 아래와 같이 dependencies를 설정해줍시다.

dependencies {
    implementation 'androidx.compose.ui:ui:1.0.0-beta07'
    // Tooling support (Previews, etc.)
    implementation 'androidx.compose.ui:ui-tooling:1.0.0-beta07'
    // Foundation (Border, Background, Box, Image, Scroll, shapes, animations, etc.)
    implementation 'androidx.compose.foundation:foundation:1.0.0-beta07'
    // Material Design
    implementation 'androidx.compose.material:material:1.0.0-beta07'
    // Material design icons
    implementation 'androidx.compose.material:material-icons-core:1.0.0-beta07'
    implementation 'androidx.compose.material:material-icons-extended:1.0.0-beta07'
    // Integration with activities
    implementation 'androidx.activity:activity-compose:1.3.0-alpha08'
    // Integration with ViewModels
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha05'
    // Integration with observables
    implementation 'androidx.compose.runtime:runtime-livedata:1.0.0-beta07'
    implementation 'androidx.compose.runtime:runtime-rxjava2:1.0.0-beta07'

    // UI Tests
    androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.0.0-beta07'
}

 

시작 

1) setContentView() 를 제거해줍시다.

2) xml를 제거해줍시다. 

 

setContent를 통해서 사용 

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
           Text(text = "helloWorld")
        }
    }
   }

- 앱을 실행 해보면 텍스트가 하나만 생성되어있는걸 볼 수 있습니다.

 

@Composable 를 사용하면 해당 함수 안에서

setContent()에서 사용할 함수를 만들 수 있습니다.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TextCreate()
        }
    }

    @Composable
    private fun TextCreate() {
        Text(text = "helloWorld")
    }
 }

 

만드려는 UI를 미리 보고자한다면  @Composable 위에 @Preview 를 사용하면 됩니다.

 Class 에서 미리 보기가 가능합니다.

 

아래와 같이 사용 가능합니다. 

 

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NewStory()
        }
    }
    
    @Preview
    @Composable
    fun NewStory() {

        MaterialTheme {
            val typography = MaterialTheme.typography
            Column(
                modifier = Modifier.padding(16.dp)
            ) {
                Image(
                    painter = painterResource(id = R.drawable.header),
                    contentDescription = null,
                    modifier = Modifier
                        .height(180.dp)
                        .fillMaxWidth()
                        .clip(shape = RoundedCornerShape(4.dp)),
                    contentScale = ContentScale.Crop
                )
                Spacer(modifier = Modifier.height(16.dp))

                Text(
                    text = "A day wandering through the sandhills " +
                            "in Shark Fin Cove, and a few of the " +
                            "sights I saw",
                    style = typography.h6,
                    maxLines = 2,
                    overflow = TextOverflow.Ellipsis
                )
                Text(
                    text = "Davenport, California",
                    style = typography.body2
                )
                Text(
                    text = "December 2018",
                    style = typography.body2
                )
            }
        }

    }

}

MaterialTheme머티리얼 디자인 원칙을 쉽게 적용하도록 해줍니다. 

 

Column 은 레이아웃 입니다.

리니어레이아웃의 수직 방향 처럼 

위에서 하나씩 만들어줍니다. Column의 패러미터로 레이아웃 속성을 정의 할 수 있습니다.(ex:Padding 16dp 적용)

 

레이아웃의 속성을 정의하려면 Modifier를 사용해야하는데 Modifier는 다른 포스팅에서 자세히 적도록 하겠습니다.

 

이어서 Column 안에 사용할 ui요소들을 넣어주면 됩니다. 뷰의 속성도 마찬가지로 모두 파라미터로 지정해주면 끝입니다. 

 

이런식으로 Class 에서 미리 만들어질 UI를 확인하면서 작성해나갈 수 있습니다.

불필요한 코드도 없고 순서대로

전체 테마 -> 레이아웃(속성) -> 레이아웃안의 UI요소들(속성들)  작성하면서

오른쪽 미리보기와 같이 생성이 되었고

도중에 내가 원하는 값이 아닌 것을 적는다면

미리보기로 미리 확인을 가능해서 수정할 부분을 찾을 수 있었습니다.

 

저는 주로 DataBinding을 통해서 View를 만들어왔었지만,

앞으로 과감하게 엄청난 생산성을 가지는 Compose 를 주로 사용할 생각입니다. 

 

안드로이드 팀이 좋은 UI 제작 도구를 만들어줘서 고맙네요