Kotlin

[Kotlin] 코틀린 기초 4 - Jetpack Compose와 기본적인 UI

도우 2024. 4. 4. 21:15
728x90

 

 

1. XML과 Jetpack Compose

Jetpack Compose는 기본 Android 어플리케이션을 빌드하기 위한 현대적이고 완전히 선언적인 UI 도구 키트이다. Kotlin 프로그래밍 언어 기능을 사용하여 Android에서 UI 개발을 단순화하고 가속화한다.

  • 선언적 UI : Jetpack Compose 에서 UI는 선언적으로 정의된다. UI의 모양과 기능을 설명하면 프레임워크가 UI 렌더링과 시간 경과에 따른 UI 변경 관리를 담당한다.
  • Kotlin 기반 : Kotlin을 기반으로 하는 Jetpack Compose는 강력하고 간결하며 표현력이 풍부한 구문을 허용하여 코드를 더 읽기 쉽고 작성하기 쉽게 한다

반면 XML은 전통적으로 Android에서 UI 레이아웃을 디자인하는 데 사용되었다.

XML은 UI 구성 요소와 레이아웃이 구조적이고 계층적인 방식으로 정의되는 마크업 언어이다.

  • 관심사 분리 : XML을 사용하면 UI 디자인과 어플리케이션 로직을 명확하게 분리할 수 있다. UI는 XML 파일로 정의되고 동작은 Kotlin 또는 Java 코드로 구현된다.
  • 정적 레이아웃 : XML 레이아웃은 더 정적이며 UI 변경 및 사용자 상호 작용을 관리하기 위해 더 많은 상용구 코드가 필요하다.

 

 

2. Android 개발 맥락에서의 UI

Android 개발 맥락에서 UI 또는 사용자 인터페이스는 사용자가 애플리케이션을 사용할 때 접하게 되는 시각적 요소와 상호 작용을 나타낸다. 이는 어플리케이션을 효과적으로 사용하기 위해 화면, 페이지, 버튼, 아이콘, 텍스트 필드 및 기타 시각적요소와 같이 상호 작용할 수 있는 모든 것을 포함한다

  • 시각적 구성 요소 : UI에는 어플리케이션의 모양을 구성하는 다양한 시각적 구성 요소가 포함된다. 여기에는 사용자가 보고 상호 작용하는 버튼, 텍스트 필드, 이미지, 슬라이더 및 기타 요소가 포함될 수 있다.
  • 레이아웃 및 구조 : UI에는 사용자 친화적이고 직관적인 방식으로 시각적 구성 요소를 구성하는 작업이 포함된다. 여기에는 요소의 배열, 크기, 색상, 위치가 포함되어 전반적인 사용자 경험에 기여한다
  • 상호작용성 : UI에는 사용자 입력에 응답하고, 다양한 화면 간을 탐색하고, 사용자 작업에 피드백을 제공하는 등 어플리케이션의 대화형 측면도 포함된다. 이를 통해 어플리케이션이 반응성이 뛰어나고 사용자 친화적이라는 것을 보장한다.

 

 

3. Jetpack Compose에서의 Composable

“컴포저블(Composable)”이란 UI 구성 요소를 선언적으로 생성하기 위해 사용되는 함수를 말한다.

Jetpack Compose는 안드로이드의 최신 UI 개발 툴킷으로, 코틀린 기반의 선언적 UI 패러다임을 사용하여 앱의 UI를 더 직관적이고 간결하게 구성할 수 있게 해준다.

컴포저블 함수를 통해 개발자는 UI의 모양, 느낌, 동작을 정의할 수 있으며, 이러한 컴포저블들은 재사용 가능한 UI 구성 요소로 사용될 수 있다.

Composable 함수의 기본 구조는 다음과 같다.

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

Composable은 주석이 달린 Kotlin 함수이다. @Composable 버튼이나 텍스트 필드와 같은 단일 UI 요소부터 전체 화면이나 그 일부에 이르기까지 무엇이든 정의할 수 있다.

