RelativeLayout — 본질, Android 애플리케이션의 레이아웃 규칙

저자: IT Sectr 게시일: 2026-02-24 읽는 시간: 9 분

RelativeLayout의 본질을 설명합니다 — Android SDK의 ViewGroup으로, 자식 요소를 서로 또는 부모 컨테이너에 대해 상대적으로 배치합니다. 요소를 엄격하게 순차적으로 배열하는 LinearLayout과 달리, RelativeLayout은 ID를 기준으로 모든 요소를 다른 요소의 왼쪽, 오른쪽, 위, 아래 또는 중앙에 배치할 수 있습니다. 이로 인해 RelativeLayout은 중첩 없이 겹치는 복잡한 레이아웃에 편리합니다. 기본 규칙은 Android Developers 문서에 설명되어 있습니다.

주요 포인트

  • layout_below / layout_above — ID로 지정된 요소의 위 또는 아래에 요소를 고정; 흐름을 구축하기 위한 주요 속성.
  • alignParentTop / alignParentBottom — 요소의 가장자리를 부모의 해당 가장자리에 고정; 네 방향 모두에서 작동.
  • 중앙 정렬 — centerInParent (두 축의 중앙), centerHorizontal (X축 중앙), centerVertical (Y축 중앙).
  • toLeftOf / toRightOf — 겹침 없이 지정된 요소의 왼쪽 또는 오른쪽에 배치.
  • 겹침 규칙 — 규칙이 충돌하는 경우 (예: alignParentTop과 다른 요소의 below), XML에서 마지막으로 선언된 규칙이 우선합니다.

RelativeLayout이란?

RelativeLayout — API Level 1부터 Android SDK에 도입된 ViewGroup으로, 선언적 규칙(레이아웃 규칙)을 통해 자식 요소를 부모 또는 다른 자식 요소에 대해 상대적으로 배치합니다. 각 규칙은 android:layout_above, android:layout_below, android:layout_toLeftOf와 같은 XML 속성에 대상 요소의 ID 값을 설정하여 정의됩니다.

RelativeLayout이 등장하기 전에는 개발자가 비표준 위치 지정마다 중첩된 LinearLayout을 사용해야 했습니다 — 이로 인해 깊은 중첩과 느린 렌더링이 발생했습니다. RelativeLayout은 단일 계층 수준에서 상대적 위치 지정을 제공하여 이 문제를 해결했습니다. 그러나 현대적인 ConstraintLayout과 비교하면 유연성이 제한적입니다: RelativeLayout은 체인, 배리어, 가이드라인 또는 백분율 기반 크기를 지원하지 않습니다.

RelativeLayout에는 두 가지 주요 특징이 있습니다: 단일 onMeasure 패스(weight가 필요한 LinearLayout은 두 번의 패스 필요)와 선언 순서에 대한 의존성 — 요소 A가 요소 B를 참조하고 B가 A보다 나중에 선언된 경우, A 측정 시점에 B의 크기를 알고 있어야 합니다. Android Developers Guide(2024)에 따르면, 모든 규칙이 이미 측정된 요소를 참조하는 경우 RelativeLayout은 한 번의 패스로 측정을 수행합니다. 그렇지 않으면 두 번째 패스가 필요하며, 성능이 저하됩니다.

RelativeLayout이 필요한 경우

RelativeLayout은 상대적 위치 지정이 필요한 3~7개 요소의 간단한 레이아웃(버튼 위의 레이블, 텍스트 오른쪽의 아이콘, 화면 하단의 패널)에 적합합니다. 새 프로젝트에는 ConstraintLayout이 권장되지만, RelativeLayout은 여전히 레거시 코드와 라이브러리에서 널리 사용됩니다.

위치 지정 규칙: relative와 align

RelativeLayout은 두 가지 유형의 규칙을 사용합니다: relative 규칙(다른 요소에 대한 상대적 위치 지정)과 align 규칙(부모에 고정). 각 자식 요소는 무제한의 규칙을 가질 수 있지만, 충돌하는 규칙(예: alignParentTop과 다른 요소의 below)은 마지막으로 선언된 속성이 우선합니다.

