|

Android ConstraintLayout 완전 정리 (4) – ConstraintLayout width height 정리: wrap_content, 0dp, match_constraint 차이

Android ConstraintLayout 완전 정리 (4) – ConstraintLayout width height 정리: wrap_content, 0dp, match_constraint 차이
ConstraintLayout은 XML 코드와 실제 배치 결과를 같이 볼 때 이해가 빨라집니다.

ConstraintLayout width height를 이해할 때 가장 헷갈리는 값이 0dp입니다. 처음 보면 “크기를 0으로 만들겠다”는 뜻처럼 보이지만, ConstraintLayout에서 0dp는 보통 match_constraint, 즉 제약 사이에서 사용할 수 있는 공간으로 크기를 계산하겠다는 뜻입니다.

이 글에서는 width와 height를 정하는 세 가지 기준을 나눠 봅니다. wrap_content는 내용 기준, fixed dp는 지정값 기준, 0dp는 제약 기준으로 이해하면 훨씬 덜 헷갈립니다.

ConstraintLayout 0dp wrap_content fixed dp width 비교 이미지
wrap_content, fixed dp, 0dp는 View 크기를 결정하는 기준이 서로 다릅니다.

ConstraintLayout width height는 위치가 아니라 크기 기준이다

앞선 1~3편에서는 View가 어디에 붙는지를 봤습니다. 이번 편부터는 View가 얼마나 커지는지를 봅니다. ConstraintLayout에서 위치와 크기는 따로 읽어야 합니다. start/end/top/bottom 제약은 위치 기준을 만들고, width/height는 그 기준 안에서 View 크기를 어떻게 계산할지 정합니다.

  • 위치 기준: start, end, top, bottom, baseline 제약
  • 크기 기준: android:layout_width, android:layout_height
  • 간격 기준: margin, goneMargin
  • 이번 편 핵심: wrap_content, fixed dp, 0dp의 차이

가장 흔한 실수는 0dp를 “안 보이게 만드는 값”으로 오해하는 것입니다. 실제로는 View가 보이지 않는 문제가 아니라, 제약이 부족해서 계산할 공간을 제대로 못 찾는 문제가 더 많습니다.


wrap_content는 내용만큼 커진다

wrap_content는 View 내부 내용이 크기 계산의 기준입니다. TextView라면 텍스트와 padding에 맞춰 폭과 높이가 정해집니다. Button도 비슷하게 텍스트, padding, 최소 크기 같은 조건이 함께 반영됩니다.

<TextView
    android:id="@+id/titleText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Title"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

이 예제에서 titleText의 위치는 parent start/top 제약으로 정해집니다. 하지만 크기는 텍스트 내용에 따라 결정됩니다. 텍스트가 짧으면 폭도 작고, 텍스트가 길어지면 폭이 커질 수 있습니다.

ConstraintLayout wrap_content width가 내용에 맞춰지는 예시
wrap_content는 View의 내용이 크기 계산의 출발점입니다.

wrap_content는 라벨, 작은 버튼, 내용 길이가 짧은 보조 텍스트에 자연스럽습니다. 다만 제목처럼 길어질 수 있는 텍스트를 wrap_content로만 두면 parent 밖으로 밀리거나 옆 View와 겹치는 문제가 생길 수 있습니다.

  • 좋은 사용처: 짧은 라벨, 아이콘 옆 작은 텍스트, 내용 크기 그대로 보여줄 버튼
  • 주의할 곳: 긴 제목, 서버에서 내려오는 긴 문구, 다국어로 길이가 크게 바뀌는 텍스트

fixed dp는 지정한 값으로 고정된다

고정 dp는 말 그대로 width나 height에 특정 값을 쓰는 방식입니다. 예를 들어 버튼 폭을 120dp로 정하면 텍스트가 짧아도 버튼 폭은 120dp를 유지합니다.

<Button
    android:id="@+id/saveButton"
    android:layout_width="120dp"
    android:layout_height="48dp"
    android:text="Save"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout fixed dp width 버튼 크기 예시
