관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 1. @resultBuilder 이해하기 - 만들어진 이유 본문

iOS 응용 (swift)

[iOS - swift] 1. @resultBuilder 이해하기 - 만들어진 이유

jake-kim 2023. 8. 17. 01:29

1. @resultBuilder 이해하기 - 만들어진 이유

2. @resultBuilder 이해하기 - 응용하여 깔끔한 코드 만들기

3. @resultBuilder 이해하기 - 선언형 UI 만들기 (Declarative UI)

 

@resultBuilder 개념

  • Swift 5.4에 도입
  • 이름이 result builder인 이유?
    • ResultBuilder는 코드 블록 내에서 여러 개의 값을 취합하여 return 키워드 없이 하나의 결과로 반환하는 것을 도와주는 기능이기 때문
    • return 부분의 옵션을 설정하여 return 키워드를 없이 사용할수 있거나, 콤마를 사용하지 않고 배열을 만들 수 있는 등의 기능 사용 가능
  • 목적: 빌딩을 간소화하는 것

ex) 여러 표현식을 단일 값으로 결합하여 결과를 빌드하는 경우

// resultBuilder를 사용하지 않은 경우 - 콤마 존재 o
func getPersonMock() -> [Person] {
  [
    Person(name: "jake", age: 20),
    Person(name: "kim", age: 22),
    Person(name: "paul", age: 32)
  ]
}

// resultBuilder를 사용한 경우 - 콤마 존재 x
@PersonBuilder
func getPerson() -> [Person] {
  Person(name: "jake", age: 20) // return 키워드를 사용하지 않아도 동작
  Person(name: "kim", age: 22)
  Person(name: "paul", age: 32)
}

@resultBuilder 만들어진 이유

  •  Swift에서 구조화된 데이터를 다룰 때 조금 더 좋은 인터페이스를 제공하기 위함
  • 구조화된 데이터 예시
    • XML, JSON
    • UI 보기 계층 구조(SwiftUI)

ex) @resultBuilder 유무에 따라 HTML 코드 생성하는 부분 비교

  • @resultBuilder없이 HTML 코드를 만드는 경우
    • 번잡하게 쉼표, 괄호, 괄호와 같은 많은 구두점이 많음
    • 자식에 대해 배열 리터럴을 사용하기 때문에 컴파일 타임의 type checker가 동일한 타입을 갖도록 요구
// interface
func body(_ children: [HTML]) -> HTMLNode { ... }
func division(_ children: [HTML]) -> HTMLNode { ... }
func paragraph(_ children: [HTML]) -> HTMLNode { ... }
func header1(_ text: String) -> HTMLNode { ... }

// ex
return body([
  division([
    header1("Chapter 1. Loomings."),
    paragraph(["Call me Ishmael. Some years ago"]),
    paragraph(["There is now your insular city"])
  ]),
  division([
    header1("Chapter 2. The Carpet-Bag."),
    paragraph(["I stuffed a shirt or two"])
  ])
])
  • @resultBuilder를 사용하면 선언형으로 구현이 가능
    • 프로그래밍의 유연성 이점도 존재
    • @resultBuilder를 사용하면 아래처럼 프로그래밍이 가능
return body {
  let chapter = spellOutChapter ? "Chapter " : ""
  division {
    if useChapterTitles {
      header1(chapter + "1. Loomings.")
    }
    paragraph {
      "Call me Ishmael. Some years ago"
    }
    paragraph {
      "There is now your insular city"
    }
  }
  division {
    if useChapterTitles {
      header1(chapter + "2. The Carpet-Bag.")
    }
    paragraph {
      "I stuffed a shirt or two"
    }
  }
}

정리

  • ResultBuilder 두 가지 편한 로직을 제공
    • 여러 개의 값을 취합
    • return 키워드 없이 반환
  • result builder를 사용하면 구조화된 데이터를 편하게 핸들링 가능

* @resultBuilder를 이용하여 깔끔한 코드 만드는 방법은 다음 포스팅 글에서 계속

 

* 참고

https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md#the-result-builder-transform

Comments