정답보다 해답을

[Android][Compose] Jetpack Compose의 padding, offset, Spacer 차이 정리 본문

Android

[Android][Compose] Jetpack Compose의 padding, offset, Spacer 차이 정리

DOLMENG. 2025. 3. 29. 15:38

Jetpack Compose의 padding, offset, Spacer 차이 정리

Jetpack Compose에서는 UI 구성 시 요소 간의 간격을 조절하거나 위치를 미세 조정할 수 있는 다양한 Modifier를 제공합니다.
그중 padding, offset, Spacer는 자주 쓰이지만 서로 명확한 차이가 있습니다.
이 글에서는 이 세 가지 Modifier의 차이점과 사용 시기를 명확하게 정리해보겠습니다.

사실 paddingoffset이나 Spacer와 같은 직접적인 비교 대상이 아닐 수도 있습니다.
padding은 정확하게 말하자면 Composable 요소 자체를 이동시키는 것이 아니라,
컴포저블의 외곽에서 자식 콘텐츠와의 간격을 확보하는 Modifier입니다.

다시 말해, padding은 위치를 옮기는 게 아니라 내부 간격을 조절하는 Modifier로,
offset이나 Spacer처럼 시각적 배치 이동과는 의미적으로 구분됩니다.

따라서 이번 글에서는 offsetSpacer의 차이에 중점을 두고 살펴보되, 함께 혼용되는 경우가 많은 padding에 대해서도 간략히 비교해보겠습니다.


1. Modifier.padding

정의

컴포저블 자신의 내부에 여백을 주는 Modifier입니다.

특징

  • 자식 컴포넌트의 측정값에 영향을 줍니다.
  • 레이아웃 크기에 영향을 미칩니다.
  • 요소의 내부에 공간을 만들고, 그로 인해 자식 요소가 차지할 수 있는 공간은 줄어듭니다.

예시

