SwiftUI의 Form은 iOS의 Settings 디자인을 따라 구조화된 설정 및 데이터 입력 인터페이스를 구축하기 위한 컨테이너 컴포넌트입니다. 이 컴포넌트는 자동으로 컨트롤을 섹션으로 그룹화하여 시스템 간격과 스타일을 적용하므로 개발자가 수동으로 구분선과 색상을 조정할 필요가 없습니다. Apple Developer Documentation (2025)에 따르면, Form은 각 플랫폼에 맞게 모양을 조정합니다 — iOS의 그룹화된 테이블부터 macOS의 표준 목록까지 — 통합된 API를 유지하면서.
핵심 포인트
Form은 입력 폼과 설정 화면을 만들기 위해 설계된 특수한 SwiftUI 컨테이너입니다. List의 동작을 상속하면서 플랫폼별 스타일을 추가합니다: iOS에서 Form은 모서리가 둥근 섹션이 있는 그룹화된 테이블로 표시됩니다. macOS에서는 체크박스와 컨트롤이 있는 표준 시스템 목록으로 나타납니다.
VStack 및 HStack을 사용한 수동 레이아웃과 달리, Form은 자동으로 요소 간 간격을 정리하고, 구분선을 추가하며, 시스템 테마(라이트 또는 다크)에 따라 모양을 조정합니다. 개발자는 논리적 구조만 설명합니다: 그룹화를 위한 Section과 내부의 컨트롤. 폼 자체가 특정 플랫폼에서 Picker, Toggle 또는 Stepper를 시각적으로 배치하는 방법을 결정합니다.
Form은 모든 표준 SwiftUI 입력 요소를 지원합니다: 텍스트용 TextField, 비밀번호용 SecureField, 목록 선택용 Picker, 켜기/끄기용 Toggle, 범위용 Slider, 단계별 값용 Stepper, 날짜용 DatePicker. 각 요소는 자동으로 대상 플랫폼의 Apple HIG(Human Interface Guidelines)에 맞는 스타일을 얻습니다.
시각적 유사성에도 불구하고, Form과 List는 다른 작업을 해결합니다. List는 스와이프 동작과 행 편집 기능이 있는 스크롤 가능한 데이터 목록을 표시하기 위한 범용 컨테이너입니다. Form은 데이터 입력 및 설정을 위한 특수 컨테이너로, 시스템 컨트롤 스타일에 최적화되어 있습니다.
List는 동적 데이터 표시에 적합합니다: 뉴스 피드, 채팅, 제품 카탈로그. Form은 예측 가능한 필드 세트가 있는 정적 화면에 적합합니다: 사용자 프로필, 앱 설정, 등록 양식. 주요 차이점: Form 요소는 대화형 컨트롤이 될 수 있는 반면, List 행은 대부분 데이터를 표시하고 탭에 탐색 또는 동작으로 응답합니다.
| 매개변수 | Form | List |
|---|---|---|
| 목적 | 데이터 입력, 설정 | 목록 표시 |
| 섹션 스타일 | Grouped(iOS), 시스템(macOS) | Plain 또는 Grouped |
| 컨트롤 | Picker, Toggle, Slider, Stepper | 제한적(버튼) |
| 동적 데이터 | 제한적(Section 내 ForEach) | 전체 지원 |
| 스와이프 동작 | 예, swipeActions | 예, swipeActions |
Apple Human Interface Guidelines (2025)에 따르면, Form은 한 화면에 3~20개의 컨트롤이 있고 섹션으로 나누면 사용성이 향상되는 설정 및 입력 화면에 사용해야 합니다.
Section은 Form의 주요 구성 요소로, 논리적으로 관련된 요소를 함께 그룹화할 수 있습니다. 각 Section에는 헤더, 푸터 및 내부에 임의 개수의 컨트롤이 있을 수 있습니다. 시스템은 자동으로 섹션 간 간격을 추가하고 각 섹션을 모서리가 둥근 시각적 블록으로 감쌉니다.
Section 사용은 폼 가독성에 중요합니다: 의미별로 그룹화된 요소는 사용자가 처리하기 더 쉽습니다. 예를 들어, 프로필 설정 화면에서 «개인 데이터», «알림», «보안»을 개별 섹션으로 분리할 수 있습니다. 각 섹션에는 설명 텍스트가 있는 푸터가 포함될 수 있으며, 시스템은 요소 그룹 아래에 더 작은 글꼴로 표시합니다.
Form {
Section(header: Text("프로필")) {
TextField("이름", text: $name)
TextField("Email", text: $email)
}
Section(header: Text("알림"),
footer: Text("회의 중 비활성화")) {
Toggle("Push notifications", isOn: $pushEnabled)
Toggle("Email notifications", isOn: $emailEnabled)
}
}
예제에서 첫 번째 섹션 «Profile»에는 푸터 없는 두 개의 텍스트 필드가 포함되고, 두 번째 섹션 «Notifications»에는 그룹 아래 설명과 함께 두 개의 토글이 포함됩니다. 푸터는 자동으로 간격을 추가하고 caption 글꼴 스타일을 사용합니다. Section은 헤더 없이 푸터를 가지거나 푸터 없이 헤더를 가질 수 있습니다.
Form은 모든 표준 SwiftUI 입력 요소를 지원합니다. Picker는 Form 내에서 자동으로 iOS에서 별도 선택 화면으로 전환되는 탐색 행으로 표시됩니다. Toggle은 오른쪽에 정렬된 스위치가 있는 행으로 나타납니다. TextField는 플레이스홀더가 있는 시스템 입력 스타일을 얻습니다.
숫자 값의 경우 Stepper(단계별 변경)와 Slider(범위 내 부드러운 변경)가 사용됩니다. DatePicker는 여러 모드를 지원합니다: date, time, dateAndTime. 색상 선택에는 ColorPicker를 사용할 수 있습니다. 각 요소는 추가 코드 없이 플랫폼에 적응합니다 — iOS에서는 컨트롤이 네이티브 UIKit 스타일을 사용하고, macOS에서는 AppKit을 사용합니다.
| 요소 | 목적 | Form 스타일 |
|---|---|---|
| TextField | 텍스트 입력 | 플레이스홀더가 있는 행 |
| SecureField | 비밀번호 입력 | 숨겨진 문자가 있는 행 |
| Picker | 목록 선택 | 선택 화면으로의 NavigationLink |
| Toggle | 켜기/끄기 | 스위치가 있는 행 |
| Slider | 값 범위 | 수평 슬라이더 |
| DatePicker | 날짜/시간 선택 | 컴팩트 또는 휠 스타일 |
Form 내부의 사용자 정의 컨트롤의 경우, 모든 SwiftUI View를 사용할 수 있습니다 — 표준 섹션 동작을 상속합니다. 그러나 HIG 준수를 보장하고 추가 구성 없이 접근성(VoiceOver, Dynamic Type)을 지원하므로 시스템 요소를 따르는 것이 좋습니다.
Form을 사용하여 등록 화면을 만들어 보겠습니다. 폼에는 네 개의 섹션이 있습니다: 개인 데이터, 역할 선택, 구독 설정, 제출 버튼. 그룹화를 위해 Section과 표준 SwiftUI 컨트롤을 사용합니다.
struct RegistrationForm: View {
@State private var name = ""
@State private var email = ""
@State private var role = "Developer"
@State private var agreedToTerms = false
let roles = ["Developer", "Designer", "Manager"]
var body: some View {
NavigationStack {
Form {
Section(header: Text("개인 정보")) {
TextField("Name", text: $name)
TextField("Email", text: $email)
.keyboardType(.emailAddress)
}
Section(header: Text("역할")) {
Picker("Select role", selection: $role) {
ForEach(roles, id: \.self) { role in
Text(role).tag(role)
}
}
}
Section {
Toggle("Agree to terms", isOn: $agreedToTerms)
}
Section {
Button("등록") {
submitForm()
}
.disabled(!agreedToTerms)
}
}
.navigationTitle("Registration")
}
}
private func submitForm() { }
}
폼은 네 개의 Section으로 나뉩니다: 두 개의 텍스트 필드가 있는 개인 데이터, Picker를 통한 역할 선택, Toggle을 통한 약관 동의, 등록 버튼. 버튼은 사용자가 약관에 동의할 때까지 비활성화됩니다 — 이는 Form 내부의 유효성 검사 예입니다. NavigationStack은 제목을 추가하고 Picker가 iOS에서 별도 선택 화면을 열 수 있게 합니다.
struct SettingsForm: View {
@State private var volume: Double = 0.5
@State private var isDarkMode = false
@State private var reminderDate = Date()
var body: some View {
NavigationStack {
Form {
Section(header: Text("모양")) {
Toggle("Dark mode", isOn: $isDarkMode)
Slider(value: $volume, in: 0...1) {
Text("볼륨")
}
}
Section(header: Text("알림"),
footer: Text("선택한 시간에 알림을 받게 됩니다")) {
DatePicker("Remind at",
selection: $reminderDate,
displayedComponents: .hourAndMinute)
}
Section {
NavigationLink("Advanced Settings",
destination: AdvancedSettingsView())
}
}
.navigationTitle("Settings")
}
}
}
이 예제는 Form 내부에서 Slider, DatePicker 및 NavigationLink의 조합을 보여줍니다. DatePicker는 시간만 표시하기 위해 hourAndMinute 모드를 사용합니다. 마지막 섹션의 NavigationLink는 고급 설정 화면으로의 전환을 만듭니다 — Settings 스타일 인터페이스의 일반적인 패턴입니다. 섹션 헤더와 푸터는 폼을 자체 문서화하게 만듭니다: 사용자는 각 컨트롤이 어떤 그룹에 속하는지 즉시 이해합니다.
자주 묻는 질문
Form은 데이터 입력 및 설정에 최적화되어 있습니다: 컨트롤은 시스템 스타일을 얻고, 섹션은 둥근 모서리와 간격을 얻습니다. List는 데이터 표시를 위한 범용 컨테이너입니다. Form은 설정 화면에 적합하고, List는 채팅, 피드, 카탈로그에 적합합니다.
예, Form 내부의 Picker는 자동으로 iOS에서 선택된 값과 목록 선택을 위한 NavigationLink가 있는 행으로 표시됩니다. macOS에서는 Picker가 스타일에 따라 드롭다운 목록 또는 라디오 그룹으로 나타납니다. 추가 코드 없이 적응이 이루어집니다.
모든 SwiftUI View를 Form 또는 Section 내에 배치할 수 있습니다. 사용자 정의 컨트롤의 경우, 표준 섹션 간격을 상속하고 시스템 글꼴을 통해 Dynamic Type을 지원하는 것이 좋습니다. 모든 기기에서 폼이 올바르게 표시되도록 고정 크기와 색상을 피하세요.
예, 콘텐츠가 화면 높이를 초과하면 Form이 자동으로 ScrollView로 감싸집니다. ScrollView를 수동으로 추가할 필요가 없습니다 — 시스템이 스크롤 필요성을 자동으로 결정합니다. 스크롤되지 않아야 하는 폼의 경우, 고정 높이의 VStack을 사용하세요.
iOS의 Form은 .formStyle(.grouped) 수정자를 통해 두 가지 스타일을 지원합니다 — 둥근 섹션이 있는 표준 그룹화된 보기. macOS에서는 다중 열 레이아웃의 .formStyle(.columns)을 사용할 수 있습니다. 스타일은 전체 Form에 한 번에 적용되며 내부의 모든 요소의 시각적 표현을 변경합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.