고정 dp는 버튼 폭을 맞출 때 유용하지만 화면 크기 변화에는 덜 유연합니다.

고정 dp는 같은 크기의 버튼을 나란히 맞추거나, 아이콘 영역처럼 명확한 규격이 있는 곳에 유용합니다. 하지만 화면 폭이 좁아지거나 텍스트가 길어지는 상황까지 모두 고정값으로 버티려고 하면 UI가 쉽게 깨집니다.

  • 좋은 사용처: 아이콘 박스, 고정 높이 버튼, 썸네일 영역
  • 주의할 곳: 긴 텍스트 영역, 반응형 카드, 화면 폭이 다양한 리스트 아이템

고정값을 쓴다고 해서 무조건 나쁜 것은 아닙니다. 문제는 고정값이 화면 변화와 콘텐츠 변화까지 책임져야 할 때입니다. 이럴 때는 0dp와 제약을 함께 쓰는 편이 더 자연스럽습니다.


ConstraintLayout 0dp는 match_constraint로 읽는다

ConstraintLayout에서 width나 height를 0dp로 쓰면 보통 MATCH_CONSTRAINT 의미가 됩니다. 공식 AndroidX ConstraintLayout 레퍼런스도 0dp를 MATCH_CONSTRAINT와 같은 의미로 설명합니다.

<ImageView
    android:id="@+id/iconImage"
    android:layout_width="48dp"
    android:layout_height="48dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:text="Long title can use remaining space"
    app:layout_constraintStart_toEndOf="@id/iconImage"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="@id/iconImage" />

여기서 titleText의 width는 0dp입니다. 하지만 화면에서는 0px로 사라지는 것이 아닙니다. start는 iconImage의 end에 연결되어 있고, end는 parent end에 연결되어 있습니다. 그래서 titleText는 그 사이의 남은 폭을 사용합니다.

ConstraintLayout 0dp match_constraint가 남은 공간을 채우는 예시
0dp는 크기가 0이라는 뜻이 아니라 제약 사이 사용 가능한 공간을 쓰겠다는 뜻입니다.

이 구조는 카드 UI에서 특히 자주 씁니다. 왼쪽에는 아이콘이나 이미지가 있고, 오른쪽 텍스트는 남은 공간 안에서 줄바꿈되거나 말줄임 처리됩니다. wrap_content로 두면 텍스트가 너무 길 때 오른쪽으로 밀릴 수 있지만, 0dp는 parent 끝을 기준으로 폭을 제한할 수 있습니다.

  • 0dp width가 자연스러운 경우: 양쪽 가로 제약이 있다
  • 0dp height가 자연스러운 경우: 위아래 세로 제약이 있다
  • 텍스트 영역을 남은 공간 안에 가두고 싶을 때 유용하다

0dp가 실패하는 대표 실수는 제약 누락이다

0dp는 제약 기준으로 크기를 계산합니다. 따라서 가로 폭을 0dp로 두면서 start만 있고 end가 없으면 “어디까지 채워야 하는지”가 불명확해집니다. 반대로 height를 0dp로 쓰려면 top/bottom 같은 세로 기준을 충분히 확인해야 합니다.

<!-- 좋지 않은 예: width는 0dp인데 end 제약이 없다 -->
<TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Title"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout 0dp 한쪽 제약 누락 실수 예시
0dp width는 가로 제약이 부족하면 의도한 폭 계산을 만들기 어렵습니다.

이럴 때는 먼저 방향별 제약을 점검합니다. width 문제라면 start/end를 봅니다. height 문제라면 top/bottom을 봅니다. 0dp 자체를 없애기 전에, 계산할 기준이 충분한지부터 확인하는 것이 좋습니다.

  • width=0dp 문제: start와 end가 모두 있는지 본다
  • height=0dp 문제: top과 bottom이 모두 있는지 본다
  • sibling 기준이라면 기준 View가 존재하고 GONE 상태 변화가 없는지도 본다
  • margin이 너무 커서 남은 공간이 거의 없는지도 본다

