🔥 하위 명령어 정의하기

249자
3분

이제 앞서 언급한 하위 명령어 중 AddMultiply를 먼저 정의해 볼게요. 이 두 하위 명령어는 모두 @OptionGroup 프로퍼티 래퍼로 Options 타입에 정의된 인자를 포함하고 있어요. (OptionGroup 참고)

extension Math {
    struct Add: ParsableCommand {
        static var configuration
            = CommandConfiguration(abstract: "Print the sum of the values.")
 
        @OptionGroup var options: Options
 
        mutating func run() {
            let result = options.values.reduce(0, +)
            print(format(result: result, usingHex: options.hexadecimalOutput))
        }
    }
 
    struct Multiply: ParsableCommand {
        static var configuration
            = CommandConfiguration(abstract: "Print the product of the values.")
 
        @OptionGroup var options: Options
 
        mutating func run() {
            let result = options.values.reduce(1, *)
            print(format(result: result, usingHex: options.hexadecimalOutput))
        }
    }
}
 
swift

@OptionGroup은 다른 ParsableArguments 타입에 정의된 인자를 그대로 가져와서 현재 명령어에 추가해줍니다.

예를 들어, 다음과 같이 CommonOptions라는 ParsableArguments 타입이 있다고 가정해 봅시다.

struct CommonOptions: ParsableArguments {
    @Option(help: "Verbose 모드 활성화")
    var verbose: Bool = false
 
    @Option(help: "출력 파일 경로")
    var output: String?
}
 
swift

그리고 MyCommand라는 명령어가 있는데, 이 명령어에서 CommonOptions의 인자를 사용하고 싶다면 다음과 같이 @OptionGroup을 사용할 수 있습니다.

struct MyCommand: ParsableCommand {
    @OptionGroup var commonOptions: CommonOptions
 
    @Argument(help: "입력 파일 경로")
    var inputFile: String
 
    mutating func run() throws {
        if commonOptions.verbose {
            print("Verbose 모드 활성화")
        }
        print("입력 파일: \(inputFile)")
        print("출력 파일: \(commonOptions.output ?? "기본 경로")")
    }
}
 
swift

이렇게 하면 MyCommand에서 CommonOptions에 정의된 verboseoutput 인자를 직접 정의하지 않아도 사용할 수 있습니다. 마치 CommonOptions의 인자를 MyCommand에 복사해 넣은 것처럼 동작하는 거죠.

이렇게 @OptionGroup을 사용하면 여러 명령어에서 공통으로 사용되는 인자를 별도의 ParsableArguments 타입으로 분리하고, 필요한 곳에서 가져다 쓸 수 있어 코드 재사용성을 높일 수 있습니다.