@Composable
private fun Greeting(name: String, modifier: Modifier = Modifier) {
    Column(
        modifier = Modifier
            .padding(24.dp)
            .fillMaxWidth()
    ) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

Column에 padding(24.dp)이 적용되어 있어 텍스트 요소들은 상하좌우로 24dp의 여백을 두고 배치됩니다.

이미지 예시:

padding 예시


2. Modifier.offset

정의

컴포저블의 위치를 시각적으로만 이동시키는 Modifier입니다.

특징

  • 측정값에는 영향을 주지 않고 배치에만 영향을 줍니다.
  • 다른 요소들은 이 요소가 원래 위치에 있다고 인식합니다.
  • 겹치기나 애니메이션에 적합합니다.

offset이 작동하는 시점

Modifier.offset은 컴포저블이 측정(measure)되고 배치(layout)까지 완료된 이후,
시각적으로만 위치를 이동시키는 Modifier입니다.

즉, 컴포저블의 실제 크기나 배치 순서에는 영향을 주지 않으며,
화면에 그려지는 위치만 바꿉니다.

이러한 점에서 offset은 배치 이후 위치를 살짝 조정할 수 있어
미세 위치 조정, 겹치기, 애니메이션 처리 등에 적합합니다.

예를 들어,

Row(modifier = Modifier.fillMaxWidth()) {
    Text("A")
    Text("B", modifier = Modifier.offset(x = 20.dp))
}

이 경우 Text("B")는 오른쪽으로 20dp 시각적으로 이동하지만,
Row는 여전히 B가 A 바로 옆에 있다고 인식하기 때문에 겹침 현상이 생길 수 있습니다.

또한 offset은 요소의 원래 위치에 터치 이벤트 등이 적용되므로
터치 범위가 이동한 것처럼 보이지 않을 수도 있음에 유의해야 합니다.

예시

@Composable
fun ArtistCard(artist: Artist) {
    Row {
        Column {
            Text(artist.name)
            Text(
                text = artist.lastSeenOnline,
                modifier = Modifier.offset(x = 4.dp)
            )
        }
    }
}

offset(x = 4.dp)를 통해 두 번째 텍스트를 오른쪽으로 4dp만큼 시각적으로 이동시킵니다. 실제 측정값에는 영향을 주지 않으며, 배치 위치만 바뀝니다.

이미지 예시:

offset 예시

그렇다면 위 ArtistCard를 Spacer로 구현해볼까요?


3. Spacer

참고: Spacer는 음수 값을 사용할 수 없습니다.
예를 들어 Modifier.width(-8.dp)처럼 음수 크기를 주면 예외가 발생하거나 무시됩니다.
따라서 요소를 왼쪽 또는 위로 이동하고 싶은 경우에는 Modifier.offset을 사용해야 합니다.

정의

공간을 차지하는 빈 컴포저블로, 요소 사이에 여백을 만들기 위해 사용됩니다.

특징

  • 실제로 공간을 차지합니다.
  • Modifier.size() 또는 Modifier.weight()와 함께 사용됨.
  • 의도적으로 간격을 만들 때 명시적으로 사용하면 가독성이 좋음.

예시

@Composable
fun ArtistCardWithSpacer(artist: Artist) {
    Row {
        Column {
            Text(artist.name)
            Row {
                Spacer(modifier = Modifier.width(4.dp))
                Text(artist.lastSeenOnline)
            }
        }
    }
}

위 코드는 offset으로 이동한 텍스트 위치를 Spacer로 그린 예시입니다.
하지만 이 방식은 내부에 Row를 하나 더 중첩해야 하므로 구조가 복잡해지고, 실제로는 요소의 위치를 이동한 것이 아닌 공간을 확보한 것에 불과합니다.
따라서 정밀한 위치 이동에는 offset을 사용하는 것이 적합합니다.


offset과 Spacer의 공통점과 차이점

같은 진행 방향이라면 Spacer가 더 적절한 이유

만약 Row 또는 Column처럼 일정한 방향으로 컴포저블을 나열하고 그 사이의 간격만 확보하고자 할 경우, Spacer를 사용하는 것이 더 적절합니다.

이유:

  • Spacer는 명시적으로 공간을 확보하는 컴포저블입니다.
  • Row, Column의 레이아웃 흐름을 유지하면서 중간중간 간결하게 여백을 삽입할 수 있습니다.
  • offset을 사용할 경우, 레이아웃 구조를 더 복잡하게 만들거나 위치를 눈대중으로 조절하게 되는 경우가 있어 가독성이나 유지보수 측면에서 불리합니다.
  • offset은 실제로 요소의 위치를 이동시키기 때문에 겹침 현상이 발생할 수 있으나, Spacer는 명확하게 공간을 차지하기 때문에 겹침 없이 일관된 간격 유지가 가능합니다.

예를 들어, 다음과 같은 Row가 있다고 가정해봅시다:

Row {
    Text("Label")
    Spacer(modifier = Modifier.width(8.dp))
    Button(onClick = { }) {
        Text("Action")
    }
}

이렇게 구성하면 정확히 8dp의 간격을 유지하면서도 구조가 단순하게 유지됩니다.

반대로 offset으로 여백을 만들려 한다면 실제로 공간이 확보되지 않기 때문에 레이아웃 왜곡이나 겹침 현상이 발생할 수 있습니다.

예: 언제 offset이 필요한가?

  • 네비게이션 UI에서 아이콘과 레이블 간의 간격이 조금 어색할 때, offset으로 미세 조정이 가능합니다.
  • 예를 들어, BottomNavigationItem 안의 아이콘과 텍스트 간 여백이 디자인적으로 살짝 어긋날 경우:
    Icon(
      imageVector = Icons.Default.Home,
      contentDescription = null,
      modifier = Modifier.offset(y = (-2).dp)
    )
  • 이런 식으로 아이콘만 살짝 올리거나 텍스트만 살짝 내릴 수 있기 때문에, 이미지 리소스를 수정하지 않고 정밀하게 조정할 수 있습니다.

공통점

  • 둘 다 컴포저블 외부의 위치 또는 간격을 조정하는 데 사용됩니다.
  • 레이아웃 배치에 직접적인 영향을 주며, 시각적인 구조를 바꿀 수 있습니다.
  • Modifier를 통해 컴포저블에 체이닝 방식으로 적용됩니다.
  • 컴포저블의 외부 레이아웃에 영향을 줄 수 있다는 점에서 padding과 다릅니다.

차이점

항목 offset Spacer
역할 요소를 시각적으로 이동 실제 공간 확보 (간격 생성)
공간 차지 여부 X 차지하지 않음 O 차지함
측정값 영향 X 없음 O 있음
음수 값 허용 O 가능 X 불가
겹치기 가능 여부 O 가능 X 불가
애니메이션 활용 O 자주 사용됨 X 거의 없음
사용 예 위치 미세 조정, 겹치기 UI 컴포넌트 간 여백 생성

언제 무엇을 써야 할까?

상황 적절한 구성 방식
요소 사이에 일정한 간격을 주고 싶을 때 Spacer 컴포저블 + Modifier.width() 또는 Modifier.height()
컴포저블 내부에 여백이 필요할 때 Modifier.padding
컴포저블의 위치를 시각적으로 살짝 옮기고 싶을 때 Modifier.offset
애니메이션과 함께 위치 이동이 필요한 경우 Modifier.offset (측정값에 영향 없음으로 효과적)

참고 자료