Communitygithub.com

apple-hig-designer

Apple HIG(인간 인터페이스 가이드라인)에 따라 iOS 앱을 디자인합니다. iPhone, iPad, Apple Watch용 네이티브 컴포넌트를 생성하고, 디자인을 검증하며, 접근성 준수 여부를 확인합니다.

apple-hig-designer란 무엇인가요?

이 스킬은 Apple의 인간 인터페이스 가이드라인(HIG)에 따라 iOS 앱을 디자인하고 구축하는 AI 어시스턴트입니다. SwiftUI 및 UIKit 컴포넌트를 생성하고, Apple HIG 준수 여부를 검증하며, VoiceOver, Dynamic Type, 색상 대비와 같은 접근성 기능을 보장합니다. Clarity, Deference, Depth와 같은 Apple의 디자인 원칙을 적용하고, SF 글꼴 시스템과 시맨틱 컬러를 사용하며, 8포인트 그리드 시스템과 Safe Area를 따릅니다. 네비게이션 바, 탭 바, 리스트, 시트(모달), 버튼, 텍스트 필드, 토글, 피커 등 주요 UI 컴포넌트에 대한 코드 예제와 지침을 제공하며, WCAG AA 접근성 기준을 충족시키기 위한 색상 대비 및 접근성 관련 세부 지침을 포함합니다. Claude Code, Cursor, Codex 등 다양한 AI 에이전트 플랫폼에서 사용 가능하며, macOS에서 SwiftUI 개발 환경을 지원합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Bershmern/my-skills/tree/HEAD/skills/apple-hig-designer

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Apple HIG Designer

Apple의 인간 인터페이스 가이드라인(HIG)을 따라 아름답고 네이티브한 iOS 앱을 디자인하세요. 네이티브 컴포넌트, 적절한 타이포그래피, 시맨틱 컬러, Apple의 디자인 원칙을 사용하여 접근성이 뛰어나고 직관적인 인터페이스를 만듭니다.

이 스킬이 하는 일

Apple의 가이드라인을 따라 네이티브한 느낌을 주는 iOS 앱을 디자인하고 구축하는 데 도움을 줍니다:

  • iOS 컴포넌트 생성 - SwiftUI 및 UIKit 컴포넌트를 생성합니다.
  • 디자인 검증 - Apple HIG 준수 여부를 확인합니다.
  • 접근성 보장 - VoiceOver, Dynamic Type, 색상 대비를 지원합니다.
  • 디자인 원칙 적용 - Clarity(명확성), Deference(경의), Depth(깊이)를 적용합니다.
  • 시맨틱 컬러 사용 - 자동 다크 모드를 지원합니다.
  • 타이포그래피 구현 - San Francisco 글꼴 시스템을 사용합니다.
  • 간격 준수 - 8포인트 그리드 시스템과 Safe Area를 따릅니다.

Apple의 디자인 원칙

1. Clarity (명확성)

콘텐츠를 명확하고 집중되게 만드세요.

텍스트는 모든 크기에서 읽기 쉬워야 하며, 아이콘은 정확하고 명료해야 하며, 장식은 미묘하고 적절해야 하며, 기능성에 초점을 맞춘 디자인이어야 합니다.

// ✅ 명확하고 집중된 콘텐츠
Text("Welcome back, Sarah")
    .font(.title)
    .foregroundColor(.primary)

// ❌ 불명확하고 복잡함
Text("Welcome back, Sarah!!!")
    .font(.title)
    .foregroundColor(.red)
    .background(.yellow)
    .overlay(Image(systemName: "star.fill"))

2. Deference (경의)

UI는 사용자가 콘텐츠를 이해하고 상호작용하도록 돕지만, 콘텐츠와 경쟁해서는 안 됩니다.

인터페이스는 콘텐츠에 경의를 표하며, 콘텐츠에 집중할 수 있도록 가벼운 시각적 처리를 사용합니다.

// ✅ 콘텐츠 중심
VStack(alignment: .leading, spacing: 8) {
    Text("Article Title")
        .font(.headline)
    Text("Article content goes here...")
        .font(.body)
        .foregroundColor(.secondary)
}
.padding()

// ❌ 방해가 되는 UI
VStack(spacing: 8) {
    Text("Article Title")
        .font(.headline)
        .foregroundColor(.white)
        .background(.blue)
        .border(.red, width: 3)
}

3. Depth (깊이)

시각적 계층과 사실적인 모션은 계층 구조를 전달하고 관계를 이해하는 데 도움을 줍니다.