또한 Composable은 함께 구성될 수 있다. 즉, 하나의 Composable을 다른 컴포저블 안에 사용하여 계층적이고 체계적인 UI를 구성할 수 있다.

Composable 함수의 특징을 정리하자면 다음과 같다

  • 선언적 UI
  • 재사용성
  • 조합성
  • 리액티브 프로그래밍 ⇒ 데이터의 상태 변화에 따라 UI를 자동으로 갱신 ( State, MutableState 객체를 통해 상태관리)

 

 

Composable 만들기

자신만의 Composable을 만들면 재사용 가능한 모듈식 코드가 가능해진다.

  1. 함수 정의 : Kotlin의 @Composable 함수를 정의한다.
  2. UI 요소 추가 : 함수 내부에 Text(), Button() 등의 사전 정의된 구성 가능한 함수나 기타 맞춤 Composable을 추가한다.
  3. 맞춤 설정을 위한 매개변수 : 구성하고자 하는 상황에 맞추어 매개변수를 사용한다.
  4. 함께 작성 : 다른 Composable내에서 맞춤 Composable을 사용할 수 있다.

아래의 예시는 CustomText 특정 스타일이 적용된 텍스트 문자열을 표시하는 맞춤 Composable이다. 그런 다음 다른 컴포저블인 내부에서 사용되어 구성 가능성과 재사용성을 보여준다.

// CustomText composable을 사용한 예시
@Composable
fun MyApp() {
    Column {
        CustomText(text = "Hello, World!")
        CustomText(text = "Welcome to Jetpack Compose!")
    }
}

 

Jetpack Compose : Column (열)

Column을 사용하여 항목을 수직으로 아래에 배치할 수 있다.

@Composable
fun MyColumn() {
    Column {
        Text("First item")
        Text("Second item")
        Text("Third item")
    }
}

 

Column의 Modifier 속성

Modifier는 열, 행, 버튼과 같은 앱 요소의 모양과 동작을 설정한다.

@Composable
fun CustomColumn() {
    Column(
        modifier = Modifier.fillMaxSize(), 
        // 전체 화면을 차지
        verticalArrangement = Arrangement.Center, 
        // 항목을 세로로 가운데에 배치
        horizontalAlignment = Alignment.CenterHorizontally 
				// 항목을 가로로 가운대에 배치
     ) {
        Text("Item 1")
        Text("Item 2")
        Text("Item 3")
     }      
}

간단하게 정리하면 다음과 같다

  • Modifier : 요소의 스타일을 지정하고 정렬하는 도구
  • .fillMaxSize : 최대한 크게 만들기
  • verticalArragnement (수직 배열) : 항목의 상하 위치를 결정
  • horizontalAlignment (수평 정렬) : 항목의 왼쪽 및 오른쪽 위치를 결정

 

Jetpack Compose : Row (행)

Row를 사용하면 항목을 수평으로 나란히 배치할 수 있다.

@Composable
fun MyRow() {
    Row {
        Text("First item")
        Text("Second item")
        Text("Third item")
    }
}

 

 

4. Jetpack Composable의 Text Composable

Text Composable은 사용자가 텍스트를 입력하거나 표시할 수 있는 사용자 인터페이스의 일부이다.

사용자는 텍스트를 입력할 수 있지만 현재로서는 기억되거나 사용되지 않는다.

 

Jetpack Compose : TextField

TextField는 사용자가 내용을 입력할 수 있는 텍스트 상자와 같다

@Composable
fun MyTextField() {
    TextField(
        value = "",
        onValueChange = {},
        label = { Text("Enter your name") }
    )
}

 

Jetpack Compose : BasicTextFeild

BasicTextField는 별도의 디자인이 필요 없는 단순한 텍스트 상자이다.

라벨이나 추가 디자인 없이 간단한 텍스트 상자가 만들어진다.

@Composable
fun MyBasicTextField() {
    BasicTextField(
        value = "",
        onValueChange = {}
    )
}

 

Jetpack Compose : OutlinedTextField

OutlinedTextField 주위에 윤곽선이 있는 텍스트 상자이다. label을 가질 수도 있다.

아래 코드는 “안녕하세요”라는 label이 있는 텍스트 상자가 생성된다.