match_parent 대신 0dp와 parent 제약을 생각한다

AndroidX ConstraintLayout 레퍼런스는 ConstraintLayout 안의 widget에 MATCH_PARENT를 권장하지 않는다고 설명합니다. 비슷한 동작은 MATCH_CONSTRAINT, 즉 0dp와 parent 제약으로 만들 수 있습니다.

<!-- 권장 방향: parent 양쪽에 제약을 걸고 width를 0dp로 둔다 -->
<TextView
    android:id="@+id/bannerText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Full width banner"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout match_parent와 0dp parent 제약 차이 이미지
ConstraintLayout 안에서는 match_parent보다 0dp와 parent 제약을 조합하는 편이 권장됩니다.

기존 코드에 match_parent가 있다고 해서 무조건 바로 바꿔야 한다는 뜻은 아닙니다. 하지만 새 ConstraintLayout 예제를 작성할 때는 parent 양쪽 제약과 0dp 조합을 먼저 떠올리는 편이 좋습니다. 그래야 margin, bias, min/max, ratio 같은 ConstraintLayout 기능과도 자연스럽게 이어집니다.


ImageView 크기는 더 조심해서 읽는다

ImageView는 텍스트보다 한 가지를 더 생각해야 합니다. 이미지 원본 비율과 scaleType이 실제 표시 결과에 영향을 줄 수 있기 때문입니다. 이번 편에서는 자세한 비율 계산까지 들어가지는 않지만, ImageView에 wrap_content, fixed dp, 0dp를 쓸 때의 느낌은 구분해두는 것이 좋습니다.

  • wrap_content: 이미지 intrinsic size나 drawable 조건의 영향을 받는다
  • fixed dp: 지정한 박스 안에 이미지가 scaleType에 따라 맞춰진다
  • 0dp: 제약 사이 공간을 박스로 잡고, 이미지는 그 안에서 표시된다

이미지 비율을 안정적으로 맞추는 내용은 8편 dimensionRatio에서 따로 다룹니다. 이번 편에서는 0dp가 “남은 공간을 계산하는 크기 기준”이라는 점만 정확히 잡으면 충분합니다.


실무에서 고르는 기준

  • 내용이 기준이면 wrap_content
  • 디자인 규격이 명확하면 fixed dp
  • 제약 사이 남은 공간을 써야 하면 0dp
  • parent 전체 폭처럼 보이게 만들고 싶으면 match_parent보다 0dp + parent 제약
  • 0dp가 이상하면 width/height보다 먼저 방향별 제약 누락을 확인

이 기준을 외워두면 XML을 읽는 속도가 빨라집니다. 특히 긴 제목 TextView는 0dp와 end 제약을 함께 두는 경우가 많습니다. 반대로 짧은 label은 wrap_content가 더 읽기 쉽습니다. 같은 TextView라도 역할에 따라 크기 기준이 달라집니다.


정리

ConstraintLayout width height를 이해할 때는 속성값을 하나씩 외우기보다 “무엇이 크기의 기준인가”를 먼저 보면 됩니다. wrap_content는 내용, fixed dp는 지정값, 0dp는 제약 사이 공간이 기준입니다.

  • wrap_content는 내용만큼 커진다
  • fixed dp는 지정값을 유지한다
  • 0dp는 ConstraintLayout에서 match_constraint로 읽는다
  • 0dp는 양쪽 제약이 있을 때 가장 자연스럽다
  • match_parent보다 0dp와 parent 제약 조합을 우선 검토한다

다음 편에서는 0dp를 더 깊게 다룹니다. 양쪽 제약, min/max 크기, 남은 공간 계산을 기준으로 match_constraint가 언제 성공하고 언제 실패하는지 이어서 정리하겠습니다.

아래에는 이 편보다 앞에서 다룬 글만 모았습니다. 아직 뒤 편은 발행 전이므로 링크하지 않습니다.

공식 기준은 Android Developers ConstraintLayout 가이드AndroidX ConstraintLayout 레퍼런스를 확인했습니다.

함께보면 좋은 글