뚜렷한 시각적 레이어와 사실적인 모션은 생동감을 주고 이해를 돕습니다. 터치와 발견 가능성은 즐거움을 높이며 컨텍스트를 잃지 않고 기능에 접근할 수 있게 합니다.

// ✅ 명확한 깊이 계층
ZStack {
    Color(.systemBackground)

    VStack {
        // 그림자가 있는 카드
        CardView()
            .shadow(radius: 8)
    }
}

// 깊이를 위한 블러 사용
Text("Content")
    .background(.ultraThinMaterial)

iOS UI 컴포넌트

탐색 패턴

1. 네비게이션 바

탐색 및 액션을 위한 상단 바입니다.

NavigationStack {
    List {
        Text("Item 1")
        Text("Item 2")
    }
    .navigationTitle("Title")
    .navigationBarTitleDisplayMode(.large)
    .toolbar {
        ToolbarItem(placement: .navigationBarTrailing) {
            Button("Add") {
                // Action
            }
        }
    }
}

가이드라인:

  • 최상위 뷰에는 large 제목을 사용하세요.
  • 상세 뷰에는 inline 제목을 사용하세요.
  • 액션은 현재 컨텍스트와 관련 있어야 합니다.
  • 최대 2-3개의 툴바 항목.

2. 탭 바

최상위 목적지를 위한 하단 탐색입니다.

TabView {
    HomeView()
        .tabItem {
            Label("Home", systemImage: "house")
        }

    SearchView()
        .tabItem {
            Label("Search", systemImage: "magnifyingglass")
        }

    ProfileView()
        .tabItem {
            Label("Profile", systemImage: "person")
        }
}

가이드라인:

  • 최대 3-5개의 탭.
  • 아이콘에는 SF Symbols를 사용하세요.
  • 레이블은 간결해야 합니다(한 단어).
  • 탭을 숨기거나 비활성화하지 마세요.
  • 같은 뷰에서 탭 바와 툴바를 함께 사용하지 마세요.

3. 리스트

스크롤 가능한 항목 목록입니다.

List {
    Section("Today") {
        ForEach(items) { item in
            NavigationLink {
                DetailView(item: item)
            } label: {
                HStack {
                    Image(systemName: item.icon)
                        .foregroundColor(.accentColor)
                    Text(item.title)
                }
            }
        }
    }
}
.listStyle(.insetGrouped)

리스트 스타일:

  • .plain - 가장자리에서 가장자리까지의 행
  • .insetGrouped - 둥근 모서리, 여백이 있는 섹션 (iOS 기본값)
  • .sidebar - 사이드바 탐색용

4. 시트 (모달)

콘텐츠를 모달로 표시합니다.

struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        Button("Show Details") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            DetailView()
                .presentationDetents([.medium, .large])
        }
    }
}

시트 디텐트(크기):

  • .medium - 화면 절반
  • .large - 전체 화면
  • 사용자 지정 높이 가능

폼 컨트롤

1. 버튼

기본 액션 컨트롤입니다.

// 채워진 버튼 (기본 액션)
Button("Continue") {
    // Action
}
.buttonStyle(.borderedProminent)

// 테두리 버튼 (보조 액션)
Button("Cancel") {
    // Action
}
.buttonStyle(.bordered)

// 일반 버튼 (3차 액션)
Button("Learn More") {
    // Action
}
.buttonStyle(.plain)

버튼 계층:

  1. Prominent - 기본 액션 (화면당 하나)
  2. Bordered - 보조 액션
  3. Plain - 3차 액션, 링크

가이드라인:

  • 최소 터치 대상: 44x44 포인트
  • 버튼 레이블에는 동사를 사용하세요.
  • 파괴적인 액션은 확인을 요구하세요.

2. 텍스트 필드

텍스트 입력 컨트롤입니다.

@State private var username = ""
@State private var password = ""

VStack(alignment: .leading, spacing: 16) {
    // 표준 텍스트 필드
    TextField("Username", text: $username)
        .textFieldStyle(.roundedBorder)
        .textContentType(.username)
        .textInputAutocapitalization(.never)
        .autocorrectionDisabled()

    // 보안 필드
    SecureField("Password", text: $password)
        .textFieldStyle(.roundedBorder)
        .textContentType(.password)
}

텍스트 콘텐츠 유형:

  • .username - 사용자 이름 필드
  • .password - 비밀번호 필드
  • .emailAddress - 이메일 필드
  • .telephoneNumber - 전화번호
  • .creditCardNumber - 신용카드

3. 토글

부울 컨트롤 (스위치)입니다.

@State private var isEnabled = false

