
ConstraintLayout start end 제약은 View의 가로 위치를 정하는 기본 규칙입니다. 여기에 top, bottom 제약을 함께 걸어야 View의 세로 위치까지 안정적으로 정해집니다.
이번 글은 parent 기준 배치와 sibling 기준 배치를 나누어 보고, 같은 View가 어떤 제약을 만나면 어디로 이동하는지 이미지로 확인합니다.

ConstraintLayout start end top bottom 제약은 두 부분으로 읽는다
예를 들어 layout_constraintStart_toStartOf는 두 부분으로 나눠 읽으면 쉽습니다. 앞의 Start는 내 View의 start edge입니다. 뒤의 StartOf는 대상 View의 start edge입니다.
- layout_constraintStart_toStartOf: 내 start를 대상 start에 연결
- layout_constraintStart_toEndOf: 내 start를 대상 end에 연결
- layout_constraintEnd_toStartOf: 내 end를 대상 start에 연결
- layout_constraintEnd_toEndOf: 내 end를 대상 end에 연결
- top/bottom도 같은 방식으로 읽는다
속성 이름이 길어 보이는 이유는 “내 쪽 edge”와 “대상 쪽 edge”를 한 이름에 모두 담기 때문입니다. 그래서 속성을 외우기보다 왼쪽 절반과 오른쪽 절반을 나눠 읽으면 실수가 줄어듭니다.
- constraintStart: 내 View의 start edge
- toEndOf: 대상 View의 end edge
- @id/nameText: 연결 대상
- parent: ConstraintLayout 자체
parent 왼쪽 위에 붙이기
가장 기본은 View를 parent의 start와 top에 연결하는 것입니다. 이때 parent는 ConstraintLayout 자체입니다.
<Button
android:id="@+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />이 코드는 saveButton의 왼쪽 시작점을 parent의 시작점에 붙이고, saveButton의 위쪽을 parent의 위쪽에 붙입니다. margin이 없다면 parent의 기준선에 바로 붙습니다.

parent 오른쪽 아래에 붙이기
반대로 end와 bottom을 parent에 연결하면 View는 오른쪽 아래 기준으로 배치됩니다. floating button이나 하단 액션 버튼을 만들 때 자주 보는 형태입니다.
<Button
android:id="@+id/actionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Action"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />여기서 end는 오른쪽이라고만 외우지 않는 편이 좋습니다. 언어 방향에 따라 start와 end의 실제 방향은 달라질 수 있습니다.

이 예제는 실제 앱에서 화면 오른쪽 아래 버튼을 만들 때 자주 쓰입니다. 보통 여기에 marginEnd와 marginBottom을 함께 넣어 parent 가장자리와 버튼 사이에 여백을 둡니다.
<Button
android:id="@+id/actionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
android:text="Action"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />A 오른쪽에 B 배치하기
sibling 기준 배치는 ConstraintLayout을 쓰는 이유가 가장 잘 드러나는 부분입니다. B의 start를 A의 end에 연결하면 B는 A 오른쪽에 놓입니다.
<TextView
android:id="@+id/labelText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="이름"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/valueText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="병섭"
app:layout_constraintStart_toEndOf="@id/labelText"
app:layout_constraintTop_toTopOf="@id/labelText" />이 구조에서는 labelText가 움직이면 valueText도 함께 움직입니다. valueText의 기준이 parent가 아니라 labelText이기 때문입니다.

A 아래에 B를 놓을 때도 원리는 같습니다. 이번에는 B의 top을 A의 bottom에 연결합니다. start는 parent에 연결할 수도 있고, A의 start에 맞출 수도 있습니다.
<TextView
android:id="@+id/descriptionText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Description"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText" />
가로로 붙일 때는 start/end를 봅니다. 세로로 붙일 때는 top/bottom을 봅니다. 이 기준만 분리해도 XML을 읽는 속도가 빨라집니다.
양쪽 제약을 걸면 가운데 배치가 된다
View의 start와 end를 모두 parent에 연결하면 ConstraintLayout은 View를 두 제약 사이에 놓습니다. 기본값은 가운데입니다. 나중에 bias를 배우면 이 위치를 왼쪽이나 오른쪽으로 밀 수 있습니다.
<Button
android:id="@+id/centerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
양쪽 제약은 “가운데 정렬 속성”이 아니라 “두 기준 사이에 놓기”에 가깝습니다. 기본 bias가 0.5라서 가운데로 보일 뿐입니다. 6편에서 bias를 바꾸면 같은 양쪽 제약에서도 왼쪽이나 오른쪽으로 치우칠 수 있습니다.
start/end를 먼저 쓰는 이유
left/right 속성도 있지만 새 글과 새 예제에서는 start/end를 기본으로 쓰는 편이 안전합니다. start/end는 레이아웃 방향을 고려합니다. 영어와 한국어 화면에서는 start가 보통 왼쪽이지만, RTL 언어에서는 반대가 될 수 있습니다.

left/right가 항상 틀린 것은 아닙니다. 다만 새 화면을 만들 때는 start/end를 기본값으로 잡는 편이 더 안전합니다. 특히 다국어 앱이나 라이브러리 UI를 만들 때는 방향성 대응을 초반부터 고려하는 것이 좋습니다.
제약을 읽는 순서
복잡한 XML을 볼 때는 모든 속성을 위에서 아래로 읽지 않아도 됩니다. 먼저 가로 제약을 찾고, 그 다음 세로 제약을 찾습니다. 마지막으로 margin과 width/height를 확인합니다.
- 1단계: start/end 또는 left/right를 찾아 가로 위치를 본다
- 2단계: top/bottom 또는 baseline을 찾아 세로 위치를 본다
- 3단계: margin이 기준선에서 얼마나 떨어뜨리는지 본다
- 4단계: width/height가 wrap_content인지 0dp인지 확인한다
정리
ConstraintLayout 제약은 길게 외우지 않아도 됩니다. 내 View의 어느 edge를 대상의 어느 edge에 연결하는지만 읽으면 됩니다. parent 기준 배치로 시작하고, sibling 기준 배치를 익히면 실제 화면을 구성하는 감각이 생깁니다.
- start/end는 가로 방향의 기본
- top/bottom은 세로 방향의 기본
- parent는 ConstraintLayout 자신
- sibling 기준 제약은 실제 UI 조합에서 자주 사용
- 양쪽 제약은 bias와 0dp 크기 계산의 기반
기본 제약을 한 번에 넓게 훑고 싶다면 기존에 정리한 안드로이드 ConstraintLayout 완전 정리 글도 참고할 수 있습니다. 이 시리즈에서는 그 내용을 더 잘게 나누어 이미지 중심으로 다시 설명합니다.
아래에는 이 편보다 앞에서 다룬 글만 모았습니다. 아직 뒤 편은 발행 전이므로 링크하지 않습니다.
공식 기준은 Android Developers ConstraintLayout 가이드와 AndroidX ConstraintLayout 레퍼런스를 확인했습니다.
Android ConstraintLayout 완전 정리 이전 글 모음
Android ConstraintLayout 완전 정리 (1) – ConstraintLayout 기본 사용법: LinearLayout과 다른 제약 기반 배치 이해하기