본문 바로가기

기타/안드로이드

Empty Compose Activity - Activity, Composable 함수, Preview 함수

Empty Compose Activity - Activity, Composable 함수, Preview 함수

저번에 Empty Compose Activity 템플릿을 활용해 만든 첫번째 프로젝트를 살펴보면서

안드로이드와 Jetpack Compose의 가장 기본적인 개념인

Activity와 Compose 함수, Preview 함수에 대해서 같이 공부해보자

 

개요

나는 공부를 할 때 최신기술에 대해 거부감을 가지고 있는데

안드로이드 개발에 있어서 Kotlin과 Compose가 바로 그 최신기술의 위치를 차지하고 있다

(상대적으로 최신이라는 뜻. 몇 년 되긴 했음.)

과거의 기술이 되어가는 Java와 xml을 배우고 싶다는 마음을 떨쳐내고 한 번 도전해보기로 했다

 

일단 이름을 짚어보고 넘어가자

Compose는 Jetpack이라는 라이브러리의 한 항목으로써 UI를 구성하는 방식을 지원한다

그러니까 Compose는 Jetpack의 일부이고

그 중에서도 UI, 화면을 디자인하는 기능을 지원한다는 뜻이다

 

기본 코드 이해

개요

우선 저번에 만들었던 프로젝트를 확인해보자

Empty Compose Activity 라는 템플릿을 이용해서 프로젝트를 생성하면 다음와 같은 코드를 볼 수 있다

package com.example.myfirstcomposeapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.myfirstcomposeapp.ui.theme.MyFirstComposeAppTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyFirstComposeAppTheme {
                // 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!")
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    MyFirstComposeAppTheme {
        Greeting("Android")
    }
}

 

onCreate는 일단은 이 코드의 main 함수라고만 생각하면 되고

setContent는 Compose를 사용하는(즉 UI를 구성하는) 함수들을 호출할 수 있는 영역이다

ComposeAppTheme은 지금은 몰라도 되고

Surface는 컨테이너라고 그냥 UI상에서의 상자라고 생각하면 되겠다

modifier는 컨테이너의 너비 등 UI 관련 속성을 조절하는 인자이다

여기에선 fillMaxSize() 즉 화면의 최대 크기로 확대했다

 MaterialTheme도 지금은 몰라도 된다

 

Composable 함수

그 안에 있는 Greeting이라는 함수는 밑에 보면 정의가 있다

@Composable이라는 annotation이 앞에 있으면서 pascal style인 함수이다

이런 함수를 Composable 함수라고 한다

Composable 함수는 Composable을 만들어주는데,

Composable은 UI상에 나타나는 하나의 요소라고 생각하면 된다

예를 들어 글씨, 그림 등이 있다

Composable 함수는 setContent나 같은 Composable 함수 내에서만 호출가능하다

아까 setContent는 Compose를 사용하는(UI를 구성하는) 함수들을 호출할 수 있는 영역이라고 했는데

바로 그 Compose를 사용하는(UI를 구성하는) 함수라는게 바로 Composable 함수인 것이다

사실 setContent가 가장 최상위의 Composable, 즉 Root Composable이다.

 

Greeting 함수의 내용을 보면 Text라는 Composable을 품고 있다

이 Text라는 Composable은 말 그대로 파워포인트 같은데서 볼 수 있는 텍스트 상자이다

Greeting 함수가 name을 매개변수로 받아서 Text composable의 text 인자로 "Hello $name"을 넘겨준다

정리하자면 Greeting Composable은 "Hello  $name"이라는 텍스트 상자를 품고 있는 상자이다.

 

Preview 함수

그 아래에는 @Preview라는 주석이 달린 DefaultPreview 함수가 있다

ComposeAppTheme 역시 지금은 몰라도 된다

이 함수는 안에서 Greeting 함수를 호출하고 있다

안드로이드 앱은 빌드를 해서 실행을 시키면 내가 컴퓨터에 연결한 안드로이드 기기 또는

안드로이드 스튜디오에 등록한 가상 기기에서 실행된다

그런데 예를 들어 카카오톡 같은 규모가 있는 어플을 만들었는데

글자 한 줄 바꾸고 변경된 모습을 확인한다고 다시 빌드를 하고 실행을 시킨다면 시간낭비가 너무 크다

 

그럴 때 Preview라는 기능을 이용해서 변경된 일부분만 확인이 가능하다

DefaultPreview라는 Preview 함수는 Greeting이 어떤 식으로 바뀌는 지 실시간으로 보여주는 기능을 하는 것이다

Preview 함수 이름 옆에 휴대폰에 초록색 화살표가 있는 기호를 클릭하면 Preview 함수를 실행할 수 있고

split이나 design 탭을 클릭해 Preview 함수가 보여주는 앱의 일부분의 실행결과를 볼 수 있다

 

 

기본 코드 발전시키기

여기까지 이해가 됐다면 이번엔 코드를 다음과 같이 바꿔보자

package com.example.composeapp
 
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.composeapp.ui.theme.ComposeAppTheme
 
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeAppTheme {
                // A surface container using the 'background' color from the theme
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
                    Greeting("게으른 컴공생")
                }
            }
        }
    }
}
 
@Composable
fun Greeting(name: String) {
    Surface(color = Color.Blue) {
        Text(text = "Hello $name!", Modifier.padding(24.dp))
    }
}
 
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeAppTheme {
        Greeting("게으른 컴공생")
    }
}

우선 Preview 함수와 setContent 함수 내에서 호출할 때 넘겨주는 인자를 블로그의 이름으로 바꿨다

이를 제외하면 바뀐 부분은 Greeting 함수 내부에만 있다

 

첫째로 Surface라는 겉 상자 Composable을 추가해줬다 그리고 상자의 색은 파란색으로 바꿔줬다

setContent의 Surface가 Modifier.fillMaxSize()를 통해 전체화면을 차지하고 있기 때문에

그 밑의 Greeting과 Surface도 현재 전체화면인 상태이다

따라서 전체화면이 퍼렇게 변할 것이다

참고로

Text(text = "Hello $name!", Modifier.padding(24.dp))

라고 적힌 행을 전체 선택하고

Alt + Enter나 옆에 있는 전구버튼을 누르면 여러 옵션을 볼 수 있는데 surround with containers 항목을 선택해주면

Surface Composable의 코드를 쉽게 추가할 수 있다

 

Text Composable 함수에는 setContent 내부의 Surface처럼 Modifier를 넘겨줬다

이 modifier는 UI관련속성을 변경할 수 있는 인자라고 위에서 잠깐 설명했었다

이 친구는 역할답게 모든 Composable들이 인자로 가진다고 생각하면 되겠다

padding은 html을 배워본 사람이면 어떤 영역인지 알 수 있겠고

dp와 sp는 상대적 크기와 절대적 크기의 단위라고 생각하면 된다

상대적 크기는 화면의 크기가 변했을 때 알아서 비율에 맞게 조절이 된다

따라서 24.dp는 24만큼의 화면비율을 차지하는 크기이다

 

마지막으로 위 코드를 작성하다보면 빨간색 글씨로 뜨는 코드들이 있을 것이다

예를 들면 padding, Color 등이 있는데 이들은 import가 안되서 그런 것이니 해당 단어를 선택하고

Alt + Enter를 눌러 뜨는 옵션에서 import를 선택해주자

그러면 코드 위쪽에 알아서 import가 되고 사용할 수 있게 된다

 

결과화면