Beeeam

명령형 vs 선언형, Jetpack Compose 본문

Android

명령형 vs 선언형, Jetpack Compose

Beamjun 2024. 2. 4. 03:53

최근에 진행한 프로젝트는 Jetpack Compose 를 사용하여 진행했는데 여태까지 사용했던 방식에 비해서 큰 장점을 가지고 있는 것을 느꼈습니다. 그래서 공부하던 중 이전의 방식과 비교를 하여 각 방식의 장단점을 알아보고 추가로 Compose 맛보기를 하려고 합니다.

안드로이드 개발을 할 때 이전까지는 UI를 xml 파일에 만들고 동작을 Activity나 Fragment에 정의하였습니다. 이러한 방식을 명령형 UI 라고 합니다. 그리고 Jetpack Compose는 선언형 UI 라고 합니다. 이 둘의 차이점을 알려면 먼저 명령형 프로그래밍과 선언형 프로그래밍의 차이를 알아야 합니다.

명령형 프로그래밍

명령형 프로그래밍을 위키백과에서는 다음과 같이 설명하고 있습니다.

선언형 프로그래밍과 반대되는 개념으로, 프로그래밍의 상태와 상태를 변경시키는 구문의 관점에서 연산을 설명하는 프로그래밍 패러다임의 일종이다. 자연 언어에서의 명령법이 어떤 동작을 할 것인지를 명령으로 표현하듯이, 명령형 프로그램은 컴퓨터가 수행할 명령들을 순서대로 써 놓은 것이다.

 

명령형 프로그래밍은 어떻게(How)에 관점을 두고 프로그래밍을 하는 것입니다.

ex) 택시를 타고 집에 가는 상황

기사님 100m 직진 후 사거리에서 우회전하고 500m 직진하고 삼거리에서 좌회전하고 …

코드로 예시를 들면 다음과 같습니다.

// 인자로 받은 리스트의 요소에 1씩 더하는 함수

fun imparativeFunction(list: MutableList<Int>) {
    for (i in 0 until list.size) {
        list[i] = list[i] + 1
    }
}

위처럼 목표를 이루기 위해 어떻게 동작해야 하는지 과정을 자세히 설명하는 것을 명령형 프로그래밍이라고 할 수 있습니다.

(전 개인적으로 아직 이런 방식으로 코딩하는게 익숙한거 같습니다… ㅎㅎ)

선언형 프로그래밍

선언형 프로그래밍은 위키백과에서 다음과 같이 설명하고 있습니다.

선언형 프로그래밍은 두 가지 뜻으로 통용되고 있다.

한 정의에 따르면, 프로그램이 어떤 방법으로 해야 하는지를 나타내기보다 무엇과 같은지를 설명하는 경우에 "선언형"이라고 한다. 예를 들어, 웹 페이지는 선언형인데 웹페이지는 제목, 글꼴, 본문, 그림과 같이 "무엇"이 나타나야하는지를 묘사하는 것이지 "어떤 방법으로" 컴퓨터 화면에 페이지를 나타내야 하는지를 묘사하는 것이 아니기 때문이다. 이것은 전통적인 포트란과 C, 자바와 같은 명령형 프로그래밍 언어와는 다른 접근방식인데, 명령형 프로그래밍 언어는 프로그래머가 실행될 알고리즘을 명시해주어야 하는 것이다. 간단히 말하여, 명령형 프로그램은 알고리즘을 명시하고 목표는 명시하지 않는 데 반해 선언형 프로그램은 목표를 명시하고 알고리즘을 명시하지 않는 것이다.

또 다른 정의에 따르면, 프로그램이 함수형 프로그래밍 언어, 논리형 프로그래밍 언어, 혹은 제한형 프로그래밍 언어로 쓰인 경우에 "선언형"이라고 한다. 여기서 "선언형 언어"라는 것은 명령형 언어와 대비되는 이런 프로그래밍 언어들을 통칭하는 것이다.

요약하자면 무엇(What) 즉 목표에 관점을 두고 프로그래밍 하는 것 또는 명령형과 대비되는 개념이라는 것입니다.

ex)

기사님 XXX번지로 가주세요~
// 인자로 받은 리스트의 요소에 1씩 더하는 함수

fun declarativeFunction(list: MutableList<Int>): List<Int> {
    return list.map { it + 1 }
}

명령형 프로그래밍과 다르게 선언형 프로그래밍은 무엇(What)을 할 것인지에 집중하는 것입니다.

요약하자면 명령형은 무엇을 어떻게 할 것인가에 초점을 맞추는 것이고 선언형은 무엇을 할 것인가에 초점을 맞추는 것입니다.

그런데 선언형 프로그래밍을 하기 위해서는 전제 조건이 필요합니다. 바로 추상화입니다.