Toggle("Enable notifications", isOn: $isEnabled)
    .toggleStyle(.switch)

가이드라인:

  • 레이블은 토글이 제어하는 대상을 설명합니다.
  • 효과는 즉각적이어야 합니다.
  • 이진 선택에만 사용하세요.

4. 피커

선택 컨트롤입니다.

@State private var selectedSize = "Medium"
let sizes = ["Small", "Medium", "Large"]

// 메뉴 스타일
Picker("Size", selection: $selectedSize) {
    ForEach(sizes, id: \.self) { size in
        Text(size).tag(size)
    }
}
.pickerStyle(.menu)

// 세그먼트 스타일 (2-5개 옵션용)
Picker("Size", selection: $selectedSize) {
    ForEach(sizes, id: \.self) { size in
        Text(size).tag(size)
    }
}
.pickerStyle(.segmented)

피커 스타일:

  • .menu - 드롭다운 메뉴 (기본값)
  • .segmented - 세그먼트 컨트롤 (2-5개 옵션)
  • .wheel - 스크롤 가능한 휠
  • .inline - 인라인 리스트 (폼 내에서)

카드 및 컨테이너

카드 뷰

struct CardView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Title")
                .font(.headline)

            Text("Description goes here with some details about the content.")
                .font(.subheadline)
                .foregroundColor(.secondary)
                .lineLimit(2)

            Spacer()

            Button("Action") {
                // Action
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .frame(width: 300, height: 200)
        .background(Color(.systemBackground))
        .cornerRadius(12)
        .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
    }
}

타이포그래피

San Francisco 글꼴 시스템

최적의 가독성을 위해 설계된 Apple의 시스템 글꼴입니다.

// Dynamic Type 텍스트 스타일
Text("Large Title").font(.largeTitle)      // 34pt
Text("Title").font(.title)                 // 28pt
Text("Title 2").font(.title2)              // 22pt
Text("Title 3").font(.title3)              // 20pt
Text("Headline").font(.headline)           // 17pt semibold
Text("Body").font(.body)                   // 17pt regular
Text("Callout").font(.callout)             // 16pt
Text("Subheadline").font(.subheadline)     // 15pt
Text("Footnote").font(.footnote)           // 13pt
Text("Caption").font(.caption)             // 12pt
Text("Caption 2").font(.caption2)          // 11pt

Dynamic Type을 지원하는 사용자 정의 글꼴

// Dynamic Type에 따라 크기가 조정되는 사용자 정의 글꼴
Text("Custom Text")
    .font(.custom("YourFont-Regular", size: 17, relativeTo: .body))

글꼴 두께

Text("Light").fontWeight(.light)
Text("Regular").fontWeight(.regular)
Text("Medium").fontWeight(.medium)
Text("Semibold").fontWeight(.semibold)
Text("Bold").fontWeight(.bold)
Text("Heavy").fontWeight(.heavy)

타이포그래피 가이드라인

권장 사항:

  • ✅ 일관성을 위해 시스템 글꼴(San Francisco)을 사용하세요.
  • ✅ 접근성을 위해 Dynamic Type을 지원하세요.
  • ✅ 시맨틱 텍스트 스타일(.headline, .body 등)을 사용하세요.
  • ✅ 본문 텍스트 최소 크기: 17pt
  • ✅ 줄 간격: 글꼴 크기의 120-145%

금지 사항:

  • ❌ 너무 많은 글꼴 크기를 사용하지 마세요 (시스템 스타일을 고수하세요).
  • ❌ 텍스트를 11pt보다 작게 만들지 마세요.
  • ❌ 긴 텍스트에 모두 대문자를 사용하지 마세요.
  • ❌ Dynamic Type을 비활성화하지 마세요.

색상

시맨틱 컬러

라이트/다크 모드에 자동으로 적응하는 색상입니다.

// UI 요소 색상
Color(.label)                    // 기본 텍스트
Color(.secondaryLabel)           // 보조 텍스트
Color(.tertiaryLabel)            // 3차 텍스트
Color(.quaternaryLabel)          // 워터마크 텍스트

Color(.systemBackground)         // 기본 배경
Color(.secondarySystemBackground) // 보조 배경
Color(.tertiarySystemBackground)  // 3차 배경

Color(.systemFill)               // 채우기 색상
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)

Color(.separator)                // 구분선
Color(.opaqueSeparator)          // 불투명 구분선

시스템 색상