Relative 규칙: - android:layout_above="@id/target" — 요소의 아래쪽 가장자리가 target의 위쪽 가장자리에 고정됩니다. - android:layout_below="@id/target" — 요소의 위쪽 가장자리가 target의 아래쪽 가장자리에 고정됩니다. - android:layout_toLeftOf="@id/target" — 오른쪽 가장자리가 target의 왼쪽 가장자리에 고정됩니다. - android:layout_toRightOf="@id/target" — 왼쪽 가장자리가 target의 오른쪽 가장자리에 고정됩니다. - android:layout_toStartOf="@id/target" — RTL 로케일의 경우 toLeftOf와 유사. - android:layout_toEndOf="@id/target" — RTL의 경우 toRightOf와 유사.

Align 규칙(부모에): - android:layout_alignParentTop="true" — 요소의 위쪽 가장자리가 부모의 위쪽 가장자리와 일치. - android:layout_alignParentBottom="true" — 아래쪽 가장자리가 부모의 아래쪽 가장자리와 일치. - android:layout_alignParentLeft="true" — 왼쪽 가장자리가 부모의 왼쪽 가장자리와 일치. - android:layout_alignParentRight="true" — 오른쪽 가장자리가 부모의 오른쪽 가장자리와 일치. - android:layout_alignParentStartandroid:layout_alignParentEnd — RTL용.

다른 요소에 대한 Align 규칙: - android:layout_alignTop="@id/target" — 요소의 상단이 target의 상단과 일치. - android:layout_alignBottom, android:layout_alignLeft, android:layout_alignRight, android:layout_alignStart, android:layout_alignEnd — 유사. - android:layout_alignBaseline="@id/target" — 텍스트 기준선으로 정렬(다른 글꼴 크기의 문자열에 유용).

중앙 정렬과 Z 순서

RelativeLayout의 중앙 정렬은 세 가지 속성으로 설정됩니다: android:layout_centerInParent="true"(두 축에서 부모의 중앙), android:layout_centerHorizontal="true"(수평 중앙), android:layout_centerVertical="true"(수직 중앙). 중앙 정렬은 다른 규칙과 호환됩니다: 요소가 수평으로 중앙에 위치하면서 부모의 아래쪽 가장자리에 고정될 수 있습니다.

Z 순서(겹침 순서)는 XML에서 요소 선언 순서에 의해 결정됩니다. 먼저 선언된 요소가 먼저 그려지고(아래에), 마지막 요소가 마지막에 그려집니다(위에). XML을 변경하지 않고 겹침 순서를 변경해야 하는 경우 android:elevation(API 21부터)을 사용하세요 — elevation이 높은 요소가 위에 그려집니다. API 21 미만 버전에서는 선언 순서만으로 겹침 순서가 제어됩니다.

중요: RelativeLayout은 부모의 android:elevation 속성을 지원하지 않습니다 — 각 요소가 자체 elevation을 제어합니다. 위치 지정 규칙과 elevation이 충돌하는 경우(예: 겹치는 요소), 렌더링에서는 elevation이 우선하지만 위치 지정에서는 우선하지 않습니다 — elevation이 높은 요소는 레이아웃 규칙이 "뒤"에 배치하더라도 시각적으로 다른 요소를 겹칠 수 있습니다.

예제: RelativeLayout을 사용한 XML 레이아웃

예제 1: 사용자 프로필

아바타가 상단 중앙에, 이름이 아바타 아래에, 상태가 이름 아래에, 작업 버튼이 화면 하단에 있습니다. 모든 요소는 순차적 고정을 위해 relative 규칙을 사용합니다.

xml
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/avatar"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="32dp"
        android:src="@drawable/avatar_placeholder" />

    <TextView
        android:id="@+id/user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/avatar"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="12dp"
        android:text="이반 이바노프"
        android:textSize="20sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/user_status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/user_name"
        android:layout_centerHorizontal="true"
        android:text="온라인"
        android:textColor="@color/green" />

    <Button
        android:id="@+id/edit_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="24dp"
        android:text="프로필 편집" />

