커스텀 뷰를 만들 때 고민점

2025. 7. 5. 16:42·iOS/SwiftUI
반응형

👋 들어가기 전

25

회사 일이 조금 소강 상태에 들어, 사이드 프로젝트를 본격적으로 시작하려고한다.

 

우리는 SwiftUI를 사용하기로 결정했고, 혼자 SwiftUI를 사용하여, 커스텀 뷰를 만들때

고민한 점을 시작으로, 이번 사이드 프로젝트의 여정을 기록하려고한다.


🏁 학습할 내용

  • 커스텀 뷰를 만들 때
  • ~View
  • ViewModifier
  • View Style
  • 비교

❓커스텀 뷰를 만들 때

 

SwiftUI를 통해 커스텀 뷰를 만드는 방법은 정말 많은 것 같다.

 

여기서 뷰를 만드는 의미는 실제 어떤 ~View 만드는 것이 아닌 UI적인 커스텀을 의미한다.

 

나는 대표적으로 3가지 방법을 알고있다.

  • ~View 정의
  • ViewModifier 정의
  • View Style 정의

각 내용을 먼저 알아보고 마지막에 비교를 해보자.


🏭 ~View 정의

📌 개요

SwiftUI에서 가장 기본적인 커스텀 방식

View 프로토콜을 따라는 struct를 정의해서 새로운 뷰를 만든다.

struct MyButton: View {
    let title: String
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .font(.headline)
                .padding()
                .frame(maxWidth: .infinity)
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(12)
        }
    }
}

✅ 장점

  • 재사용성과 조합성이 뛰어남내부에
  • @Binding, @State, @Environment 등 사용 가능 → 상태 기반 UI 구현 가능
  • 뷰 계층을 명확하게 분리할 수 있어 대규모 UI 구성에 유리

❌ 단점

  • 뷰 계층이 깊어질 경우 오히려 코드가 분산되어 추적이 어려울 수 있음
  • 단순한 스타일 변경에는 오버엔지니어링일 수 있음

🧑‍💻 사용 예시

  • 상태를 가진 독립적인 UI 컴포넌트 (예: 카드 뷰, 커스텀 버튼, 셀 등)
  • 뷰 계층을 분리하고자 할 때
  • View 타입 전체를 추상화하고자 할 때

✍️ ViewModifier

반복적으로 적용하는 스타일이나 효과를 커스텀 modifier로 추출할 때 사용.

구현 후, View protocol의 extension의 함수 형태로 만들면, 조금 더 쉽게 사용할 수 있다.

import SwiftUI

struct EmphasizedTextModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.system(size: 20, weight: .bold))
            .foregroundColor(.orange)
            .padding(8)
            .background(Color.orange.opacity(0.1))
            .cornerRadius(8)
    }
}

// Modifier를 더 자연스럽게 쓰기 위한 확장
extension View {
    func emphasized() -> some View {
        self.modifier(EmphasizedTextModifier())
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Text("중요한 텍스트")
                .emphasized()

            Text("일반 텍스트")
        }
        .padding()
    }
}

✅ 장점

  • 기존 뷰에 체이닝 방식으로 적용 가능 → 선언적 스타일 유지
  • 코드 중복 제거에 효과적
  • 애플도 공식 프레임워크 내부에서 매우 많이 사용 (예: .buttonStyle, .frame 등도 내부적으로 ViewModifier 기반)

❌ 단점

  • 여러 modifier가 중첩되면 구현 추적이 어려울 수 있음

🧑‍💻 사용 예시

  • 버튼, 텍스트, 이미지 등에 스타일을 공통으로 적용할 때
  • 특정 스타일을 추출

🪮 View Style

애플이 제공하는 스타일 프로토콜 (TextFieldStyle, ButtonStyle, ToggleStyle 등)을 구현하여

뷰 구성 요소의 전체적인 인터랙션과 외형을 완전히 바꾸는 방식.

import SwiftUI

struct CustomTextFieldStyle: TextFieldStyle {
    func _body(configuration: TextField<_Label>) -> some View {
        configuration
            .padding(12)
            .background(RoundedRectangle(cornerRadius: 8).stroke(Color.blue, lineWidth: 1))
            .padding(.horizontal)
    }
}

struct ContentView: View {
    @State private var name: String = ""

