안드로이드 시스템·Compose 용어 사전
Composepadding · Modifier 순서

Modifier

컴포저블에 크기·여백·동작을 입히는 체인. 순서가 결과를 바꾼다.

컴포저블에 크기 · 여백 · 배경 · 동작을 입히는 체인.

순서가 결과를 바꾼다

// 배경이 여백을 포함한다 — 큰 회색 박스
Modifier.background(Gray).padding(16.dp)

// 여백 안쪽에만 배경 — 작은 회색 박스
Modifier.padding(16.dp).background(Gray)
  • **왜 — Modifier 는 바깥에서 안으로 순서대로 감싼다**
    • background 가 먼저면 '전체 영역' 을 칠하고 그 안에 여백을 준다
    • padding 이 먼저면 '여백을 뺀 영역' 이 background 에 전달된다

클릭 영역도 순서를 탄다

Modifier.clickable { }.padding(16.dp)    // 여백까지 클릭된다 (터치 영역이 넓다)
Modifier.padding(16.dp).clickable { }    // 내용만 클릭된다

접근성 최소 터치 영역은 48dp 다 작은 아이콘은 clickable 을 먼저 걸거나 minimumInteractiveComponentSize 를 쓴다

세 가지 기본 레이아웃

Column { }   세로로 쌓는다
Row { }      가로로 쌓는다
Box { }      겹친다 (z 축)

Column(
    verticalArrangement = Arrangement.spacedBy(8.dp),   // 자식 사이 간격
    horizontalAlignment = Alignment.CenterHorizontally
)

weight — 남는 공간을 나눈다

Row {
    Text("고정")
    Spacer(Modifier.weight(1f))       // 남는 공간을 밀어낸다
    Icon(...)
}

weight 는 Row/Column 스코프 안에서만 쓸 수 있다 (RowScope 확장 함수) fillMaxWidth() 와 weight 를 같이 주면 weight 가 이긴다

재사용 가능한 컴포저블의 규칙

@Composable
fun MyCard(
    title: String,
    modifier: Modifier = Modifier      // ★ 첫 번째 선택 파라미터로 받는다
) {
    Card(modifier) { Text(title) }     // ★ 받은 것을 최상위에 그대로 적용한다
}

이 규칙을 안 지키면 호출부가 크기·여백을 제어할 수 없다 또 받은 modifier 를 안쪽 자식에 붙이면 호출부의 기대와 어긋난다

Modifier.then과 재사용

val base = Modifier.fillMaxWidth().padding(16.dp)
Box(base.then(Modifier.background(Gray)))

// 조건부 적용
Modifier.then(if (isSelected) Modifier.border(2.dp, Blue) else Modifier)

면접 함정

  • "Modifier 순서는 스타일 취향" → 결과가 실제로 다르다. 여백·배경·클릭 영역이 전부 달라진다.
  • modifier를 받지 않는 공용 컴포저블 → 재사용이 사실상 불가능해진다.

크기 지정의 종류

Modifier.size(48.dp)            // 정확히 이 크기 (부모 제약을 무시하고 강제)
Modifier.requiredSize(48.dp)    // 부모 제약도 무시한다 (밖으로 넘칠 수 있다)
Modifier.fillMaxWidth(0.5f)     // 부모의 50%
Modifier.wrapContentSize()      // 내용 크기
Modifier.defaultMinSize(48.dp)  // 최소 크기 보장 (더 커질 수 있다)
Modifier.aspectRatio(16f / 9f)  // 비율 유지

여러 번 적용하면

Modifier.padding(8.dp).padding(8.dp)     // 합쳐서 16dp
Modifier.size(100.dp).size(50.dp)        // 첫 번째가 이긴다 (제약이 먼저 좁혀진다)

Modifier 는 '누적' 이 아니라 '중첩' 이다 바깥쪽이 제약을 정하고 안쪽이 그 안에서 다시 정한다

  • size 를 두 번 주면 두 번째가 무시되는 것처럼 보인다

커스텀 Modifier

fun Modifier.shimmer(): Modifier = composed {
    val transition = rememberInfiniteTransition(label = "shimmer")
    val x by transition.animateFloat(0f, 1000f, infiniteRepeatable(tween(1200)), label = "x")
    drawWithContent { drawContent(); drawRect(brush = gradientAt(x)) }
}

composed { } 는 성능 비용이 있어 Modifier.Node 방식이 권장된다 간단한 조합이면 그냥 확장 함수로 충분하다

  • fun Modifier.card() = this.padding(16.dp).clip(RoundedCornerShape(12.dp))

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — Compose 레이아웃·Modifier — Column·Row·Box·체이닝