</RelativeLayout>

아바타는 marginTop + centerHorizontal으로 상단에 고정되고, 이름은 layout_below로 아바타 아래에, 상태는 이름 아래에, 버튼은 alignParentBottom으로 부모의 아래쪽 가장자리에 고정됩니다. 모든 요소는 서로 독립적이며 체인이나 중첩이 없습니다.

예제 2: 아이콘과 배지가 있는 패널

오른쪽 상단 모서리에 빨간색 배지(숫자가 있는 원)가 있는 아이콘. 배지는 아이콘에 대해 가장자리에 정렬되어 겹침을 위해 음수 마진으로 배치됩니다.

xml
<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/ic_notification" />

    <TextView
        android:id="@+id/badge"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_alignTop="@+id/icon"
        android:layout_alignRight="@+id/icon"
        android:layout_marginTop="-6dp"
        android:layout_marginRight="-6dp"
        android:gravity="center"
        android:background="@drawable/badge_background"
        android:text="3"
        android:textColor="@android:color/white"
        android:textSize="10sp" />

</RelativeLayout>

배지는 아이콘의 위쪽과 오른쪽 가장자리에 고정됩니다. 음수 마진(-6dp)은 배지를 바깥쪽으로 이동시켜 아이콘 경계를 겹치는 효과를 만듭니다. 이것은 알림에 널리 사용되는 패턴으로, RelativeLayout이 없으면 FrameLayout이나 사용자 정의 그리기가 필요합니다.

예제 3: RelativeLayout을 사용한 로그인 화면

로그인 양식: 로고가 상단 중앙에, 그 아래에 이메일 필드, 이메일 아래에 비밀번호 필드, 비밀번호 아래에 "로그인" 버튼, "등록" 링크가 하단에 고정됩니다. 모든 요소는 layout_below를 통해 순차적으로 고정됩니다.

xml
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="24dp">

    <TextView
        android:id="@+id/logo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="48dp"
        android:text="MyApp"
        android:textSize="32sp"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/email_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/logo"
        android:layout_marginTop="32dp"
        android:hint="Email" />

    <EditText
        android:id="@+id/password_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/email_input"
        android:layout_marginTop="16dp"
        android:hint="비밀번호"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/password_input"
        android:layout_marginTop="24dp"
        android:text="로그인" />

    <TextView
        android:id="@+id/register_link"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="16dp"
        android:text="계정이 없으신가요? 등록하기"
        android:textColor="@color/primary" />

</RelativeLayout>

화면은 단일 계층 수준에서 5개의 요소를 사용합니다. 위에서 아래로의 흐름(로고 → 이메일 → 비밀번호 → 버튼)은 layout_below를 통해 이루어지며, 링크는 alignParentBottom을 통해 아래로 밀려납니다. 동일한 기능을 위해 LinearLayout은 두 개의 중첩된 컨테이너(상단 그룹용, weight가 있는 링크용)가 필요합니다.

RelativeLayout vs ConstraintLayout: 비교

상대적 위치 지정을 위한 두 ViewGroup의 비교: RelativeLayout(클래식, API 1+)과 ConstraintLayout(모던, Jetpack). 기준: 유연성, 성능, RTL 지원, 적응성.

특성RelativeLayoutConstraintLayout
백분율 크기없음 (고정 및 match_parent만)있음 (width_percent, height_percent, guideline_percent)
RTL 지원start/end를 통해 (API 17+)내장
Chain / 체인없음있음 (spread, spread_inside, packed)
Barrier / Group / Flow없음있음 (가상 도우미)
MotionLayout 애니메이션없음있음
onMeasure 패스1 (의존성 사이클 없음)2 (항상, 하지만 최적화됨)
중앙 정렬centerInParent, centerHorizontal, centerVertical반대 제약 조건으로 bias (0.0–1.0)를 통해
사용 시기레거시 코드, 3~7개 요소의 간단한 레이아웃새 프로젝트, 복잡한 화면, 적응형 레이아웃

