xml에서 Compose로 넘어가며 UI를 그릴 때 가장 처음 마주하는(?) 부분이라고 느껴졌던 Modifier에 대해 정리해보려고 합니다
🎨 Modifier
1. Modifier란?
Modifier는 Compose에서 UI 컴포넌트를 변경하거나 꾸미기 위해 사용하는 데코레이터입니다.
Modifier는 다음과 같은 역할을 합니다
- UI 요소 설정 : Modifier를 사용해 UI 요소의 레이아웃, 스타일, 상호작용 등을 변경 가능
- 상호 작용 설정 (행동을 추가하기 위한 Modifier) : 클릭, 스크롤, 드래그, 확대/축소 등의 상호 작용을 설정 가능
- 구성 요소 조합 : 여러 Modifier를 연결해서 사용할 수 있어, 다양한 스타일을 조합 가능
주요 특징은
- 불변성 (Immutable) : Modifier는 불변 객체로 설계되어 있어, 동일한 Modifier를 여러 컴포넌트에 재사용해도 안전함
- 체이닝 : 여러 동작을 한 번에 연결하여 사용할 수 있음. 예를 들어, 패딩, 배경, 클릭 동작을 순차적으로 적용 가능
- 순서가 중요 : Modifier를 체인으로 연결할 때 적용 순서가 중요함. 먼저 정의된 Modifier가 먼저 적용됨
특징에 나와있는 것처럼 Modifier는 체인 형태로 연결할 수 있도록 설계되어 있는데요,
여기서 '체이닝 함수'란?
말 그대로 메소드들을 체인으로 엮듯이 위에서부터 엮어 호출되는 프로그래밍 패턴을 의미합니다
그렇기 때문에 Modifier는 순서가 굉장히 중요합니다 !
⛓️ Modifier의 체이닝
위에서 말한대로 Modifier는 순서가 굉장히 중요한데요, 예시를 통해 알아보겠습니다
첫 번째 예시
@Composable
fun CardView(/*...*/) {
val padding = 16.dp
Column(
Modifier
.clickable(onClick = onClick)
.padding(padding)
.fillMaxWidth()
) {
}
}
위 코드를 보면 clickable을 먼저 호출한 뒤 padding을 호출하고 있습니다
이렇게 만들어진 뷰를 보면 (영상) click 후에 padding을 적용하게 되어있기 때문에 클릭 시에는 패딩이 적용되지 않은 모습을 확인할 수 있습니다
두 번째 예시
@Composable
fun CardView(/*...*/) {
val padding = 16.dp
Column(
Modifier
.padding(padding)
.clickable(onClick = onClick)
.fillMaxWidth()
) {
// rest of the implementation
}
}
이번엔 padding을 먼저 호출한 후 clickable을 호출하고 있습니다
이렇게 만들어진 뷰를 확인하면 클릭하기 전에 패딩을 주어 클릭 시 패딩이 생성되어 있는 모습을 볼 수 있습니다
똑같이 clickable과 padding을 사용했지만 Modifier는 체이닝 함수이기 때문에 순서에 따라 뷰에 적용되는 모습이 다르다는 점..!
그렇기 때문에 순서를 주의해서 사용해야 합니다
그리고 modifier를 처음 사용하면서 저는 xml을 사용하며 margin과 padding을 같이 사용하던 사람으로써,,
왜.. margin이 없어..?
하고 제법 당황을 했었는데요
이 부분 또한 Modifier의 체이닝과 관련이 있다고 합니다
Modifier는 체이닝 함수의 특징을 이용해 동작을 더 직관적이고 선언적인 방식으로 간격을 조정하도록 하기 위해 margin을 의도적으로 제거했다고 합니다
추가적으로, 제가 개인적으로 modifier를 사용하면서 느꼈던 점은
위 코드를 보면 최상위에 있는 Column은 매개변수로 전달받은 modifier를 사용하고 있고,
그 아래에 있는 하위 컴포넌트인 Spacer와 Text는 새로운 Modifier 객체를 생성해서 사용하고 있는 모습을 볼 수 있습니다
이때 xml과 비교를 해보자면 OnBoardingPages라는 컴포넌트는 외부에서 받은 매개변수가 margin의 역할을 하고 내부에서 만든 새로운 Modifier 객체가 padding 역할을 하는 것처럼 느껴졌습니다
Compose를 처음 사용하시는 분들은 이렇게 이해를 해보면 쉽지 않을까 싶네요 !
📍 Modifier 사용 시 규칙
Modifier 사용 시 개발자들끼리의 규칙이 있다고 하는데요,
Composable 함수를 만들다보면 선택 매개변수로 주어지는 것들이 굉장히 많습니다
이 때, 첫 번째 규칙으로 선택 매개변수 중에 modifier는 가장 첫 번째여야 합니다
⭕️
@Composable
fun TextButton(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true
) {
}
필수 인자인 text, onClick 이후에 선택 인자 중에 modifier가 가장 먼저 오도록 한 코드입니다
❌
@Composable
fun TextButton(
text: String,
onClick: () -> Unit,
enabled: Boolean = true
modifier: Modifier = Modifier
) {
}
선택 인자 중에 enabled가 더 먼저 온 경우..! modifier를 우선으로 배치해주는 것이 좋습니다
그리고 두 번째 규칙으로 Modifier 매개변수의 기본값은 항상 Modifier여야 합니다
Modifier 매개변수는 반드시 선택적 매개변수여야 하며, 기본값은 항상 Modifier여야 한다고 합니다
modifier: Modifier = Modifier
위 형태가 아닌 커스텀 된 형태로 정의한다면 사용자가 다른 Modifier를 재정의 해 전달했을 때 기존의 정의가 덮어씌워져 버리기 때문입니다
만약 기본적인 Modifier 속성을 정의하고 싶다면 매개변수로 받은 Modifier 뒤에 이어서 붙이면 됩니다
🍀 마무리
xml에서 Compose로 넘어가면서 가장 처음 맞이한 부분이자 헷갈렸던 부분이 Modifier였는데요,
사용을 하다보니 xml과의 차이점도 느껴지고 특히 체이닝 함수라는 부분이 독특하게 다가왔던 것 같습니다
Compose가 손에 익는 그날까지,, 💪🏻
📚 참고
https://developer.android.com/develop/ui/compose/modifiers#best_practices_for_reusing_modifiers
Compose 수정자 | Jetpack Compose | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. Compose 수정자 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 수정자를 사용하면 컴포저블을 장식하거
developer.android.com