모바일 앱 인터페이스 개발은 UI 구성요소와 프레임워크를 이해하는 것에서 시작됩니다. 이 기사에서는 Material Design, Human Interface Guidelines, SwiftUI, Jetpack Compose, Flutter Widgets, 측정 단위 시스템(dp, sp, pt, px) 및 NavigationView와 RecyclerView부터 Safe Area와 Dark Mode까지 모든 주요 UI 요소를 다룹니다. 이 자료는 이론에서 첫 번째 프로젝트로 전환하는 초보자를 대상으로 합니다. 자세한 내용은 공식 Material Design 문서를 참조하세요.
핵심 포인트
각 플랫폼은 자체 규칙과 구성요소 세트를 제공합니다. Android의 경우 2014년 Google이 개발한 Material Design입니다. Material Design은 물리적 재료의 은유를 사용합니다 — 레이어, 그림자(Elevation), 애니메이션 전환 및 적응형 레이아웃. 주요 원칙에는 Elevation을 통한 계층 구조, 의미 있는 움직임 및 다양한 폼 팩터에 대한 적응성이 포함됩니다. Material Design 3(Material You) — 동적 테마와 개인화된 색상을 갖춘 최신 버전 — 을 살펴보는 것이 좋습니다.
Apple은 Human Interface Guidelines(HIG)를 제공합니다 — iOS, iPadOS, macOS, watchOS 및 tvOS를 위한 규칙 세트입니다. HIG는 명확한 타이포그래피(San Francisco), Notch 및 Dynamic Island를 고려한 Safe Area, 제스처 기반 탐색 및 일관성을 강조합니다. Material Design과 달리 HIG는 "레이어"와 Elevation을 사용하지 않습니다 — 대신 흐림(vibrancy), 그림자 및 미묘한 구분선을 사용합니다. 전체 HIG 문서는 새로운 iOS 릴리스와 함께 정기적으로 업데이트됩니다.
IT Sectr에서는 클라이언트 플랫폼에 따라 두 디자인 시스템을 모두 사용합니다. 크로스 플랫폼 Flutter 프로젝트의 경우 Material Design과 HIG의 모범 사례를 결합한 통합 디자인 시스템을 개발합니다. 이 접근 방식은 코드 중복 없이 각 플랫폼에서 네이티브 UX를 유지합니다.
UI 구축의 전통적인 접근 방식은 XML(Android) 또는 Interface Builder/코드(iOS)를 통한 명령형 레이아웃입니다. 현대적인 대안은 선언형 프레임워크로, 개발자가 각 상태에서 인터페이스가 어떻게 보여야 하는지 설명하고 프레임워크가 업데이트를 처리합니다.
Jetpack Compose는 Kotlin에서 네이티브 UI를 구축하기 위한 Google의 최신 도구 키트입니다. XML 레이아웃 대신 Kotlin 컴포저블 함수(@Composable)가 사용됩니다. Compose는 완전히 선언형입니다: 데이터가 변경되면 화면의 변경된 부분만 다시 그려집니다. 텍스트와 버튼이 있는 간단한 화면 예제:
@Composable
fun GreetingScreen() {
var count = remember { mutableStateOf(0) }
Column {
Text(text = "Нажато: $count")
Button(onClick = { count++ }) {
Text("Нажми меня")
}
}
}
SwiftUI는 2019년에 소개된 Apple의 선언형 프레임워크입니다. 통합 API를 통해 모든 Apple 플랫폼(iOS, iPadOS, macOS, watchOS, tvOS)에서 작동합니다. SwiftUI는 데이터 관리를 위해 View 구조체, @State 및 @Binding 속성을 사용하고 스타일링을 위해 수정자를 사용합니다. SwiftUI에서 위 예제와 동등한 코드:
struct GreetingView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Нажато: \(count)")
Button("Нажми меня") {
count += 1
}
}
}
}
Google의 Flutter는 자체 위젯 라이브러리를 사용합니다. Flutter에서는 모든 것이 위젯입니다 — 패딩부터 전체 화면까지. 위젯은 StatelessWidget(불변)과 StatefulWidget(상태 포함)으로 나뉩니다. 기본 컨테이너는 Container, Row, Column, Stack입니다. Flutter는 플랫폼의 네이티브 구성요소를 사용하지 않습니다 — Skia Engine을 통해 모든 것을 그리며 Android와 iOS에서 일관된 모양을 보장합니다.
class GreetingWidget extends StatefulWidget {
@override
State createState() => _GreetingWidgetState();
}
class _GreetingWidgetState extends State<GreetingWidget> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Нажато: $count'),
ElevatedButton(
onPressed: () => setState(() => count++),
child: Text('Нажми меня'),
),
],
);
}
}
선언형 프레임워크의 확산에도 불구하고 레거시 프로젝트 지원과 심층 사용자 정의를 위해 네이티브 구성요소를 이해하는 것이 중요합니다.
Android의 탐색은 Activity(화면 활동)와 Fragment(하나의 Activity 내의 조각)를 기반으로 합니다. Jetpack Navigation Component는 탐색 그래프를 통해 화면 간 전환을 단순화합니다. iOS에서 탐색은 NavigationController — 애니메이션 전환이 있는 컨트롤러 스택 — 을 통해 구현됩니다. Tab Bar 및 Bottom Navigation은 앱의 주요 섹션 간 전환을 가능하게 합니다. Drawer(사이드 메뉴) 및 Toolbar/ActionBar는 추가 작업에 사용됩니다. Android Navigation Component는 모든 새 프로젝트에 권장됩니다.
대량의 데이터를 표시하기 위해 Android는 RecyclerView — ViewHolder 재사용이 가능한 효율적인 컨테이너 — 를 사용합니다. iOS의 동등한 구성요소는 UITableView(세로 목록) 및 UICollectionView(그리드)입니다. Jetpack Compose는 LazyColumn 및 LazyVerticalGrid를 제공하고 SwiftUI는 List 및 LazyVStack/LazyHStack을 제공합니다. Lazy 구성요소의 주요 장점은 보이는 요소만 렌더링하는 것입니다.
| 플랫폼 | 목록 구성요소 | 그리드 구성요소 | 지연 로딩 |
|---|---|---|---|
| Android (View System) | RecyclerView + ListView | RecyclerView GridLayoutManager | 예 |
| Android (Compose) | LazyColumn | LazyVerticalGrid | 예 |
| iOS (UIKit) | UITableView | UICollectionView | 예 |
| iOS (SwiftUI) | List / LazyVStack | LazyVGrid | 예 |
| Flutter | ListView.builder | GridView.builder | 예 |
Android View System은 여러 레이아웃 컨테이너를 제공합니다: ConstraintLayout(유연한 제약 조건 시스템), LinearLayout(선형 배열), RelativeLayout(상대적 위치 지정), FrameLayout(레이어 스택). iOS에서 Core Auto Layout은 제약 조건 시스템(NSLayoutConstraint)을 사용하여 요소 위치를 설명합니다. SwiftUI와 Flutter는 각각 VStack/HStack/ZStack 및 Row/Column/Stack을 사용합니다.
모바일 장치 UI 구성요소는 다양한 픽셀 밀도를 고려하여 표시됩니다. 모든 화면에서 인터페이스를 동일하게 보이게 하기 위해 밀도 독립 단위가 사용됩니다.
| 단위 | 플랫폼 | 설명 |
|---|---|---|
| dp | Android | 밀도 독립 픽셀 — mdpi 화면에서 1px에 해당하는 추상 단위 |
| sp | Android | 크기 독립 픽셀 — 글꼴용, 사용자 글꼴 크기 설정을 존중 |
| pt | iOS | 포인트 — 인쇄 단위, 1x(비Retina) 화면에서 1pt = 1px |
| px | 모두 | 물리적 화면 픽셀 — 밀도가 다르므로 레이아웃에 권장되지 않음 |
화면 밀도는 다음과 같이 분류됩니다: mdpi(160dpi, 1x), hdpi(240dpi, 1.5x), xhdpi(320dpi, 2x), xxhdpi(480dpi, 3x), xxxhdpi(640dpi, 4x). 이미지를 준비할 때 모든 밀도에 대한 리소스를 만들어야 합니다: icon.png, icon_hdpi.png, icon_xhdpi.png 등. 벡터 형식(Android의 VectorDrawable, iOS의 SF Symbols)은 여러 래스터 리소스 문제를 해결합니다.
IT Sectr에서는 Figma에서 아이콘을 내보내기 위해 배율 인수를 사용합니다: iOS용 1x, 2x, 3x 및 Android용 mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi로 내보냅니다. 이는 태블릿과 폴더블 스마트폰을 포함한 모든 장치에서 선명한 표시를 보장합니다.
최신 모바일 앱 UI 구성요소는 여러 표준을 지원해야 하며, 이를 지원하지 않으면 사용자 경험이 불완전합니다.
다크 모드는 최신 애플리케이션에서 필수 옵션입니다. Material Design 3 및 iOS 13+는 다크 테마에 대한 내장 지원을 제공합니다. 색상을 반전시키는 것이 아니라 별도의 색상 팔레트(어두운 배경, 밝은 텍스트, 보조 요소에 대한 낮은 대비)를 사용하는 것이 중요합니다. 자동 전환은 장치의 시스템 테마에 연결할 수 있습니다.
최신 iPhone에는 Notch(전면 카메라 컷아웃)와 Dynamic Island가 있습니다. Android 장치에도 컷아웃과 둥근 모서리(Corner Radius)가 있습니다. Safe Area는 시스템 요소(상태 표시줄, 홈 표시기), 탐색 표시줄 및 컷아웃이 없음이 보장된 화면 영역입니다. iOS는 Safe Area Insets를 자동으로 적용합니다. Android는 WindowInsets 또는 DisplayCutout을 통한 명시적 확인이 필요합니다.
접근성은 장애가 있는 사람들이 앱을 사용할 수 있도록 보장합니다. 주요 요구 사항: TalkBack(Android) 및 VoiceOver(iOS) 지원, ImageView에 대한 올바른 contentDescription, 충분한 색상 대비(텍스트의 경우 최소 4.5:1), 글꼴 크기 조정을 위한 Dynamic Type(iOS) 지원, 시각 없이 탐색 및 제스처 대안. WCAG 2.1은 국제 접근성 표준입니다.
국제화(i18n)는 여러 언어 및 지역 형식을 지원하도록 앱을 준비하는 것입니다. 지역화(l10n)는 문자열, 날짜, 통화 및 문화적 특성을 번역하는 것입니다. Android는 리소스 디렉토리(values-ru, values-de)를 사용하고 iOS는 Localizable.strings 및 XLIFF를 사용합니다. Flutter는 ARB 번역 파일과 함께 flutter_localizations를 지원합니다.
터치 상호작용에는 많은 제스처가 포함됩니다: 탭, 길게 누르기, 스와이프, 핀치 투 줌, 당겨서 새로고침, 드래그 앤 드롭. Android는 GestureDetector를 사용하고 iOS는 UIGestureRecognizer를 사용합니다. iOS는 Taptic Engine을 통한 햅틱 피드백과 함께 3D Touch(Force Touch) 및 Haptic Touch도 지원합니다.
자주 묻는 질문
Material Design(Google)은 그림자, 레이어 및 애니메이션 전환이 있는 "재료" 은유를 사용하는 반면, HIG(Apple)는 명확성, Safe Area 및 Dynamic Type에 의존합니다. Material Design은 Android에, HIG는 iOS에 권장됩니다. 디자인 시스템 선택은 탐색에도 영향을 미칩니다: Android는 하단 탐색과 탐색 서랍을 선호하는 반면, iOS는 Tab Bar와 Navigation Controller를 선호합니다.
Jetpack Compose는 Android용 선언형 프레임워크이고 SwiftUI는 iOS용입니다. 둘 다 선언형 접근 방식을 사용하고 UI 개발을 단순화합니다. Compose는 Kotlin 및 Android Architecture Components와 더 긴밀하게 통합되고 SwiftUI는 Combine 및 전체 Apple 생태계와 통합됩니다.
반응형 디자인은 인터페이스가 화면 크기, 방향 및 픽셀 밀도에 적응하는 접근 방식입니다. 상대적 단위(dp, sp, pt), Auto Layout 또는 ConstraintLayout이 사용됩니다. 태블릿, 폴더블 장치 및 데스크톱 창(iPad Stage Manager)에는 추가 적응(Split View, 마스터-디테일 레이아웃)이 필요합니다.
Android에서는 dp(밀도 독립 픽셀)와 sp(크기 독립 픽셀), iOS에서는 pt(포인트)가 사용됩니다. px는 하드웨어 픽셀입니다. dp와 pt는 다양한 화면 밀도(mdpi(1x), hdpi(1.5x), xhdpi(2x), xxhdpi(3x), xxxhdpi(4x))에서 동일한 물리적 크기를 제공합니다.
접근성은 장애가 있는 사람들이 인터페이스를 사용할 수 있도록 합니다: 화면 읽기 프로그램 지원, 큰 텍스트, 대비. a11y가 없으면 앱은 App Store 또는 Google Play에 게시가 승인되지 않습니다. 또한 접근성은 모든 사용자의 UX를 향상시킵니다 — 예를 들어 Dynamic Type 지원은 시력이 약한 사람들을 돕습니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.