RelativeLayout은 한 가지를 제외한 거의 모든 면에서 ConstraintLayout보다 떨어집니다: API 1부터 Android SDK에 내장되어 추가 종속성이 필요하지 않습니다. API 14(Android 4.0) 미만의 minSdk를 사용하는 프로젝트의 경우 RelativeLayout이 상대적 위치 지정의 유일한 표준 옵션입니다. 다른 모든 경우 Google은 ConstraintLayout을 권장합니다.

자주 묻는 질문

RelativeLayout 요소가 표시되지 않는 이유는 무엇인가요?

가장 가능성 있는 이유는 충분한 위치 지정 규칙의 부재입니다. RelativeLayout의 각 요소에는 최소한 하나의 수평 규칙(alignParentLeft, toRightOf, centerHorizontal)과 하나의 수직 규칙(alignParentTop, below, centerVertical)이 있어야 합니다. 규칙이 없으면 요소는 위치(0,0)에 있게 되며 다른 요소 아래나 화면 밖에 숨겨질 수 있습니다. 두 번째 이유는 순환 의존성(요소 A가 B에, B가 A에 연결됨)으로, 예측할 수 없는 동작을 초래합니다.

RelativeLayout에서 화면 중앙에 요소를 배치하려면 어떻게 하나요?

android:layout_centerInParent="true" 속성을 사용하세요. 두 축에서 동시에 요소를 중앙에 배치합니다. 수평으로만 필요한 경우 android:layout_centerHorizontal="true", 수직으로만 필요한 경우 android:layout_centerVertical="true"를 사용하세요. 중앙 정렬은 마진과 함께 작동하며 요소는 지정된 오프셋만큼 중앙에서 이동합니다.

RecyclerView에서 RelativeLayout을 사용할 수 있나요?

가능하지만 권장되지 않습니다. RelativeLayout은 순환 의존성이 있을 때 두 번의 onMeasure 패스를 수행하며, RecyclerView 목록에서 ConstraintLayout보다 15~30% 느립니다. RecyclerView 항목 레이아웃에는 ConstraintLayout을 사용하세요 — 최소한의 측정 시간으로 평면적인 계층 구조를 제공합니다. 레거시 프로젝트에서 이미 RelativeLayout을 사용 중이라면 요소가 순환 의존성을 만들지 않는지 확인하고 Profile GPU Rendering을 통해 스크롤 FPS를 측정하세요.

RelativeLayout에서 layout_margin과 layout_marginTop의 차이는 무엇인가요?

android:layout_margin은 모든 면에 동시에 마진을 설정합니다. android:layout_marginTop은 위쪽에만 설정합니다. 더 구체적인 속성이 우선합니다: layout_margin(16dp)과 layout_marginTop(8dp)이 모두 설정된 경우 위쪽 마진은 8dp가 됩니다. RelativeLayout에서 마진은 인접 요소가 아니라 제약 조건에 대해 작동합니다: layout_below="@id/target"에서 layout_marginTop은 요소의 위쪽 가장자리에서 target의 아래쪽 가장자리까지의 마진입니다.

요약

  • RelativeLayout — 선언적 규칙을 통해 요소를 서로 또는 부모에 대해 상대적으로 배치하는 ViewGroup.
  • 고정 규칙 — layout_below/above (수직), layout_toLeftOf/toRightOf (수평), alignParentTop/Bottom (부모에).
  • 중앙 정렬 — centerInParent (중앙), centerHorizontal (X축), centerVertical (Y축)으로 빠른 정렬.
  • Z 순서 — XML의 선언 순서로 결정; elevation (API 21+)은 렌더링 중 Z 순서를 변경.
  • 제한 사항 — 백분율 크기, 체인, 배리어 없음; 순환 의존성이 두 번째 onMeasure 패스를 유발.
  • 성능 — 사이클 없이 1회 onMeasure 패스, 하지만 복잡한 레이아웃에서 ConstraintLayout보다 떨어짐.
  • 권장 사항 — 레거시 프로젝트에서 사용; 새 화면에서는 ConstraintLayout을 선택.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기