🔥 하위 명령어 정의하기

249자
3분

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

swift
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
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))
        }
    }
}
 

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

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

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

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

swift
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
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 ?? "기본 경로")")
    }
}
 

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

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

YouTube 영상

채널 보기
바이펑터란? | 프로그래머를 위한 카테고리 이론
NestJS 가드, 바이딩과 스코프 | NestJS 가이드
미들웨어 vs 가드, 왜 NestJS에서는 가드가 더 똑똑할까? | NestJS 가이드
존 매카시가 들려주는 인공지능의 탄생 이야기
class-validator 와 DTO | NestJS 가이드
Pro펑터, 입력과 출력을 동시에 다루는 펑터 | 프로그래머를 위한 카테고리 이론
NestJS 파이프가 뭔가요? 컨트롤러를 보호하는 방법 | NestJS 가이드
함수형 데이터 타입 | 프로그래머를 위한 카테고리 이론