XML 레이아웃 구조와 기본 속성
Android의 인터페이스는 View와 ViewGroup의 계층적 트리 구조로 구현됩니다. 레이아웃 파일은 이러한 UI 노드를 선언형으로 정의하며, HTML과 유사한 구문을 사용하여 화면 구성을 직관적으로 설계할 수 있습니다.
핵심 레이아웃 속성
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:layout_margin="12dp"
android:background="@color/surface"
android:visibility="gone" />
layout_width/height: 부모 컨테이너의 경계 또는 내부 콘텐츠 크기에 맞춰 확장 범위를 결정padding/margin: 요소 내부 여백과 외부 여백을 제어하며, 화면 밀도 독립성을 위해dp단위 사용 권장visibility:visible,invisible,gone상태로 렌더링 포함 여부를 전환
주요 View 위젯 구성
텍스트 표시: TextView
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/greeting"
android:textSize="18sp"
android:textColor="@color/text_primary"
android:fontFamily="sans-serif-medium" />
입력 필드: EditText
<EditText
android:id="@+id/inputField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/enter_data"
android:inputType="textEmailAddress" />
상호작용 요소: Button & ImageView
<Button
android:id="@+id/actionBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="확인"
android:backgroundTint="@color/primary" />
<ImageView
android:id="@+id/displayImage"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/sample_icon"
android:scaleType="fitCenter" />
실무 적용: 로그인 폼 구현
선언적 레이아웃을 통해 로그인 화면을 구성하고, Kotlin 코드에서 이벤트 바인딩을 수행하는 과정입니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center_horizontal">
<ImageView
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_marginTop="48dp"
android:src="@drawable/app_logo" />
<EditText
android:id="@+id/edtAccount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:hint="아이디"
android:inputType="text" />
<EditText
android:id="@+id/edtPass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="비밀번호"
android:inputType="textPassword" />
<Button
android:id="@+id/btnProceed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="접속하기" />
</LinearLayout>
해당 레이아웃을 Activity에서 연결하는 로직은 다음과 같습니다.
class AuthScreenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.screen_auth)
val accountInput = findViewById<EditText>(R.id.edtAccount)
val passInput = findViewById<EditText>(R.id.edtPass)
val submitBtn = findViewById<Button>(R.id.btnProceed)
submitBtn.setOnClickListener {
val credentials = SessionData(accountInput.text.toString(), passInput.text.toString())
processLogin(credentials)
}
}
data class SessionData(val userId: String, val secret: String)
private fun processLogin(data: SessionData) { /* 인증 요청 처리 */ }
}
레이아웃 디버깅 및 분석
- Layout Inspector: 실행 중인 앱의 뷰 트리를 실시간으로 시각화하여 마진, 패딩, 크기 오버플로우를 정확히 진단할 수 있습니다.
- Design/Preview 탭: 빌드 없이 레이아웃의 렌더링 결과를 다양한 디바이스 크기 및 다크/라이트 모드에서 미리 확인합니다.
- Static Analysis (Lint): XML 내의 잠재적 오류, 접근성 위반, 성능 병목 현상을 코드 분석 단계에서 사전에 경고합니다.
렌더링 성능 최적화 전략
- 계층 구조 평면화:
ConstraintLayout활용을 통해 중첩된 ViewGroup을 최소화하고 레이아웃 파싱 시간을 단축합니다. - 측정 알고리즘 최적화:
wrap_content의 과도한 사용은 재측정(remesure)을 유발하므로, 가능한 한 고정 크기 또는match_parent를 적용합니다. - 부분 레이아웃 재활용:
<include>태그로 반복되는 컴포넌트를 분리하고, 루트 컨테이너 삽입을 방지하기 위해<merge>를 병행합니다. - 지연 로딩:
ViewStub을 활용하여 화면 전환 시점에 따라 뷰의 인스턴스화를 지연시켜 초기 메모리 점유율을 낮춥니다.
기술 면접 핵심 질문
Q1. Android 뷰 계층의 생명주기와 렌더링 파이프라인은?
표준 렌더링 과정은 세 단계로 나뉩니다. onMeasure()에서 부모의 제약 조건에 따라 각 노드의 최종 크기를 계산한 후, onLayout()에서 화면 내 상대 좌표와 위치를 배치합니다. 마지막으로 onDraw()가 호출되어 비트맵 캔버스에 배경, 콘텐츠, 포어그라운드 순서로 픽셀이 그려집니다.
Q2. UI 렌더링 성능을 개선하는 구체적인 방법은?
레이아웃 트리 깊이를 줄이고 ConstraintLayout으로 단일 계층 구조를 유지하는 것이 기본입니다. 불필요한 wrap_content를 제거하고, 반복되는 UI 조각은 <include>로 추상화하며, 화면 초기 로딩 시 쓰이지 않는 요소는 ViewStub으로 지연 처리합니다.
Q3. 고정 값(Pixel/dp)을 직접 입력하는 것이 비권장되는 이유는?
Android 디바이스는 화면 밀도(DPI)와 물리적 크기가 천차만별입니다. 고정값은 다양한 해상도에서 UI 변형이나 잘림 현상을 유발하며, 다국어 환경이나 동적 테마 적용 시 유지보수 비용이 급증합니다. 대신 상대적 레이아웃 전략과 dp/sp 단위를 조합하여 반응형 구조를 갖추어야 합니다.
Material Design 통합 사례
Google의 공식 컴포넌트 라이브러리를 적용한 현대적인 입력 폼 예시입니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:boxStrokeColor="@color/accent">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="메모 입력" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="24dp"
android:contentDescription="추가"
app:srcCompat="@drawable/ic_plus" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>