// 표준 시스템 색상 (다크 모드에 적응)
Color(.systemRed)
Color(.systemOrange)
Color(.systemYellow)
Color(.systemGreen)
Color(.systemMint)
Color(.systemTeal)
Color(.systemCyan)
Color(.systemBlue)
Color(.systemIndigo)
Color(.systemPurple)
Color(.systemPink)
Color(.systemBrown)
Color(.systemGray)

다크 모드를 지원하는 사용자 정의 색상

// 적응형 색상 정의
extension Color {
    static let customBackground = Color("CustomBackground")
}

// Assets.xcassets에서 색상 세트를 다음과 같이 생성:
// - Any Appearance: #FFFFFF
// - Dark Appearance: #000000

색상 대비 가이드라인

WCAG AA 준수:

  • 일반 텍스트: 최소 4.5:1 대비율
  • 큰 텍스트(24pt+): 최소 3:1 대비율
  • UI 컴포넌트: 3:1 대비율

사용자 정의 색상:

  • 증가된 대비 모드에서 테스트하세요.
  • 중요한 텍스트의 경우 7:1을 목표로 하세요.
  • 두 모드 모두에서 충분한 대비를 제공하세요.

간격 및 레이아웃

8포인트 그리드 시스템

모든 간격은 8의 배수여야 합니다.

// 간격 값
.padding(8)      // 8pt
.padding(16)     // 16pt (표준)
.padding(24)     // 24pt
.padding(32)     // 32pt
.padding(40)     // 40pt
.padding(48)     // 48pt

// 가장자리별 패딩
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)

Safe Areas

디바이스 Safe Area를 존중하세요.

// Safe Area 내의 콘텐츠 (기본값)
VStack {
    Text("Content")
}

// Safe Area 너머로 확장
VStack {
    Color.blue
}
.ignoresSafeArea()

// 상단만 확장
VStack {
    Color.blue
}
.ignoresSafeArea(edges: .top)

터치 대상

최소 상호작용 크기: 44x44 포인트.

Button("Tap") {
    // Action
}
.frame(minWidth: 44, minHeight: 44)

간격 가이드라인

// 컴포넌트 간격
VStack(spacing: 8) {       // 좁은 간격
    Text("Line 1")
    Text("Line 2")
}

VStack(spacing: 16) {      // 표준 간격
    Text("Section 1")
    Text("Section 2")
}

VStack(spacing: 24) {      // 넓은 간격
    SectionView()
    SectionView()
}

접근성

VoiceOver 지원

시각 장애 및 저시력 사용자를 위한 화면 읽기 프로그램.

// 접근 가능한 레이블
Image(systemName: "heart.fill")
    .accessibilityLabel("Favorite")

// 접근 가능한 값
Slider(value: $volume)
    .accessibilityLabel("Volume")
    .accessibilityValue("\(Int(volume * 100))%")

// 접근 가능한 힌트
Button("Share") {
    share()
}
.accessibilityHint("Shares this item with others")

// 요소 그룹화
HStack {
    Image(systemName: "person")
    Text("John Doe")
}
.accessibilityElement(children: .combine)

// VoiceOver에서 숨기기
Image("decorative")
    .accessibilityHidden(true)

Dynamic Type

사용자가 선호하는 텍스트 크기를 지원하세요.

// 시스템 글꼴로 자동 지원
Text("This text scales")
    .font(.body)

// 크기 제한 (필요한 경우)
Text("This text has limits")
    .font(.body)
    .dynamicTypeSize(...DynamicTypeSize.xxxLarge)

// Dynamic Type을 지원하는 사용자 정의 글꼴
Text("Custom font")
    .font(.custom("YourFont", size: 17, relativeTo: .body))

색맹

색맹 사용자를 위해 디자인하세요.

// 색상에만 의존하지 마세요
HStack {
    Image(systemName: "checkmark.circle.fill")
        .foregroundColor(.green)
    Text("Success")
}

// 색상만 사용하지 않음
Circle()
    .fill(.green)
// ❌ 색상만

// 모양/아이콘과 함께 사용하는 것이 더 좋음
HStack {
    Image(systemName: "checkmark.circle.fill")
    Circle().fill(.green)
}
// ✅ 색상 + 모양

동작 줄이기

사용자의 동작 선호도를 존중하세요.

@Environment(\.accessibilityReduceMotion) var reduceMotion

var animation: Animation {
    reduceMotion ? .none : .spring()
}

Button("Animate") {
    withAnimation(animation) {
        // Animate
    }
}

대비 증가

고대비 모드를 지원하세요.

@Environment(\.accessibilityIncreaseContrast) var increaseContrast

var backgroundColor: Color {
    increaseContrast ? Color(.systemBackground) : Color(.secondarySystemBackground)
}