@Composable
fun MyOutlinedTextField() {
    OutlinedTextField(
        value = "",
        onValueChange = {},
        label = { Text("안녕하세요") }
    )
}

 

onValueChange

onValueChange는 사용자 입력과 같은 이벤트가 발생할 때마다 호출되는 콜백 함수이다.

입력된 값이 변경될 때마다 호출되며, 새로운 값을 인자로 받는다.

예시)

텍스트 상자가 있고 입력된 문자를 다른 곳에 표시해보도록 하자.

@Composable
fun UserInputExample() {
    // 상태를 관리하기 위한 변수를 선언합니다. 초기값은 빈 문자열입니다.
    var textState by remember { mutableStateOf("") }

    Column(modifier = Modifier.padding(16.dp)) {
        // TextField 컴포넌트를 사용하여 사용자 입력을 받습니다.
        TextField(
            value = textState, // TextField의 현재 텍스트 값을 지정합니다.
            onValueChange = { newText ->
                // 사용자가 입력할 때마다 호출되며, textState를 새로운 값으로 업데이트합니다.
                textState = newText
            },
            label = { Text("Enter your name") } // 라벨을 표시합니다.
        )
        // 사용자가 입력한 텍스트를 표시하는 Text 컴포넌트입니다.
        Text(text = "Hello, $textState!")
    }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    UserInputExample()
}

 

실시간으로 바뀌는 UI

 

 

5. Composable Preview

Composable Preview는 휴대폰이나 에뮬레이터에서 전체 앱을 실행하지 않고도 앱 화면이나 Composable이 어떻게 보이는지 확인할 수 있는 기능이다.

아래의 MyButton이라는 버튼을 만들었을 때, @Preview 어노테이션 함수에 사용하면 앱을 실행하지 않고도 화면을 보고 확인할 수 있다.

@Composable
fun MyButton() {
    Button(onClick = {}) {
        Text("Click me")
    }
}
 
@Preview
@Composable
fun PreviewMyButton() {
    MyButton()
}

 

오른쪽에 보이는 것이 Preview이다

 

6. Context란?

Android에서 Context는 앱의 여러 부분을 시스템에 연결하는 다리와 같다.

어플리케이션의 현재 상태에 대해 알려주며, 앱의 리소스, 데이터베이스, 기타 시스템 서비스에 접근하도록 돕는다.

사용되는 주요 사용 사례는 다음과 같다

  • 리소스 접근 : 앱이 이미지, 색상, 문자열과 같은 리소스를 찾고 사용한다
  • 시스템 서비스 접근 : 위치 서비스, 알림 서비스 등에 접근할 수 있다.
  • 액티비티 시작
  • 퍼미션 요청
  • 브로드캐스트 리시버 등록 및 해제

 

Composable에서 Context 설정하는 방법

Jetpack Compose에서는 LocalContext 제공자를 사용하여 구성 가능한 함수 내에서 Context를 직접 가져올 수 있다.

 

예시)

Context를 사용하여 Toast 메세지를 표시하는 방법은 다음과 같다.

@Composable
fun ShowToastButton() {
    val context = LocalContext.current
 
    Button(onClick = {
        Toast.makeText(context, "Button clicked!", Toast.LENGTH_SHORT).show()
    }) {
        Text("Click me")
    }
}

LocalContext.current를 사용하여 현재 Composable 함수가 실행되고 있는 Context에 접근한다.

즉, 현재 Composable 함수가 실행되고 있는 Context를 가져올 수 있다.

이는 대체로 Activity의 Context와 동일하다.

 

 

7. Spacer와 Padding

  • Spacer : 버튼이나 텍스트와 같은 앱의 다양한 요소 사이의 빈 공간을 나타낸다.
  • 패딩 (Padding) : 패딩은 요소 테두리 내부의 공간이다. 요소의 콘텐츠와 가장사리 사이에 공간을 만든다.
// Padding
Text("Hello", modifier = Modifier.padding(16.dp))

// Spacer
Spacer(modifier = Modifier.height(16.dp))
728x90