Macros의 도입 (Update*)

7과11사이·2024년 2월 23일
3
post-custom-banner

SwiftUI에 대해 배우다보니 #Preview는 필수적으로 활용하는 코드였다!
캠프를 하면서 처음 접했었는데, 당시에는 시뮬레이터와 추가 코드 작성 때문에 '굳이?' 라는 생각을 많이 했었던 기억이 난다.

하지만 처음 봤던 코드와 구성이 달라진 모습이 흥미로웠는데,

struct viewPreview: PreviewProvider {
	static var preview: some View {
    	ContentView()
	}
}

👇🏻👇🏻👇🏻👇🏻

#Preview {
	ContentView()
}

위처럼 간단하게 축약된 형식으로 코드가 사용되고 있었다!
이렇게 바뀌게 된 이유는 Macro의 도움 덕분이라고 하던데, Macro가 무엇인지에 대해 공부한 내용들을 업데이트해보고자 한다.


1. What is Macro?

Macro는 컴파일 과정에서 코드를 즉각적으로 생성하고 제공하는 기술이라고 한다.
Freestanding과 Attached Macro 2가지로 구분이 되며
필요한 코드를 새로 작성해주지만 삭제 또는 변경하지 않는다고 한다.

이게 무슨 말일까? 🤔
Macro의 의미를 파보면 나름(?) 이해하게 될 것 같다.

사전적 의미

Macro is a single Instruction given to a computer that produces a set of instructions for the computer to perform a particular piece of work
즉, 컴퓨터에게 특정 일을 시키기 위한 하나의 명령/설명서라고 이해할 수 있겠다!

WWDC 23에서 처음 사용된 표현인 Macro도 해당 의미와 상당히 유사하다고 볼 수 있다. 개발자 입장에겐 반복되는 코드를 시각적으로 줄여주지만 설명서 혹은 명령은 뒷단에서 실행시키는 기술인 셈으로 이해하게 된다.


2. Why is Macro important?

개발을 하다보면 runtime과 build time의 중요성을 깨닿게 되는 것 같다.
어플을 실행하지 않아도 오류를 발견할 수 있다는 점이 개발자와 소비자 입장에서 얼마나 편한지!

그런 점에서 Macro는 개발자에게 build time에서 버그가 있는지 확인하면서 동시에 코드의 가독성을 향상 시켜주는 기술이기 때문에 중요한 것으로 이해된다.

앞서 #Preview같은 경우도 한 줄만으로 코드 가독성을 극단적으로 올려주는 점을 보면 이해하기 쉬워지는 것 같다.


3. How to use Macros

앞서 작성한대로 Macro는 2가지로 구분이 된다.
다만 부르는 명칭이 다를 뿐, 기본적인 역할(코드 추가 및 생성)은 동일하다.

Freestanding Macro

  • '#' 를 활용한다
  • 이름처럼 어떤 곳에서도 활용할 수 있다
  • 새로운 타입, 멤버를 코드에서 활용할 수 있도록 돕는데, Warning, Error 같은 존재이다.
private func getFollowers(username: String, page: Int) {
        showLoadingView()
        isLoadingFollowers = true
        
        NetworkManager.shared.getFollowers(for: username, page: page) { [weak self] result in
            guard let self = self else { return }
            #warning("loading view가 아직 돌아가고 있어요") << 활용 예시
            self.dismissLoadingView()
            
            switch result {
            case .success(let newFollowers):
                self.updateUI(with: newFollowers)
                
            case .failure(let error):
                self.presentGFAlertOnMainThread(title: "오류", message: error.rawValue, buttonTitle: "OK")
            }
            self.isLoadingFollowers = false
        }
    }

한번 적용해봤던 방식이다!
네트워크 작업이 진행 중인 경우, 사용자에게 로딩 화면을 보일 수 있도록 적용하였는데
작업이 완료된 이후 로딩 화면을 내려야하는 점을 잊지 않도록 안내차 적용 했던 방식

Attached Macro

  • '@' 를 활용한다
  • 어떤 코드, 파일에서도 활용 가능하다
  • 이름에서 알 수 있듯이, 붙은 선언문에 코드를 추가할 수 있게 된다!
// attached macros를 활용하지 않을 경우 - 생성 시점을 위해 일일히 값을 적용해주어야 한다.
struct SundaeToppings: OptionSet {
  let rawValue: Int
  static let nuts = SundaeToppings(rawValue: 1 << 0)
  static let cherry = SundaeToppings(rawValue: 1 << 1)
  static let fudge = SundaeToppings(rawValue: 1 << 2)
}

// 반대로 Macro를 적용한 경우 - 개발자 입장에서 오타를 낼 가능성이 떨어지게 된다!
@OptionSet<Int> // << 이 부분이 macros
struct SundaeToppings {
  private enum Options: Int {
    case nuts
    case cherry
    case fudge
  }
}

위처럼 Macro를 활용하지 않은 경우와 활용한 경우를 바라보면 개발자가 작성해야하는 코드 상당수를 간소화 시킨다. 동일한 결과를 가지지만 우리 입장에서는 가독성, 디버깅 시간 단축 등 여러모로 편리한 점들이 보인다.


SwiftUI를 공부하면서 궁금해진 Macro에 대해 공식문서를 토대로 조금 알아보았다!
다음에는 직접 생성하는 과정에 대해 조금 더 파보고자 한다.

post-custom-banner

5개의 댓글

comment-user-thumbnail
2024년 2월 23일

스프링도 그렇고 대부분 어노테이션을 통해 작성하는 코드의 양을 줄이는 방식을 채택하는 것 같습니다
저는 아직 매크로에 익숙하지 않아서 코드 이해가 잘 안되네요
저의 수련이 필요한 부분인 것 같습니다

OptionSet도 저는 낯서네요
OptionSet 이외에 사용하는 매크로의 예시는 뭐가 있을까요?

1개의 답글
comment-user-thumbnail
2024년 2월 24일

매크로에 대해 저도 궁금한게 많았는데 어떤개념인지 가볍게 훑어보기 좋았던 것 같아요!! 어떻게 만들고 활용하는지 더 깊이 알고 싶은데 다음 포스팅이 너무 기대됩니다..😆

1개의 답글
comment-user-thumbnail
2024년 2월 24일

언제나 새롭게 채택되는 개념들은 개발자의 편의를 도와주기 위함인 듯 합니다 🤓
(새로운 것에 나만 못 따라갈뿐..ㅎㅎ)

제목과 선으로 글이 잘 나뉘어 있어서 보기 좋은 글 같습니다.
좋은 글 감사합니다 👍

답글 달기