VStack {
    Text("Content")
        .foregroundColor(.primary)
}
.background(backgroundColor)

적응형 레이아웃

iOS 앱은 모든 디바이스와 방향에서 잘 작동해야 합니다.

크기 클래스

@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.verticalSizeClass) var verticalSizeClass

var layout: some View {
    if horizontalSizeClass == .regular {
        // iPad, 가로 방향 iPhone Plus
        HStack {
            SidebarView()
            ContentView()
        }
    } else {
        // iPhone (세로)
        NavigationStack {
            ContentView()
        }
    }
}

회전 지원

struct AdaptiveView: View {
    @Environment(\.verticalSizeClass) var verticalSizeClass

    var body: some View {
        if verticalSizeClass == .compact {
            // 가로 방향
            HStack {
                Image("hero")
                    .frame(maxWidth: .infinity)
                VStack {
                    Text("Title")
                    Text("Description")
                }
                .frame(maxWidth: .infinity)
            }
        } else {
            // 세로 방향
            VStack {
                Image("hero")
                    .frame(maxHeight: 300)
                VStack {
                    Text("Title")
                    Text("Description")
                }
            }
        }
    }
}

애니메이션

표준 애니메이션

// 암시적 애니메이션
.animation(.default, value: isExpanded)

// 명시적 애니메이션
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
    isExpanded.toggle()
}

Apple의 HIG 모션 가이드라인

// 부드러운 전환
.transition(.opacity)
.transition(.slide)
.transition(.move(edge: .bottom))
.transition(.scale)

// SwiftUI 전환
.transition(.asymmetric(
    insertion: .move(edge: .trailing),
    removal: .move(edge: .leading)
))

// 지속 시간 (초)
.animation(.easeInOut(duration: 0.3), value: state)
.animation(.default, value: state)
.animation(.interactiveSpring(), value: state)  // 드래그 상호작용용

햅틱

// 햅틱 피드백 가져오기
import UIKit

let feedback = UIImpactFeedbackGenerator(style: .medium)
feedback.impactOccurred()

// 선택 피드백
let selectionFeedback = UISelectionFeedbackGenerator()
selectionFeedback.selectionChanged()

// 알림 피드백
let notificationFeedback = UINotificationFeedbackGenerator()
notificationFeedback.notificationOccurred(.success)
notificationFeedback.notificationOccurred(.warning)
notificationFeedback.notificationOccurred(.error)

디자인 리소스

Apple HIG 웹사이트

Xcode 템플릿

  • SwiftUI 앱 템플릿
  • UIKit 앱 템플릿
  • Tabbed 앱 템플릿

디자인 도구

  • Sketch
  • Figma
  • Adobe XD

사용 예시

모든 컴포넌트를 사용한 완전한 설정 화면 예시

struct SettingsView: View {
    @AppStorage("notifications") private var notifications = true
    @AppStorage("darkMode") private var darkMode = false
    @State private var selectedLanguage = "English"

    let languages = ["English", "Spanish", "French", "Japanese"]

    var body: some View {
        NavigationStack {
            Form {
                Section("Profile") {
                    HStack {
                        Image(systemName: "person.circle.fill")
                            .font(.largeTitle)
                            .foregroundColor(.accentColor)
                        VStack(alignment: .leading) {
                            Text("John Doe")
                                .font(.headline)
                            Text("[email protected]")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }
                    }
                    .accessibilityElement(children: .combine)
                }

                Section("Preferences") {
                    Toggle("Enable Notifications", isOn: $notifications)
                    Toggle("Dark Mode", isOn: $darkMode)
                    Picker("Language", selection: $selectedLanguage) {
                        ForEach(languages, id: \.self) { lang in
                            Text(lang).tag(lang)
                        }
                    }
                }

                Section("Account") {
                    Button("Sign Out") {
                        signOut()
                    }
                    .foregroundColor(.red)
                    Button("Delete Account") {
                        confirmDelete()
                    }
                    .foregroundColor(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }

    func signOut() { /* ... */ }
    func confirmDelete() { /* ... */ }
}

직접 시도해보세요

  1. 이 예시를 복사하여 Xcode 프로젝트에 붙여넣으세요.
  2. 디바이스 회전을 테스트하세요.
  3. 접근성 검사기를 실행하세요.
  4. 다크 모드로 전환하세요.
  5. Dynamic Type 크기를 변경하세요.

Apple HIG 디자이너를 사용해 주셔서 감사합니다! 세심하고, 네이티브하며, 접근성이 뛰어난 iOS 앱을 만드는 데 도움이 되길 바랍니다.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