    var body: some View {
        TextField("이름을 입력하세요", text: $name)
            .textFieldStyle(CustomTextFieldStyle())
    }
}

✅ 장점

  • 시스템 뷰와의 일관성을 유지하면서 동작 방식까지 제어 가능
  • 스타일끼리 쉽게 교체 가능 (다형성)

❌ 단점

  • 적용 대상이 제한적 (예: TextField, Toggle, Button, ProgressView 등)
  • 복잡한 UI 조합에는 부적합

🧑‍💻 사용 예시

  • 앱 전역에서 일관된 스타일을 적용하고자 할 때
  • 특정 컴포넌트 (Button, TextField, etc.)의 기본 동작 및 외형을 커스터마이징할 때

😀 비교

마지막으로 위 내용을 표로 정리해보자.

 

구분  사용 위치 재사용성 특징 대표 예시
struct View 전체 UI ✅ 높음 컴포넌트 단위 분리 카드, 셀, 커스텀 뷰
ViewModifier 스타일 추출 ✅ 중간 선언적 스타일 유지 폰트, 테두리, 그림자
Style 프로토콜 시스템 뷰 스타일링 ✅ 높음 동작 + 외형 변경 TextFieldStyle

출처

https://developer.apple.com/documentation/swiftui/view

 

View | Apple Developer Documentation

A type that represents part of your app’s user interface and provides modifiers that you use to configure views.

developer.apple.com

https://developer.apple.com/documentation/swiftui/viewmodifier

 

ViewModifier | Apple Developer Documentation

A modifier that you apply to a view or another view modifier, producing a different version of the original value.

developer.apple.com

https://developer.apple.com/documentation/swiftui/view-styles

 

View styles | Apple Developer Documentation

Apply built-in and custom appearances and behaviors to different types of views.

developer.apple.com

반응형

'iOS > SwiftUI' 카테고리의 다른 글

.contentShape  (0) 2025.07.19
커스텀 SwipePopNavigationStack 구현하기  (6) 2025.07.13
@Observable 매크로  (0) 2025.07.03
Custom Carousel 만들기  (0) 2025.03.16
.scrollTargetLayout  (0) 2025.03.15
'iOS/SwiftUI' 카테고리의 다른 글
  • .contentShape
  • 커스텀 SwipePopNavigationStack 구현하기
  • @Observable 매크로
  • Custom Carousel 만들기
Hamp
Hamp
남들에게 보여주기 부끄러운 잡다한 글을 적어 나가는 자칭 기술 블로그입니다.
  • Hamp
    Hamp의 분리수거함
    Hamp
  • 전체
    오늘
    어제
    • 분류 전체보기 (304)
      • CS (30)
        • 객체지향 (2)
        • Network (7)
        • OS (6)
        • 자료구조 (1)
        • LiveStreaming (3)
        • 이미지 (1)
        • 잡다한 질문 정리 (0)
        • Hardware (2)
        • 이론 (6)
        • 컴퓨터 그래픽스 (0)
      • Firebase (3)
      • Programing Langauge (37)
        • swift (32)
        • python (4)
        • Kotlin (1)
      • iOS (132)
        • UIKit (37)
        • Combine (1)
        • SwiftUI (32)
        • Framework (7)
        • Swift Concurrency (22)
        • Tuist (6)
        • Setting (11)
        • Modularization (1)
        • Instruments (6)
      • PS (59)
        • 프로그래머스 (24)
        • 백준 (13)
        • LeetCode (19)
        • 알고리즘 (3)
      • Git (18)
        • 명령어 (4)
        • 이론 (2)
        • hooks (1)
        • config (2)
        • action (7)
      • Shell Script (2)
      • Linux (6)
        • 명령어 (5)
      • Spring (13)
        • 어노테이션 (1)
        • 튜토리얼 (11)
      • CI-CD (4)
      • Android (0)
        • Jetpack Compose (0)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Spring
    dfs
    백준
    UIKit
    GIT
    AVFoundation
    lifecycle
    Swift
    protocol
    dp
    property
    dispatch
    SwiftUI
    투포인터
    IOS
    boostcamp
    Tuist
    CS
    concurrency
    프로그래머스
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.0
Hamp
커스텀 뷰를 만들 때 고민점
상단으로

티스토리툴바