명령형의 추상화

선언형 프로그래밍의 예시를 보면 무엇을 할지만 띡 말했는데 이걸 어떻게 하는 것인가라는 생각이 들 수 있습니다. 이런 생각의 답은 명령형의 추상화입니다.

위에서 들었던 예시들을 기준으로 설명하겠습니다.

택시 기사님이 주소만 말했는데 어떻게 갈 수 있는 걸까요? → 기사님한테 내비게이션이 있다는 가정이 있는 것입니다.
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
    for (item in this)
        destination.add(transform(item))
    return destination
}

예시 코드의 map 함수는 위와 같이 정의 되어 있습니다. map 함수 내의 mapTo 함수에서 리스트의 각 요소를 돌면서 리스트의 요소를 람다의 동작을 통해 변경하는 것을 확인할 수 있습니다. 이런 과정은 명령형 프로그래밍에서 정의했던 과정과 동일합니다.

그래서 선언형 프로그래밍을 하기 위해서는 어떻게 할 것인지에 대한 부분이 추상화 되어 있어야 합니다.

명령형 UI

이름처럼 명령형 프로그래밍 기법으로 구현하는 UI 입니다. 어떻게 화면을 구성할 것인지에 초점이 맞춰져 있습니다.

ex)

binding.progressBar.isVisible = false
binding.text.setText = "Hello~"

// 프로그레스 바를 화면에 안보이게 설정하고
// 텍스트를 Hello~ 라고 설정해줘

명령형 UI는 UI의 변경을 UI 객체의 갱신을 통해서 처리합니다. 이 때문에 변수나 이벤트를 UI 객체와 연결해야 합니다.

(안드로이드에서는 findViewById() 나 setOnClickListener())

정리하자면 명령형 UI는 변수나 이벤트가 UI 객체들에 연결되어 있어 UI의 변경이 필요한 경우 위의 예시 코드 처럼 화면을 “어떻게 구성해줘”라는 명령에 따라 UI를 갱신합니다.

선언형 UI

선언형 UI는 어떤 화면을 그릴지에 초점이 맞춰져 있습니다.

Screen() {
	CircularProgress()
	Text("Hello~")
}

선언형 UI는 UI 전체를 다시 생성하여 UI의 변경을 처리합니다. 화면 전체를 다시 만들기 때문에 변수나 이벤트를 UI 객체와 연결할 필요가 없습니다.

Point

UI의 변경이 일어날 때마다 화면 전체를 다시 생성한다면 비효율적이지 않을까? 라는 생각을 할 수 있습니다. 굳이 변경할 필요 없는 부분까지 다시 그리는 것은 비효율적입니다. 하지만 이런 단점들은 프레임워크에서 다 해결해줍니다.

(Jetpack Compose에서는 Smart Recomposition을 통해서 상태가 바뀐 부분만 다시 그리는 방식을 사용하고 있습니다!)

장점

  1. 코드 간소화
  2. Hot-Reload / Preview

Jetpack Compose

Jetpack Compose 공식 사이트에서 다음과 같이 설명하고 있습니다.

Jetpack Compose는 네이티브 UI를 빌드하기 위한 Android의 최신 권장 도구 키트입니다. Jetpack Compose는 Android에서의 UI 개발을 간소화하고 가속화합니다. 간단한 코드, 강력한 도구, 직관적인 Kotlin API를 사용하여 앱을 빠르고 생동감 있게 구현하세요.

특징

  • 간단한 코드
  • 직관적인 API
  • 빠른 개발 과정
  • 강력한 성능

적용 예시

이전의 방식에 비해서 Compose를 사용하면 코드를 간소화 할 수 있다는 것을 확인할 수 있습니다.

LazyColumn

위와 같은 뷰를 구현하기 위해서 이전에는 아이템의 뷰, adapter, viewHolder를 정의해야 했습니다. 하지만 Compose에서는 LazyColumn을 사용하면 간단하게 구현할 수 있습니다.

Preview

이전의 방식에서는 화면이 어떻게 그려지는지 확인하는 과정이 번거로웠습니다. 이전에 진행했던 프로젝트에서 크게 느낀 것인데 매번 작업 중인 화면까지 이동해서 테스트를 해야했습니다. 하지만 Compose에서는 Preview 기능을 지원하는데 이로 인해 테스트를 바로 해볼 수 있게 되었고 이로 인해 작업 속도가 더 빨라졌슴을 느낄 수 있었습니다.

'Android' 카테고리의 다른 글

Bottom Navigation in Multi Module with deeplink  (0) 2024.03.26
MVVM ViewModel vs AAC ViewModel  (0) 2024.02.15
MVI  (0) 2024.01.24
LazyColumn  (1) 2024.01.23
컴포즈 내비게이션  (2) 2023.12.26