InfoGrab DocsInfoGrab Docs

CI/CD 입력

요약

CI/CD inputs를 사용하면 CI/CD 구성의 유연성을 높일 수 있습니다. CI/CD 구성의 헤더에서 spec:inputs를 사용하면 구성 파일에 전달할 수 있는 입력 매개변수를 정의할 수 있습니다. 헤더 섹션 바깥에서 $[[ inputs.input-id ]] 보간 형식을 사용해 inputs를 사용할 위치를 선언합니다.

히스토리

CI/CD inputs를 사용하면 CI/CD 구성의 유연성을 높일 수 있습니다. inputs와 CI/CD 변수를 비슷한 방식으로 사용할 수 있지만, 이점은 서로 다릅니다:

  • inputs는 재사용 가능한 템플릿에 타입이 지정된 매개변수를 제공하며 파이프라인 생성 시점에 내장 검증을 거칩니다. 파이프라인 실행 시 구체적인 값을 정의하려면 CI/CD 변수 대신 inputs를 사용합니다.
  • CI/CD 변수는 여러 수준에서 정의할 수 있는 유연한 값을 제공하지만, 파이프라인 실행 도중에 수정될 수 있습니다. job의 런타임 환경에서 접근해야 하는 값에는 변수를 사용합니다. 조건부 include를 통한 동적 파이프라인 구성을 위해 사전 정의된 변수를 include:rules와 함께 사용할 수도 있습니다.

CI/CD Inputs와 변수 비교#

Inputs:

  • 목적: CI/CD 구성(템플릿, 컴포넌트, 또는 .gitlab-ci.yml)에 정의되며 파이프라인이 트리거될 때 값이 할당되어, 사용자가 재사용 가능한 CI 구성을 커스터마이즈할 수 있게 합니다.
  • 수정: 파이프라인 초기화 시점에 전달된 이후에는, input 값이 CI/CD 구성에 보간(interpolate)되어 파이프라인 실행 전체 동안 고정됩니다.
  • 범위: .gitlab-ci.yml 또는 include되는 파일 등, 정의된 파일 안에서만 사용할 수 있습니다. include:inputs를 사용하면 다른 파일에, trigger:inputs를 사용하면 파이프라인에 명시적으로 전달할 수 있습니다.
  • 검증: 타입 검사, 정규식 패턴, 사전 정의된 옵션 목록, 사용자를 위한 설명 등 탄탄한 검증 기능을 제공합니다.

CI/CD 변수:

  • 목적: job 실행 중이나 파이프라인의 다양한 위치에서 job 간 데이터 전달을 위해 환경 변수로 설정할 수 있는 값입니다.
  • 수정: dotenv 아티팩트, 조건부 규칙, 또는 job 스크립트 내에서 직접 파이프라인 실행 중에 동적으로 생성하거나 수정할 수 있습니다.
  • 범위: 전역(모든 job에 영향), job 수준(특정 job 에만 영향), 또는 GitLab UI를 통해 프로젝트나 그룹 전체 수준으로 정의할 수 있습니다.
  • 검증: 키-값 쌍이며 내장 검증은 최소한이지만, 프로젝트 변수의 경우 GitLab UI를 통해 일부 제어를 추가할 수 있습니다.

spec:inputs로 입력 매개변수 정의하기#

CI/CD 구성의 헤더에서 spec:inputs를 사용하면 구성 파일에 전달할 수 있는 입력 매개변수를 정의할 수 있습니다.

헤더 섹션 바깥에서 $[[ inputs.input-id ]] 보간 형식을 사용해 inputs를 사용할 위치를 선언합니다.

예를 들면 다음과 같습니다:

spec:
  inputs:
    job-stage:
      default: test
    environment:
      default: production
---
scan-website:
  stage: $[[ inputs.job-stage ]]
  script: ./scan-website $[[ inputs.environment ]]

이 예시에서 inputs는 job-stage와 environment 입니다.

spec 섹션이 있는 파일 안에서만 inputs 값을 사용할 수 있습니다. include로 추가된 다른 파일에서 input 값을 사용하려면 include 된 파일에 명시적으로 전달해야 합니다.

spec:inputs 사용 시:

  • default가 지정되지 않으면 inputs는 필수입니다.
  • inputs는 파이프라인 생성 중 구성이 가져와질 때 평가되고 채워집니다.
  • input을 포함하는 문자열은 1MB 미만이어야 합니다.
  • input 내부 문자열은 1KB 미만이어야 합니다.
  • inputs는 CI/CD 변수를 사용할 수 있지만, include 키워드와 동일한 변수 사용 제약을 따릅니다.
  • spec:inputs를 정의하는 파일에 job 정의도 포함되어 있다면, 헤더 다음에 YAML 문서 구분자(---)를 추가합니다.

이후 다음 시점에 inputs의 값을 설정합니다:

  • 이 구성 파일을 사용해 새 파이프라인을 실행할 때. include 이외의 방법으로 inputs를 사용해 새 파이프라인을 구성할 때는 항상 기본값을 설정해야 합니다. 그렇지 않으면 다음을 포함해 새 파이프라인이 자동으로 트리거될 경우 파이프라인이 시작되지 못할 수 있습니다:
    • 머지 리퀘스트 파이프라인
    • 브랜치 파이프라인
    • 태그 파이프라인
  • 파이프라인에 구성을 include 할 때. 필수인 inputs는 반드시 include:inputs 섹션에 추가해야 하며, 구성이 include 될 때마다 사용됩니다.

Input 구성#

inputs를 구성하려면 다음을 사용합니다:

  • spec:inputs:default: 값이 지정되지 않았을 때 사용할 input의 기본값을 정의합니다. 기본값을 지정하면 해당 input은 더 이상 필수가 아닙니다.
  • spec:inputs:description: 특정 input에 설명을 부여합니다. 설명은 input 동작에 영향을 주지 않지만, input의 세부 사항이나 예상 값을 사용자가 이해하는 데 도움이 됩니다.
  • spec:inputs:options: input에 허용되는 값 목록을 지정합니다.
  • spec:inputs:regex: input 이 일치해야 하는 정규 표현식을 지정합니다.
  • spec:inputs:type: 특정 input 타입을 강제합니다. 지정하지 않을 때 기본값은 string 이며, array, number, boolean도 가능합니다.
  • spec:inputs:rules: 다른 input의 값을 기준으로 조건부 options와 default 값을 정의합니다.

CI/CD 구성 파일 하나에 여러 input을 정의할 수 있으며, 각 input은 여러 구성 매개변수를 가질 수 있습니다.

예를 들어 scan-website-job.yml이라는 파일에서:

spec:
  inputs:
    job-prefix:     # Mandatory string input
      description: "Define a prefix for the job name"
    job-stage:      # Optional string input with a default value when not provided
      default: test
    environment:    # Mandatory input that must match one of the options
      options: ['test', 'staging', 'production']
    concurrency:
      type: number  # Optional numeric input with a default value when not provided
      default: 1
    version:        # Mandatory string input that must match the regular expression
      type: string
      regex: ^v\d\.\d+(\.\d+)$
    export_results: # Optional boolean input with a default value when not provided
      type: boolean
      default: true
---

"$[[ inputs.job-prefix ]]-scan-website":
  stage: $[[ inputs.job-stage ]]
  script:
    - echo "scanning website -e $[[ inputs.environment ]] -c $[[ inputs.concurrency ]] -v $[[ inputs.version ]]"
    - if $[[ inputs.export_results ]]; then echo "export results"; fi

이 예시에서:

  • job-prefix는 필수 문자열 input 이며 반드시 정의해야 합니다.
  • job-stage는 선택 사항입니다. 정의하지 않으면 값은 test 입니다.
  • environment는 정의된 옵션 중 하나와 일치해야 하는 필수 문자열 input 입니다.
  • concurrency는 선택적 숫자 input 입니다. 지정하지 않으면 기본값은 1 입니다.
  • version은 지정된 정규 표현식과 일치해야 하는 필수 문자열 input 입니다.
  • export_results는 선택적 불리언 input 입니다. 지정하지 않으면 기본값은 true 입니다.

Input 타입#

선택적 키워드 spec:inputs:type을 사용해 input 이 특정 타입을 사용하도록 지정할 수 있습니다.

input 타입은 다음과 같습니다:

  • array
  • boolean
  • number
  • string(지정하지 않을 때의 기본값)

input 이 CI/CD 구성에서 YAML 값 전체를 대체할 때는, 지정된 타입 그대로 구성에 보간됩니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    array_input:
      type: array
    boolean_input:
      type: boolean
    number_input:
      type: number
    string_input:
      type: string
---

test_job:
  allow_failure: $[[ inputs.boolean_input ]]
  needs: $[[ inputs.array_input ]]
  parallel: $[[ inputs.number_input ]]
  script: $[[ inputs.string_input ]]

input 이 더 큰 문자열의 일부로 YAML 값에 삽입될 때는, 해당 input은 항상 문자열로 보간됩니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    port:
      type: number
---

test_job:
  script: curl "https://gitlab.com:$[[ inputs.port ]]"

배열 타입#

배열 타입 항목의 내용에는 유효한 YAML 맵, 시퀀스, 스칼라를 모두 사용할 수 있습니다. !reference 같은 더 복잡한 YAML 기능은 사용하지 않습니다. 이러한 기능은 input 값에서 예기치 않은 결과를 낼 수 있습니다. 여러 구성 파일에서 목록을 재사용하려면 외부 파일에 배열 input을 정의합니다. 그러면 추가 항목으로 확장할 수 있습니다.

배열 input의 값을 문자열 안에서 사용하면(예: script: 섹션의 echo "My rules: $[[ inputs.rules-config ]]") 예상치 못한 결과가 나타날 수 있습니다. 배열 input은 문자열 표현으로 변환되며, 맵과 같은 복잡한 YAML 구조에 대해서는 예상과 다를 수 있습니다.

spec:
  inputs:
    rules-config:
      type: array
      default:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
          when: manual
        - if: $CI_PIPELINE_SOURCE == "schedule"
---

test_job:
  rules: $[[ inputs.rules-config ]]
  script: ls

다음의 경우 inputs를 수동으로 전달할 때 배열 input은 JSON 형식으로 작성해야 합니다(예: ["array-input-1", "array-input-2"]):

배열 input을 추가 항목으로 확장하기#

배열 input 이 배열의 항목 전체일 때, 그 항목들은 중첩되지 않고 주변 배열에 추가됩니다. 이를 이용해 공유 목록을 추가 항목으로 확장할 수 있습니다:

spec:
  inputs:
    tags:
      type: array
---

test_job:
  tags:
    - $[[ inputs.tags ]]
    - additional-tag
  script: ls

input 값이 [shared-tag-1, shared-tag-2] 일 때, test_job은 [shared-tag-1, shared-tag-2, additional-tag]를 사용합니다.

이 input은 배열 항목 전체여야 합니다. 배열 항목이 input과 다른 텍스트를 결합할 때(예: - prefix-$[[ inputs.tags ]]), GitLab은 input을 문자열로 보간합니다. 그러면 해당 항목은 배열의 문자열 표현을 포함하는 하나의 문자열이 됩니다.

옵션이 있는 배열 inputs#
히스토리

배열 input에 허용되는 값을 제한하기 위해 옵션 목록을 정의할 수 있습니다. 파이프라인을 수동으로 실행하면 UI에 텍스트 필드 대신 다중 선택 드롭다운 목록이 표시됩니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    runner_tags:
      type: array
      default: ["docker"]
      options:
        - docker
        - linux
        - gpu
        - macos
---

test:
  script:
    - run_tests.sh
  tags: $[[ inputs.runner_tags ]]

배열 input의 값 중 목록에 있는 옵션과 일치하지 않는 값이 하나라도 있으면 파이프라인이 시작되지 못합니다.

배열의 개별 요소에 접근하기#
히스토리

배열 input의 개별 요소에 접근하려면 인덱스 번호와 함께 대괄호 표기법을 사용합니다. 배열 항목은 YAML 배열에 정의된 순서대로 양수로 인덱싱됩니다. [0] 인덱스 항목이 배열의 첫 번째 항목입니다.

예를 들면 다음과 같습니다:

spec:
  inputs:
    supported_versions:
      type: array
      default:
        - '2.0'
        - '1.0'
        - '0.1'
---

job:
  script:
    # Outputs: 'Latest version is 2.0'
    - echo 'Latest version is $[[ inputs.supported_versions[0] ]]'

배열 인덱싱과 점 표기법을 연결해 중첩된 값에 접근할 수 있습니다:

spec:
  inputs:
    servers:
      type: array
      default:
        - host: server1.example.com
          port: 8080
---

job:
  script:
    - curl "https://$[[ inputs.servers[0].host ]]:$[[ inputs.servers[0].port ]]"

다차원 배열의 경우 인덱스를 여러 개 연이어 사용합니다. 예를 들어 2차원 배열에는 [0][1]을 사용할 수 있습니다:

spec:
  inputs:
    matrix:
      type: array
      default:
        - ['a', 'b']
        - ['c', 'd']
---

job:
  script:
    # Outputs: 'b'
    - echo $[[ inputs.matrix[0][1] ]]

세그먼트당 최대 5개의 인덱스를 연결할 수 있습니다(예: arr[0][1][2][3][4]).

여러 줄 문자열 input 값#

inputs는 다양한 값 타입을 지원합니다. 다음 형식을 사용해 여러 줄 문자열 값을 전달할 수 있습니다:

spec:
  inputs:
    closed_message:
      description: Message to announce when an issue is closed.
      default: 'Hi {{author}} :wave:,

        Based on the policy for inactive issues, this is now being closed.

        If this issue requires further attention, reopen this issue.'
---

spec:inputs:rules로 조건부 input 옵션 정의하기#

히스토리

spec:inputs:rules를 사용하면 다른 input의 값을 기준으로 input에 서로 다른 options와 default 값을 정의할 수 있습니다. 이 구성은 하나의 input 이 다른 input 이 제공하는 컨텍스트에 따라 서로 다른 허용 값을 가져야 할 때 사용할 수 있습니다.

rules 목록의 각 규칙은 다음을 가질 수 있습니다:

  • if: 이 규칙이 적용되는 시점을 판단하기 위해 하나 이상의 input 값을 확인하는 표현식입니다. $[[ inputs.input-id ]] 보간과 동일한 구문을 사용합니다.
  • options: 이 규칙이 일치할 때 input에 허용되는 값 목록입니다.
  • default: 이 규칙이 일치할 때 사용할 기본값입니다.

규칙은 순서대로 평가됩니다. if 조건이 일치하는 첫 번째 규칙이 사용됩니다. if 조건이 없는 마지막 규칙은 다른 규칙이 일치하지 않을 때의 대체(fallback)로 동작합니다.

예를 들어, 클라우드 제공업체와 환경에 따라 달라지는 인스턴스 타입을 정의하면 다음과 같습니다:

spec:
  inputs:
    cloud_provider:
      options: ['aws', 'gcp', 'azure']
      default: 'aws'
      description: 'Cloud provider'

    environment:
      options: ['development', 'staging', 'production']
      default: 'development'
      description: 'Target environment'

    instance_type:
      description: 'VM instance type'
      rules:
        - if: $[[ inputs.cloud_provider ]] == 'aws' && $[[ inputs.environment ]] == 'development'
          options: ['t3.micro', 't3.small']
          default: 't3.micro'
        - if: $[[ inputs.cloud_provider ]] == 'aws' && $[[ inputs.environment ]] == 'production'
          options: ['t3.xlarge', 't3.2xlarge', 'm5.xlarge']
          default: 't3.xlarge'
        - if: $[[ inputs.cloud_provider ]] == 'gcp'
          options: ['e2-micro', 'e2-small', 'e2-standard-4']
          default: 'e2-micro'
        - if: $[[ inputs.cloud_provider ]] == 'azure'
          options: ['Standard_B1s', 'Standard_B2s', 'Standard_D2s_v3']
          default: 'Standard_B1s'
        - options: ['small', 'medium', 'large']  # Fallback for any other case
          default: 'small'
---

deploy:
  script: |
    echo "Deploying to $[[ inputs.cloud_provider ]]"
    echo "Environment: $[[ inputs.environment ]]"
    echo "Instance: $[[ inputs.instance_type ]]"

이 예시에서:

  • cloud_provider가 aws 이고 environment가 development 일 때, 사용자는 t3.micro 또는 t3.small 인스턴스 타입 중에서 선택할 수 있으며 기본값은 t3.micro 입니다.
  • cloud_provider가 aws 이고 environment가 production 일 때는, 다른 인스턴스 타입(t3.xlarge, t3.2xlarge, m5.xlarge)을 사용할 수 있습니다.
  • cloud_provider가 gcp 일 때는, 환경과 무관하게 GCP 전용 인스턴스 타입을 사용할 수 있습니다.
  • 어떤 조건도 일치하지 않으면, 대체 규칙이 일반적인 크기 옵션을 제공합니다.

여러 조건을 동시에 일치시키기 위해 ||(OR) 연산자도 사용할 수 있습니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    deployment_type:
      options: ['canary', 'blue-green', 'rolling', 'recreate']
      default: 'rolling'

    requires_approval:
      description: 'Whether deployment requires manual approval'
      rules:
        - if: $[[ inputs.deployment_type ]] == 'canary' || $[[ inputs.deployment_type ]] == 'blue-green'
          options: ['true']
          default: 'true'
        - options: ['true', 'false']
          default: 'false'
---

deploy:
  script: echo "Deploying with $[[ inputs.deployment_type ]] strategy"

이 예시에서 requires_approval input은 deployment_type 이 canary 또는 blue-green 일 때 true로 설정됩니다. 그 외의 모든 경우에는 기본값이 false 이며 true와 false 둘 다 허용되는 옵션입니다.

default: null로 사용자 입력 값을 허용하기#

히스토리

환경 이름이나 테스트 설정처럼 사용자가 직접 값을 입력할 수 있게 하려면 options 없이 default: null을 지정한 spec:inputs:rules를 사용합니다.

예를 들면:

spec:
  inputs:
    deployment_type:
      options: ['standard', 'custom']
      default: 'standard'

    custom_config:
      description: 'Custom configuration value'
      rules:
        - if: $[[ inputs.deployment_type ]] == 'custom'
          default: null
---

deploy:
  script: echo "Config: $[[ inputs.custom_config ]]"

이 예시에서 deployment_type 이 custom 이면 custom_config 입력이 Run new pipeline 페이지에 표시되고, 사용자는 이 입력에 값을 반드시 입력해야 합니다.

spec:inputs:rules에서 불리언 입력 사용하기#

규칙 조건에서 불리언 입력을 사용할 수 있습니다. 불리언 값은 불리언 리터럴(true/false)로 비교할 수 있습니다.

spec:
  inputs:
    publish:
      type: boolean
      default: true

    publish_stage:
      rules:
        - if: $[[ inputs.publish ]] == true
          default: 'publish'
        - if: $[[ inputs.publish ]] == false
          default: 'test'
---

job:
  stage: $[[ inputs.publish_stage ]]
  script: echo "Publishing is $[[ inputs.publish ]]"

이 예시에서 publish가 true 이면 publish_stage의 기본값은 publish 입니다. publish가 false 이면 기본값은 test 입니다.

입력 값 설정하기#

파이프라인 설정에서 또는 파이프라인을 트리거할 때 입력 값을 설정할 수 있습니다.

파이프라인이 시작된 후에는 사용된 입력 값을 가져올 수 없습니다. 값을 노출해도 안전하다면 잡 로그에 값을 출력하거나 아티팩트에 저장해 향후 참고 자료로 남길 수 있습니다.

include로 추가한 설정의 경우#

포함된 설정이 파이프라인에 추가될 때 입력 값을 설정하려면 include:inputs를 사용합니다. 다음의 경우를 포함합니다.

예를 들어 입력 설정 예시의 scan-website-job.yml을 포함하고 입력 값을 설정하려면:

include:
  - local: 'scan-website-job.yml'
    inputs:
      job-prefix: 'some-service-'
      environment: 'staging'
      concurrency: 2
      version: 'v1.3.2'
      export_results: false

이 예시에서 포함된 설정의 입력은 다음과 같습니다.

Input Value Details
job-prefix some-service- 명시적으로 정의해야 합니다.
job-stage test include:inputs에 정의되어 있지 않으므로, 값은 포함된 설정의 spec:inputs:default에서 가져옵니다.
environment staging 명시적으로 정의해야 하며, 포함된 설정의 spec:inputs:options 값 중 하나와 일치해야 합니다.
concurrency 2 포함된 설정에서 spec:inputs:type 이 number로 설정되어 있으므로 숫자 값이어야 합니다. 기본값을 재정의합니다.
version v1.3.2 명시적으로 정의해야 하며, 포함된 설정의 spec:inputs:regex 정규 표현식과 일치해야 합니다.
export_results false 포함된 설정에서 spec:inputs:type 이 boolean으로 설정되어 있으므로 true 또는 false 여야 합니다. 기본값을 재정의합니다.

입력 값은 이를 정의하는 spec 섹션과 같은 파일에서만 사용할 수 있습니다. include로 추가한 파일은 다른 파일이나 포함하는 파일에 정의된 입력에 접근할 수 없습니다. 포함된 파일의 값을 사용하려면 include:inputs로 명시적으로 전달합니다.

Note

!reference 태그를 input 값이나 input default:에 사용하지 않습니다. 태그는 input이 보간된 이후에 해석되기 때문입니다.

여러 include 항목을 사용하는 경우#

각 include 항목마다 입력을 개별적으로 지정해야 합니다. 예를 들면:

include:
  - component: $CI_SERVER_FQDN/the-namespace/the-project/the-component@1.0
    inputs:
      stage: my-stage
  - local: path/to/file.yml
    inputs:
      stage: my-stage

파이프라인의 경우#

히스토리

입력은 타입 검사, 검증, 명확한 계약 등 변수보다 여러 장점을 제공합니다. 예상하지 못한 입력은 거부됩니다. 파이프라인용 입력은 메인 .gitlab-ci.yml 파일의 spec:inputs 헤더에 정의해야 합니다. 파이프라인 수준 설정에는 포함된 파일에 정의된 입력을 사용할 수 없습니다.

Note

GitLab 17.7 이상에서는 파이프라인 변수 전달보다 파이프라인 입력 사용을 권장합니다. 보안을 강화하려면 입력을 사용할 때 파이프라인 변수를 비활성화해야 합니다.

파이프라인용 입력을 정의할 때는 항상 기본값을 설정해야 합니다. 입력에 기본값이 없으면 파이프라인이 자동으로 트리거될 때 실패합니다. 예를 들어 머지 리퀘스트 파이프라인은 머지 리퀘스트의 소스 브랜치 변경 시 트리거될 수 있습니다. 머지 리퀘스트 파이프라인에는 입력을 수동으로 설정할 수 없으므로, 입력에 기본값이 없으면 파이프라인이 실패합니다. 이는 브랜치 파이프라인, 태그 파이프라인, 그 외 자동으로 트리거되는 파이프라인에서도 마찬가지로 발생할 수 있습니다.

입력 값은 다음 방법으로 설정할 수 있습니다.

파이프라인은 최대 20개의 입력을 받을 수 있습니다.

의견은 이 이슈에서 환영합니다.

다운스트림 파이프라인의 설정 파일이 spec:inputs를 사용하는 경우, 다운스트림 파이프라인에 입력을 전달할 수 있습니다.

예를 들어 trigger:inputs를 사용하면:

trigger-job:
  trigger:
    strategy: mirror
    include:
      - local: path/to/child-pipeline.yml
        inputs:
          job-name: "defined"
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
trigger-job:
  trigger:
    strategy: mirror
    project: project-group/my-downstream-project
    inputs:
      job-name: "defined"
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
Note

!reference 태그를 input 값이나 input default:에 사용하지 않습니다. 태그는 input이 보간된 이후에 해석되기 때문입니다.

외부 파일에 파이프라인 입력 정의하기#

히스토리

여러 CI/CD 설정에서 파이프라인 입력 정의를 재사용하려면 외부 파일에 정의한 다음 spec:include로 프로젝트의 파이프라인 설정에 포함합니다.

입력 정의 파일을 만듭니다. 예를 들어 shared-inputs.yml이라는 파일에:

inputs:
  environment:
    description: "Deployment environment"
    options: ['staging', 'production']
  region:
    default: 'us-east-1'

그런 다음 .gitlab-ci.yml에서 local로 외부 입력을 포함할 수 있습니다.

spec:
  include:
    - local: /shared-inputs.yml
---

deploy:
  script: echo "Deploying to $[[ inputs.environment ]] in $[[ inputs.region ]]"

파일이 프로젝트 외부에 저장되어 있다면 다음을 사용할 수 있습니다.

  • 다른 GitLab 프로젝트의 파일에는 project를 사용합니다. 전체 프로젝트 경로를 사용하고 file로 파일 이름을 정의합니다. 선택적으로 파일을 가져올 ref도 정의할 수 있습니다.
  • 다른 서버의 파일에는 remote를 사용합니다. 파일의 전체 URL을 사용합니다.

여러 입력 파일을 동시에 포함할 수도 있습니다. 예를 들면:

spec:
  include:
    - local: /shared-inputs.yml
    - project: 'my-group/shared-configs'
      ref: main
      file: '/ci/common-inputs.yml'
    - remote: 'https://example.com/ci/shared-inputs.yml'
---
Note

CI/CD 컴포넌트 입력에는 spec:include를 사용할 수 없습니다.

다른 프로젝트의 설정에서 외부 입력 파일 사용하기#
히스토리
Feature flag

이 기능의 가용성은 기능 플래그로 제어됩니다. 자세한 내용은 히스토리를 참고합니다.

설정 파일이 다른 프로젝트에서 포함될 때, 해당 파일의 spec:include 위치는 그 다른 프로젝트의 리포지터리와 ref에서 해석됩니다. 파이프라인을 실행하는 프로젝트는 이 해석에 영향을 주지 않습니다.

예를 들어 my-group/pipelines 프로젝트의 templates/deploy.yml 파일이 외부 파일에 입력을 정의한다고 합시다.

spec:
  include:
    - local: shared-inputs.yml
---

deploy:
  script: echo "Deploying to $[[ inputs.environment ]]"

다른 프로젝트가 자신의 .gitlab-ci.yml 파일에 이 파일을 포함합니다.

include:
  - project: 'my-group/pipelines'
    ref: main
    file: '/templates/deploy.yml'

이 예시에서 shared-inputs.yml은 파이프라인을 실행하는 프로젝트가 아니라 my-group/pipelines 프로젝트에서 읽힙니다.

외부 파일의 입력 재정의하기#

히스토리

입력 키는 포함된 모든 파일과 인라인 명세 전체에서 고유해야 합니다. 같은 input 키가 여러 포함된 파일에 있거나, 포함된 파일과 인라인 inputs: 섹션에 함께 있으면 GitLab은 다음 오류를 반환합니다.

Duplicate input keys found: environment. Input keys must be unique across all included files and inline specifications.

이 오류를 해결하려면 각 입력 키가 포함된 파일 또는 인라인 inputs: 섹션 중 한 곳에서만 정의되도록 합니다.

입력 값을 조작하는 함수 지정하기#

인터폴레이션 블록에 미리 정의된 함수를 지정해 입력 값을 조작할 수 있습니다. 지원하는 형식은 다음과 같습니다.

$[[ input.input-id | <function1> | <function2> | ... <functionN> ]]

함수와 관련해:

  • 미리 정의된 인터폴레이션 함수만 사용할 수 있습니다.
  • 하나의 인터폴레이션 블록에는 최대 3개의 함수를 지정할 수 있습니다.
  • 함수는 지정된 순서대로 실행됩니다.
spec:
  inputs:
    test:
      default: 'test $MY_VAR'
---

test-job:
  script: echo $[[ inputs.test | expand_vars | truncate(5,8) ]]

이 예시에서 입력이 기본값을 사용하고 $MY_VAR가 마스킹되지 않은 프로젝트 변수로 값이 my value 라고 가정하면:

  1. 먼저 expand_vars 함수가 값을 test my value로 확장합니다.
  2. 그런 다음 truncate가 test my value에 오프셋 5, 길이 8로 적용됩니다.
  3. script의 출력은 echo my value가 됩니다.

미리 정의된 인터폴레이션 함수#

expand_vars#

expand_vars를 사용해 입력 값에서 CI/CD 변수를 확장합니다.

include 키워드와 함께 사용할 수 있는 변수 중 마스킹되지 않은 변수만 확장할 수 있습니다. 중첩된 변수 확장은 지원하지 않습니다.

Note

입력 인터폴레이션은 잡을 환경에 할당하기 전, 파이프라인 생성 중에 발생하므로 환경 범위가 지정된 프로젝트 및 그룹 변수는 expand_vars에서 사용할 수 없습니다. expand_vars가 일치하는 변수를 찾지 못하면 리터럴 문자열(예: $MY_VAR)을 설정에 그대로 남겨두며, 셸이 런타임에 이를 확장할 수도 있습니다. 환경 범위가 지정된 변수와 범위가 지정되지 않은 변수가 같은 이름으로 모두 존재하면, expand_vars는 범위가 지정되지 않은 값을 사용합니다.

예시:

spec:
  inputs:
    test:
      default: 'test $MY_VAR'
---

test-job:
  script: echo $[[ inputs.test | expand_vars ]]

이 예시에서 $MY_VAR가 마스킹되지 않고(잡 로그에 노출) 값이 my value 라면, 입력은 test my value로 확장됩니다.

truncate#

truncate를 사용해 인터폴레이션된 값을 자를 수 있습니다. 예를 들면:

  • truncate(<offset>,<length>)
Name Type Description
offset Integer 오프셋할 문자 수.
length Integer 오프셋 이후 반환할 문자 수.

예시:

$[[ inputs.test | truncate(3,5) ]]

inputs.test의 값이 0123456789 라고 가정하면 출력은 34567 이 됩니다.

posix_escape#

히스토리

posix_escape를 사용해 입력 값에서 POSIX Bourne shell 제어 문자 또는 메타 문자를 이스케이프합니다. posix_escape는 입력에서 해당 문자 앞에 \를 삽입해 문자를 이스케이프합니다.

예시:

spec:
  inputs:
    test:
      default: |
        A string with single ' and double " quotes and   blanks
---

test-job:
  script: printf '%s\n' $[[ inputs.test | posix_escape ]]

이 예시에서 posix_escape는 셸 제어 문자 또는 메타데이터 문자가 될 수 있는 문자를 이스케이프합니다.

$ printf '%s\n' A\ string\ with\ single\ \'\ and\ double\ \"\ quotes\ and\ \ \ blanks
A string with single ' and double " quotes and   blanks

이스케이프된 입력은 제공된 대로 특수 문자와 공백을 그대로 유지합니다.

Warning

보안 목적으로 신뢰할 수 없는 입력 값에 posix_escape를 의존하지 않습니다.

posix_escape는 입력 값을 최대한 그대로 보존하려 시도하지만, 일부 문자 조합은 여전히 의도하지 않은 결과를 일으킬 수 있습니다. posix_escape를 사용하더라도 다음이 발생할 수 있습니다.

  • 문자열에 포함된 셸 코드가 실행될 수 있습니다.
  • 작은따옴표나 큰따옴표가 주변 인용을 벗어나는 데 사용될 수 있습니다.
  • 변수 참조가 보호된 변수에 접근하는 데 사용될 수 있습니다.
  • 입력 또는 출력 리다이렉션이 로컬 파일을 읽거나 쓰는 데 사용될 수 있습니다.
  • 이스케이프되지 않은 공백은 셸이 문자열을 여러 인수로 분할하는 데 사용됩니다.

보안을 위해 입력이 신뢰할 수 있는지 확인해야 합니다. 다음을 사용할 수 있습니다.

  • 문제가 될 수 있는 문자를 포함할 수 없는 spec:input:type number 또는 boolean.
  • 문제가 될 수 있는 입력을 방지하는 spec:input:regex 키워드.
  • 미리 정의된 입력 옵션 목록을 정의하는 spec:input:options 키워드.

posix_escape를 expand_vars와 함께 사용하려면 expand_vars를 먼저 설정해야 합니다. 그렇지 않으면 posix_escape가 변수의 $를 이스케이프해 확장을 막습니다. 예를 들면:

test-job:
  script: echo $[[ inputs.test | expand_vars | posix_escape ]]

split#

히스토리
  • GitLab 19.2에서 ci_interpolation_split_function이라는 이름의
  • GitLab 19.2에서 일반 공급되었습니다.

구분자를 기준으로 문자열 입력을 하위 문자열 배열로 나누려면 split을 사용합니다. 예를 들면 다음과 같습니다:

  • split('<separator>')
이름 유형 설명
separator String 분할 기준이 되는 문자 또는 문자열입니다.

split은 각 요소의 앞뒤 공백을 제거하고 빈 요소를 제거합니다.

예시:

spec:
  inputs:
    runner_tags:
      default: 'docker,linux'
---

deploy:
  tags: $[[ inputs.runner_tags | split(',') ]]
  script: echo "Deploying..."

이 예시에서 'docker,linux'를 사용하는 inputs.runner_tags는 ['docker', 'linux']를 생성하며, 이는 배열로 tags에 할당됩니다.

문제 해결#

rules에서 inputs를 사용할 때 발생하는 YAML 구문 오류#

입력을 사용해 rules:if 표현식을 수정하면 다양한 구문 오류 중 하나가 발생할 수 있습니다.

이러한 오류는 대개 CI/CD 변수 표현식에서 문자열을 처리하는 방식과 관련이 있습니다. rules:if의 표현식은 CI/CD 변수를 인용된 문자열(' 또는 ") 또는 다른 변수와 비교할 것으로 예상합니다. 파이프라인 실행 시점에 입력 값이 rules 설정에 삽입되면 결과 값이 인용된 문자열이나 변수가 아닐 수 있습니다. 이 불일치가 오류를 일으킵니다.

예를 들어 다음과 같이 포함할 설정이 있다고 가정합니다:

spec:
  inputs:
    branch:
      default: $CI_DEFAULT_BRANCH
    branch2:
      default: $CI_DEFAULT_BRANCH
---

job-name:
  rules:
    - if: $CI_COMMIT_REF_NAME == $[[ inputs.branch ]]
    - if: $CI_COMMIT_REF_NAME == $[[ inputs.branch2 ]]

그리고 메인 설정 파일에서는 다음과 같습니다:

include:
  inputs:
    branch: $CI_DEFAULT_BRANCH  # Valid
    branch2: main               # Invalid

이 예시에서:

  • branch: $CI_DEFAULT_BRANCH를 사용하는 것은 유효합니다. if: 절은 if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH로 평가되며, 이는 유효한 변수 표현식입니다. 이 변수는 인용 부호로 묶을 필요가 없습니다.
  • branch2: main을 사용하는 것은 유효하지 않습니다. if: 절은 if: $CI_COMMIT_REF_NAME == main으로 평가되며, main이 문자열인데 인용 부호로 묶이지 않았기 때문에 유효하지 않습니다.

이 문제를 해결하려면 입력 값이 설정에 삽입된 후에도 표현식이 올바른 형식을 유지하도록 해야 합니다. 이를 위해 인용 부호를 추가해야 할 수 있습니다. 예를 들어 문자열 값을 사용하는 rules에 인용 부호를 추가합니다:

rules:
  if: $CI_COMMIT_REF_NAME == "$[[ inputs.branch2 ]]"

expand_vars와 같은 보간 함수의 경우 if: 표현식 전체를 인용 부호로 묶어야 할 수도 있습니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    environment:
      default: "$ENVIRONMENT"
---

$[[ inputs.environment | expand_vars ]] job:
  script: echo
  rules:
    - if: '"$[[ inputs.environment | expand_vars ]]" == "production"'

이 예시에서는 입력과 if: 표현식 전체를 모두 인용 부호로 묶어 입력이 평가된 후에도 구문이 유효하도록 합니다. 인용 부호가 중첩되는 경우 안쪽에는 "를 바깥쪽에는 '를 사용하거나 그 반대로 사용합니다.

job 이름은 인용 부호로 묶을 필요가 없습니다.

Input 값이 #처럼 보이는 경우#

input 값에 기대한 값 대신 # 같은 문자열이 포함될 수 있습니다.

!reference 태그를 input 값으로 사용하면 이런 일이 발생합니다. 예를 들면 다음과 같습니다.

.my-shared-list:
  - value1
  - value2

include:
  - local: include.yml
    inputs:
      my_input: !reference [.my-shared-list]

input은 reference 태그보다 먼저 보간되므로, input이 reference 태그의 내부 객체로 해석됩니다. 대안으로 외부 파일에 배열 input을 정의하고 추가 항목으로 확장할 수 있습니다.

CI/CD 입력

GitLab v19.5
Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기

요약

CI/CD inputs를 사용하면 CI/CD 구성의 유연성을 높일 수 있습니다. CI/CD 구성의 헤더에서 spec:inputs를 사용하면 구성 파일에 전달할 수 있는 입력 매개변수를 정의할 수 있습니다. 헤더 섹션 바깥에서 $[[ inputs.input-id ]] 보간 형식을 사용해 inputs를 사용할 위치를 선언합니다.

히스토리

CI/CD inputs를 사용하면 CI/CD 구성의 유연성을 높일 수 있습니다. inputs와 CI/CD 변수를 비슷한 방식으로 사용할 수 있지만, 이점은 서로 다릅니다:

  • inputs는 재사용 가능한 템플릿에 타입이 지정된 매개변수를 제공하며 파이프라인 생성 시점에 내장 검증을 거칩니다. 파이프라인 실행 시 구체적인 값을 정의하려면 CI/CD 변수 대신 inputs를 사용합니다.
  • CI/CD 변수는 여러 수준에서 정의할 수 있는 유연한 값을 제공하지만, 파이프라인 실행 도중에 수정될 수 있습니다. job의 런타임 환경에서 접근해야 하는 값에는 변수를 사용합니다. 조건부 include를 통한 동적 파이프라인 구성을 위해 사전 정의된 변수를 include:rules와 함께 사용할 수도 있습니다.

CI/CD Inputs와 변수 비교#

Inputs:

  • 목적: CI/CD 구성(템플릿, 컴포넌트, 또는 .gitlab-ci.yml)에 정의되며 파이프라인이 트리거될 때 값이 할당되어, 사용자가 재사용 가능한 CI 구성을 커스터마이즈할 수 있게 합니다.
  • 수정: 파이프라인 초기화 시점에 전달된 이후에는, input 값이 CI/CD 구성에 보간(interpolate)되어 파이프라인 실행 전체 동안 고정됩니다.
  • 범위: .gitlab-ci.yml 또는 include되는 파일 등, 정의된 파일 안에서만 사용할 수 있습니다. include:inputs를 사용하면 다른 파일에, trigger:inputs를 사용하면 파이프라인에 명시적으로 전달할 수 있습니다.
  • 검증: 타입 검사, 정규식 패턴, 사전 정의된 옵션 목록, 사용자를 위한 설명 등 탄탄한 검증 기능을 제공합니다.

CI/CD 변수:

  • 목적: job 실행 중이나 파이프라인의 다양한 위치에서 job 간 데이터 전달을 위해 환경 변수로 설정할 수 있는 값입니다.
  • 수정: dotenv 아티팩트, 조건부 규칙, 또는 job 스크립트 내에서 직접 파이프라인 실행 중에 동적으로 생성하거나 수정할 수 있습니다.
  • 범위: 전역(모든 job에 영향), job 수준(특정 job 에만 영향), 또는 GitLab UI를 통해 프로젝트나 그룹 전체 수준으로 정의할 수 있습니다.
  • 검증: 키-값 쌍이며 내장 검증은 최소한이지만, 프로젝트 변수의 경우 GitLab UI를 통해 일부 제어를 추가할 수 있습니다.

spec:inputs로 입력 매개변수 정의하기#

CI/CD 구성의 헤더에서 spec:inputs를 사용하면 구성 파일에 전달할 수 있는 입력 매개변수를 정의할 수 있습니다.

헤더 섹션 바깥에서 $[[ inputs.input-id ]] 보간 형식을 사용해 inputs를 사용할 위치를 선언합니다.

예를 들면 다음과 같습니다:

spec:
  inputs:
    job-stage:
      default: test
    environment:
      default: production
---
scan-website:
  stage: $[[ inputs.job-stage ]]
  script: ./scan-website $[[ inputs.environment ]]

이 예시에서 inputs는 job-stage와 environment 입니다.

spec 섹션이 있는 파일 안에서만 inputs 값을 사용할 수 있습니다. include로 추가된 다른 파일에서 input 값을 사용하려면 include 된 파일에 명시적으로 전달해야 합니다.

spec:inputs 사용 시:

  • default가 지정되지 않으면 inputs는 필수입니다.
  • inputs는 파이프라인 생성 중 구성이 가져와질 때 평가되고 채워집니다.
  • input을 포함하는 문자열은 1MB 미만이어야 합니다.
  • input 내부 문자열은 1KB 미만이어야 합니다.
  • inputs는 CI/CD 변수를 사용할 수 있지만, include 키워드와 동일한 변수 사용 제약을 따릅니다.
  • spec:inputs를 정의하는 파일에 job 정의도 포함되어 있다면, 헤더 다음에 YAML 문서 구분자(---)를 추가합니다.

이후 다음 시점에 inputs의 값을 설정합니다:

  • 이 구성 파일을 사용해 새 파이프라인을 실행할 때. include 이외의 방법으로 inputs를 사용해 새 파이프라인을 구성할 때는 항상 기본값을 설정해야 합니다. 그렇지 않으면 다음을 포함해 새 파이프라인이 자동으로 트리거될 경우 파이프라인이 시작되지 못할 수 있습니다:
    • 머지 리퀘스트 파이프라인
    • 브랜치 파이프라인
    • 태그 파이프라인
  • 파이프라인에 구성을 include 할 때. 필수인 inputs는 반드시 include:inputs 섹션에 추가해야 하며, 구성이 include 될 때마다 사용됩니다.

Input 구성#

inputs를 구성하려면 다음을 사용합니다:

  • spec:inputs:default: 값이 지정되지 않았을 때 사용할 input의 기본값을 정의합니다. 기본값을 지정하면 해당 input은 더 이상 필수가 아닙니다.
  • spec:inputs:description: 특정 input에 설명을 부여합니다. 설명은 input 동작에 영향을 주지 않지만, input의 세부 사항이나 예상 값을 사용자가 이해하는 데 도움이 됩니다.
  • spec:inputs:options: input에 허용되는 값 목록을 지정합니다.
  • spec:inputs:regex: input 이 일치해야 하는 정규 표현식을 지정합니다.
  • spec:inputs:type: 특정 input 타입을 강제합니다. 지정하지 않을 때 기본값은 string 이며, array, number, boolean도 가능합니다.
  • spec:inputs:rules: 다른 input의 값을 기준으로 조건부 options와 default 값을 정의합니다.

CI/CD 구성 파일 하나에 여러 input을 정의할 수 있으며, 각 input은 여러 구성 매개변수를 가질 수 있습니다.

예를 들어 scan-website-job.yml이라는 파일에서:

spec:
  inputs:
    job-prefix:     # Mandatory string input
      description: "Define a prefix for the job name"
    job-stage:      # Optional string input with a default value when not provided
      default: test
    environment:    # Mandatory input that must match one of the options
      options: ['test', 'staging', 'production']
    concurrency:
      type: number  # Optional numeric input with a default value when not provided
      default: 1
    version:        # Mandatory string input that must match the regular expression
      type: string
      regex: ^v\d\.\d+(\.\d+)$
    export_results: # Optional boolean input with a default value when not provided
      type: boolean
      default: true
---

"$[[ inputs.job-prefix ]]-scan-website":
  stage: $[[ inputs.job-stage ]]
  script:
    - echo "scanning website -e $[[ inputs.environment ]] -c $[[ inputs.concurrency ]] -v $[[ inputs.version ]]"
    - if $[[ inputs.export_results ]]; then echo "export results"; fi

이 예시에서:

  • job-prefix는 필수 문자열 input 이며 반드시 정의해야 합니다.
  • job-stage는 선택 사항입니다. 정의하지 않으면 값은 test 입니다.
  • environment는 정의된 옵션 중 하나와 일치해야 하는 필수 문자열 input 입니다.
  • concurrency는 선택적 숫자 input 입니다. 지정하지 않으면 기본값은 1 입니다.
  • version은 지정된 정규 표현식과 일치해야 하는 필수 문자열 input 입니다.
  • export_results는 선택적 불리언 input 입니다. 지정하지 않으면 기본값은 true 입니다.

Input 타입#

선택적 키워드 spec:inputs:type을 사용해 input 이 특정 타입을 사용하도록 지정할 수 있습니다.

input 타입은 다음과 같습니다:

  • array
  • boolean
  • number
  • string(지정하지 않을 때의 기본값)

input 이 CI/CD 구성에서 YAML 값 전체를 대체할 때는, 지정된 타입 그대로 구성에 보간됩니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    array_input:
      type: array
    boolean_input:
      type: boolean
    number_input:
      type: number
    string_input:
      type: string
---

test_job:
  allow_failure: $[[ inputs.boolean_input ]]
  needs: $[[ inputs.array_input ]]
  parallel: $[[ inputs.number_input ]]
  script: $[[ inputs.string_input ]]

input 이 더 큰 문자열의 일부로 YAML 값에 삽입될 때는, 해당 input은 항상 문자열로 보간됩니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    port:
      type: number
---

test_job:
  script: curl "https://gitlab.com:$[[ inputs.port ]]"

배열 타입#

배열 타입 항목의 내용에는 유효한 YAML 맵, 시퀀스, 스칼라를 모두 사용할 수 있습니다. !reference 같은 더 복잡한 YAML 기능은 사용하지 않습니다. 이러한 기능은 input 값에서 예기치 않은 결과를 낼 수 있습니다. 여러 구성 파일에서 목록을 재사용하려면 외부 파일에 배열 input을 정의합니다. 그러면 추가 항목으로 확장할 수 있습니다.

배열 input의 값을 문자열 안에서 사용하면(예: script: 섹션의 echo "My rules: $[[ inputs.rules-config ]]") 예상치 못한 결과가 나타날 수 있습니다. 배열 input은 문자열 표현으로 변환되며, 맵과 같은 복잡한 YAML 구조에 대해서는 예상과 다를 수 있습니다.

spec:
  inputs:
    rules-config:
      type: array
      default:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
          when: manual
        - if: $CI_PIPELINE_SOURCE == "schedule"
---

test_job:
  rules: $[[ inputs.rules-config ]]
  script: ls

다음의 경우 inputs를 수동으로 전달할 때 배열 input은 JSON 형식으로 작성해야 합니다(예: ["array-input-1", "array-input-2"]):

배열 input을 추가 항목으로 확장하기#

배열 input 이 배열의 항목 전체일 때, 그 항목들은 중첩되지 않고 주변 배열에 추가됩니다. 이를 이용해 공유 목록을 추가 항목으로 확장할 수 있습니다:

spec:
  inputs:
    tags:
      type: array
---

test_job:
  tags:
    - $[[ inputs.tags ]]
    - additional-tag
  script: ls

input 값이 [shared-tag-1, shared-tag-2] 일 때, test_job은 [shared-tag-1, shared-tag-2, additional-tag]를 사용합니다.

이 input은 배열 항목 전체여야 합니다. 배열 항목이 input과 다른 텍스트를 결합할 때(예: - prefix-$[[ inputs.tags ]]), GitLab은 input을 문자열로 보간합니다. 그러면 해당 항목은 배열의 문자열 표현을 포함하는 하나의 문자열이 됩니다.

옵션이 있는 배열 inputs#
히스토리

배열 input에 허용되는 값을 제한하기 위해 옵션 목록을 정의할 수 있습니다. 파이프라인을 수동으로 실행하면 UI에 텍스트 필드 대신 다중 선택 드롭다운 목록이 표시됩니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    runner_tags:
      type: array
      default: ["docker"]
      options:
        - docker
        - linux
        - gpu
        - macos
---

test:
  script:
    - run_tests.sh
  tags: $[[ inputs.runner_tags ]]

배열 input의 값 중 목록에 있는 옵션과 일치하지 않는 값이 하나라도 있으면 파이프라인이 시작되지 못합니다.

배열의 개별 요소에 접근하기#
히스토리

배열 input의 개별 요소에 접근하려면 인덱스 번호와 함께 대괄호 표기법을 사용합니다. 배열 항목은 YAML 배열에 정의된 순서대로 양수로 인덱싱됩니다. [0] 인덱스 항목이 배열의 첫 번째 항목입니다.

예를 들면 다음과 같습니다:

spec:
  inputs:
    supported_versions:
      type: array
      default:
        - '2.0'
        - '1.0'
        - '0.1'
---

job:
  script:
    # Outputs: 'Latest version is 2.0'
    - echo 'Latest version is $[[ inputs.supported_versions[0] ]]'

배열 인덱싱과 점 표기법을 연결해 중첩된 값에 접근할 수 있습니다:

spec:
  inputs:
    servers:
      type: array
      default:
        - host: server1.example.com
          port: 8080
---

job:
  script:
    - curl "https://$[[ inputs.servers[0].host ]]:$[[ inputs.servers[0].port ]]"

다차원 배열의 경우 인덱스를 여러 개 연이어 사용합니다. 예를 들어 2차원 배열에는 [0][1]을 사용할 수 있습니다:

spec:
  inputs:
    matrix:
      type: array
      default:
        - ['a', 'b']
        - ['c', 'd']
---

job:
  script:
    # Outputs: 'b'
    - echo $[[ inputs.matrix[0][1] ]]

세그먼트당 최대 5개의 인덱스를 연결할 수 있습니다(예: arr[0][1][2][3][4]).

여러 줄 문자열 input 값#

inputs는 다양한 값 타입을 지원합니다. 다음 형식을 사용해 여러 줄 문자열 값을 전달할 수 있습니다:

spec:
  inputs:
    closed_message:
      description: Message to announce when an issue is closed.
      default: 'Hi {{author}} :wave:,

        Based on the policy for inactive issues, this is now being closed.

        If this issue requires further attention, reopen this issue.'
---

spec:inputs:rules로 조건부 input 옵션 정의하기#

히스토리

spec:inputs:rules를 사용하면 다른 input의 값을 기준으로 input에 서로 다른 options와 default 값을 정의할 수 있습니다. 이 구성은 하나의 input 이 다른 input 이 제공하는 컨텍스트에 따라 서로 다른 허용 값을 가져야 할 때 사용할 수 있습니다.

rules 목록의 각 규칙은 다음을 가질 수 있습니다:

  • if: 이 규칙이 적용되는 시점을 판단하기 위해 하나 이상의 input 값을 확인하는 표현식입니다. $[[ inputs.input-id ]] 보간과 동일한 구문을 사용합니다.
  • options: 이 규칙이 일치할 때 input에 허용되는 값 목록입니다.
  • default: 이 규칙이 일치할 때 사용할 기본값입니다.

규칙은 순서대로 평가됩니다. if 조건이 일치하는 첫 번째 규칙이 사용됩니다. if 조건이 없는 마지막 규칙은 다른 규칙이 일치하지 않을 때의 대체(fallback)로 동작합니다.

예를 들어, 클라우드 제공업체와 환경에 따라 달라지는 인스턴스 타입을 정의하면 다음과 같습니다:

spec:
  inputs:
    cloud_provider:
      options: ['aws', 'gcp', 'azure']
      default: 'aws'
      description: 'Cloud provider'

    environment:
      options: ['development', 'staging', 'production']
      default: 'development'
      description: 'Target environment'

    instance_type:
      description: 'VM instance type'
      rules:
        - if: $[[ inputs.cloud_provider ]] == 'aws' && $[[ inputs.environment ]] == 'development'
          options: ['t3.micro', 't3.small']
          default: 't3.micro'
        - if: $[[ inputs.cloud_provider ]] == 'aws' && $[[ inputs.environment ]] == 'production'
          options: ['t3.xlarge', 't3.2xlarge', 'm5.xlarge']
          default: 't3.xlarge'
        - if: $[[ inputs.cloud_provider ]] == 'gcp'
          options: ['e2-micro', 'e2-small', 'e2-standard-4']
          default: 'e2-micro'
        - if: $[[ inputs.cloud_provider ]] == 'azure'
          options: ['Standard_B1s', 'Standard_B2s', 'Standard_D2s_v3']
          default: 'Standard_B1s'
        - options: ['small', 'medium', 'large']  # Fallback for any other case
          default: 'small'
---

deploy:
  script: |
    echo "Deploying to $[[ inputs.cloud_provider ]]"
    echo "Environment: $[[ inputs.environment ]]"
    echo "Instance: $[[ inputs.instance_type ]]"

이 예시에서:

  • cloud_provider가 aws 이고 environment가 development 일 때, 사용자는 t3.micro 또는 t3.small 인스턴스 타입 중에서 선택할 수 있으며 기본값은 t3.micro 입니다.
  • cloud_provider가 aws 이고 environment가 production 일 때는, 다른 인스턴스 타입(t3.xlarge, t3.2xlarge, m5.xlarge)을 사용할 수 있습니다.
  • cloud_provider가 gcp 일 때는, 환경과 무관하게 GCP 전용 인스턴스 타입을 사용할 수 있습니다.
  • 어떤 조건도 일치하지 않으면, 대체 규칙이 일반적인 크기 옵션을 제공합니다.

여러 조건을 동시에 일치시키기 위해 ||(OR) 연산자도 사용할 수 있습니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    deployment_type:
      options: ['canary', 'blue-green', 'rolling', 'recreate']
      default: 'rolling'

    requires_approval:
      description: 'Whether deployment requires manual approval'
      rules:
        - if: $[[ inputs.deployment_type ]] == 'canary' || $[[ inputs.deployment_type ]] == 'blue-green'
          options: ['true']
          default: 'true'
        - options: ['true', 'false']
          default: 'false'
---

deploy:
  script: echo "Deploying with $[[ inputs.deployment_type ]] strategy"

이 예시에서 requires_approval input은 deployment_type 이 canary 또는 blue-green 일 때 true로 설정됩니다. 그 외의 모든 경우에는 기본값이 false 이며 true와 false 둘 다 허용되는 옵션입니다.

default: null로 사용자 입력 값을 허용하기#

히스토리

환경 이름이나 테스트 설정처럼 사용자가 직접 값을 입력할 수 있게 하려면 options 없이 default: null을 지정한 spec:inputs:rules를 사용합니다.

예를 들면:

spec:
  inputs:
    deployment_type:
      options: ['standard', 'custom']
      default: 'standard'

    custom_config:
      description: 'Custom configuration value'
      rules:
        - if: $[[ inputs.deployment_type ]] == 'custom'
          default: null
---

deploy:
  script: echo "Config: $[[ inputs.custom_config ]]"

이 예시에서 deployment_type 이 custom 이면 custom_config 입력이 Run new pipeline 페이지에 표시되고, 사용자는 이 입력에 값을 반드시 입력해야 합니다.

spec:inputs:rules에서 불리언 입력 사용하기#

규칙 조건에서 불리언 입력을 사용할 수 있습니다. 불리언 값은 불리언 리터럴(true/false)로 비교할 수 있습니다.

spec:
  inputs:
    publish:
      type: boolean
      default: true

    publish_stage:
      rules:
        - if: $[[ inputs.publish ]] == true
          default: 'publish'
        - if: $[[ inputs.publish ]] == false
          default: 'test'
---

job:
  stage: $[[ inputs.publish_stage ]]
  script: echo "Publishing is $[[ inputs.publish ]]"

이 예시에서 publish가 true 이면 publish_stage의 기본값은 publish 입니다. publish가 false 이면 기본값은 test 입니다.

입력 값 설정하기#

파이프라인 설정에서 또는 파이프라인을 트리거할 때 입력 값을 설정할 수 있습니다.

파이프라인이 시작된 후에는 사용된 입력 값을 가져올 수 없습니다. 값을 노출해도 안전하다면 잡 로그에 값을 출력하거나 아티팩트에 저장해 향후 참고 자료로 남길 수 있습니다.

include로 추가한 설정의 경우#

포함된 설정이 파이프라인에 추가될 때 입력 값을 설정하려면 include:inputs를 사용합니다. 다음의 경우를 포함합니다.

예를 들어 입력 설정 예시의 scan-website-job.yml을 포함하고 입력 값을 설정하려면:

include:
  - local: 'scan-website-job.yml'
    inputs:
      job-prefix: 'some-service-'
      environment: 'staging'
      concurrency: 2
      version: 'v1.3.2'
      export_results: false

이 예시에서 포함된 설정의 입력은 다음과 같습니다.

Input Value Details
job-prefix some-service- 명시적으로 정의해야 합니다.
job-stage test include:inputs에 정의되어 있지 않으므로, 값은 포함된 설정의 spec:inputs:default에서 가져옵니다.
environment staging 명시적으로 정의해야 하며, 포함된 설정의 spec:inputs:options 값 중 하나와 일치해야 합니다.
concurrency 2 포함된 설정에서 spec:inputs:type 이 number로 설정되어 있으므로 숫자 값이어야 합니다. 기본값을 재정의합니다.
version v1.3.2 명시적으로 정의해야 하며, 포함된 설정의 spec:inputs:regex 정규 표현식과 일치해야 합니다.
export_results false 포함된 설정에서 spec:inputs:type 이 boolean으로 설정되어 있으므로 true 또는 false 여야 합니다. 기본값을 재정의합니다.

입력 값은 이를 정의하는 spec 섹션과 같은 파일에서만 사용할 수 있습니다. include로 추가한 파일은 다른 파일이나 포함하는 파일에 정의된 입력에 접근할 수 없습니다. 포함된 파일의 값을 사용하려면 include:inputs로 명시적으로 전달합니다.

Note

!reference 태그를 input 값이나 input default:에 사용하지 않습니다. 태그는 input이 보간된 이후에 해석되기 때문입니다.

여러 include 항목을 사용하는 경우#

각 include 항목마다 입력을 개별적으로 지정해야 합니다. 예를 들면:

include:
  - component: $CI_SERVER_FQDN/the-namespace/the-project/the-component@1.0
    inputs:
      stage: my-stage
  - local: path/to/file.yml
    inputs:
      stage: my-stage

파이프라인의 경우#

히스토리

입력은 타입 검사, 검증, 명확한 계약 등 변수보다 여러 장점을 제공합니다. 예상하지 못한 입력은 거부됩니다. 파이프라인용 입력은 메인 .gitlab-ci.yml 파일의 spec:inputs 헤더에 정의해야 합니다. 파이프라인 수준 설정에는 포함된 파일에 정의된 입력을 사용할 수 없습니다.

Note

GitLab 17.7 이상에서는 파이프라인 변수 전달보다 파이프라인 입력 사용을 권장합니다. 보안을 강화하려면 입력을 사용할 때 파이프라인 변수를 비활성화해야 합니다.

파이프라인용 입력을 정의할 때는 항상 기본값을 설정해야 합니다. 입력에 기본값이 없으면 파이프라인이 자동으로 트리거될 때 실패합니다. 예를 들어 머지 리퀘스트 파이프라인은 머지 리퀘스트의 소스 브랜치 변경 시 트리거될 수 있습니다. 머지 리퀘스트 파이프라인에는 입력을 수동으로 설정할 수 없으므로, 입력에 기본값이 없으면 파이프라인이 실패합니다. 이는 브랜치 파이프라인, 태그 파이프라인, 그 외 자동으로 트리거되는 파이프라인에서도 마찬가지로 발생할 수 있습니다.

입력 값은 다음 방법으로 설정할 수 있습니다.

파이프라인은 최대 20개의 입력을 받을 수 있습니다.

의견은 이 이슈에서 환영합니다.

다운스트림 파이프라인의 설정 파일이 spec:inputs를 사용하는 경우, 다운스트림 파이프라인에 입력을 전달할 수 있습니다.

예를 들어 trigger:inputs를 사용하면:

trigger-job:
  trigger:
    strategy: mirror
    include:
      - local: path/to/child-pipeline.yml
        inputs:
          job-name: "defined"
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
trigger-job:
  trigger:
    strategy: mirror
    project: project-group/my-downstream-project
    inputs:
      job-name: "defined"
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
Note

!reference 태그를 input 값이나 input default:에 사용하지 않습니다. 태그는 input이 보간된 이후에 해석되기 때문입니다.

외부 파일에 파이프라인 입력 정의하기#

히스토리

여러 CI/CD 설정에서 파이프라인 입력 정의를 재사용하려면 외부 파일에 정의한 다음 spec:include로 프로젝트의 파이프라인 설정에 포함합니다.

입력 정의 파일을 만듭니다. 예를 들어 shared-inputs.yml이라는 파일에:

inputs:
  environment:
    description: "Deployment environment"
    options: ['staging', 'production']
  region:
    default: 'us-east-1'

그런 다음 .gitlab-ci.yml에서 local로 외부 입력을 포함할 수 있습니다.

spec:
  include:
    - local: /shared-inputs.yml
---

deploy:
  script: echo "Deploying to $[[ inputs.environment ]] in $[[ inputs.region ]]"

파일이 프로젝트 외부에 저장되어 있다면 다음을 사용할 수 있습니다.

  • 다른 GitLab 프로젝트의 파일에는 project를 사용합니다. 전체 프로젝트 경로를 사용하고 file로 파일 이름을 정의합니다. 선택적으로 파일을 가져올 ref도 정의할 수 있습니다.
  • 다른 서버의 파일에는 remote를 사용합니다. 파일의 전체 URL을 사용합니다.

여러 입력 파일을 동시에 포함할 수도 있습니다. 예를 들면:

spec:
  include:
    - local: /shared-inputs.yml
    - project: 'my-group/shared-configs'
      ref: main
      file: '/ci/common-inputs.yml'
    - remote: 'https://example.com/ci/shared-inputs.yml'
---
Note

CI/CD 컴포넌트 입력에는 spec:include를 사용할 수 없습니다.

다른 프로젝트의 설정에서 외부 입력 파일 사용하기#
히스토리
Feature flag

이 기능의 가용성은 기능 플래그로 제어됩니다. 자세한 내용은 히스토리를 참고합니다.

설정 파일이 다른 프로젝트에서 포함될 때, 해당 파일의 spec:include 위치는 그 다른 프로젝트의 리포지터리와 ref에서 해석됩니다. 파이프라인을 실행하는 프로젝트는 이 해석에 영향을 주지 않습니다.

예를 들어 my-group/pipelines 프로젝트의 templates/deploy.yml 파일이 외부 파일에 입력을 정의한다고 합시다.

spec:
  include:
    - local: shared-inputs.yml
---

deploy:
  script: echo "Deploying to $[[ inputs.environment ]]"

다른 프로젝트가 자신의 .gitlab-ci.yml 파일에 이 파일을 포함합니다.

include:
  - project: 'my-group/pipelines'
    ref: main
    file: '/templates/deploy.yml'

이 예시에서 shared-inputs.yml은 파이프라인을 실행하는 프로젝트가 아니라 my-group/pipelines 프로젝트에서 읽힙니다.

외부 파일의 입력 재정의하기#

히스토리

입력 키는 포함된 모든 파일과 인라인 명세 전체에서 고유해야 합니다. 같은 input 키가 여러 포함된 파일에 있거나, 포함된 파일과 인라인 inputs: 섹션에 함께 있으면 GitLab은 다음 오류를 반환합니다.

Duplicate input keys found: environment. Input keys must be unique across all included files and inline specifications.

이 오류를 해결하려면 각 입력 키가 포함된 파일 또는 인라인 inputs: 섹션 중 한 곳에서만 정의되도록 합니다.

입력 값을 조작하는 함수 지정하기#

인터폴레이션 블록에 미리 정의된 함수를 지정해 입력 값을 조작할 수 있습니다. 지원하는 형식은 다음과 같습니다.

$[[ input.input-id | <function1> | <function2> | ... <functionN> ]]

함수와 관련해:

  • 미리 정의된 인터폴레이션 함수만 사용할 수 있습니다.
  • 하나의 인터폴레이션 블록에는 최대 3개의 함수를 지정할 수 있습니다.
  • 함수는 지정된 순서대로 실행됩니다.
spec:
  inputs:
    test:
      default: 'test $MY_VAR'
---

test-job:
  script: echo $[[ inputs.test | expand_vars | truncate(5,8) ]]

이 예시에서 입력이 기본값을 사용하고 $MY_VAR가 마스킹되지 않은 프로젝트 변수로 값이 my value 라고 가정하면:

  1. 먼저 expand_vars 함수가 값을 test my value로 확장합니다.
  2. 그런 다음 truncate가 test my value에 오프셋 5, 길이 8로 적용됩니다.
  3. script의 출력은 echo my value가 됩니다.

미리 정의된 인터폴레이션 함수#

expand_vars#

expand_vars를 사용해 입력 값에서 CI/CD 변수를 확장합니다.

include 키워드와 함께 사용할 수 있는 변수 중 마스킹되지 않은 변수만 확장할 수 있습니다. 중첩된 변수 확장은 지원하지 않습니다.

Note

입력 인터폴레이션은 잡을 환경에 할당하기 전, 파이프라인 생성 중에 발생하므로 환경 범위가 지정된 프로젝트 및 그룹 변수는 expand_vars에서 사용할 수 없습니다. expand_vars가 일치하는 변수를 찾지 못하면 리터럴 문자열(예: $MY_VAR)을 설정에 그대로 남겨두며, 셸이 런타임에 이를 확장할 수도 있습니다. 환경 범위가 지정된 변수와 범위가 지정되지 않은 변수가 같은 이름으로 모두 존재하면, expand_vars는 범위가 지정되지 않은 값을 사용합니다.

예시:

spec:
  inputs:
    test:
      default: 'test $MY_VAR'
---

test-job:
  script: echo $[[ inputs.test | expand_vars ]]

이 예시에서 $MY_VAR가 마스킹되지 않고(잡 로그에 노출) 값이 my value 라면, 입력은 test my value로 확장됩니다.

truncate#

truncate를 사용해 인터폴레이션된 값을 자를 수 있습니다. 예를 들면:

  • truncate(<offset>,<length>)
Name Type Description
offset Integer 오프셋할 문자 수.
length Integer 오프셋 이후 반환할 문자 수.

예시:

$[[ inputs.test | truncate(3,5) ]]

inputs.test의 값이 0123456789 라고 가정하면 출력은 34567 이 됩니다.

posix_escape#

히스토리

posix_escape를 사용해 입력 값에서 POSIX Bourne shell 제어 문자 또는 메타 문자를 이스케이프합니다. posix_escape는 입력에서 해당 문자 앞에 \를 삽입해 문자를 이스케이프합니다.

예시:

spec:
  inputs:
    test:
      default: |
        A string with single ' and double " quotes and   blanks
---

test-job:
  script: printf '%s\n' $[[ inputs.test | posix_escape ]]

이 예시에서 posix_escape는 셸 제어 문자 또는 메타데이터 문자가 될 수 있는 문자를 이스케이프합니다.

$ printf '%s\n' A\ string\ with\ single\ \'\ and\ double\ \"\ quotes\ and\ \ \ blanks
A string with single ' and double " quotes and   blanks

이스케이프된 입력은 제공된 대로 특수 문자와 공백을 그대로 유지합니다.

Warning

보안 목적으로 신뢰할 수 없는 입력 값에 posix_escape를 의존하지 않습니다.

posix_escape는 입력 값을 최대한 그대로 보존하려 시도하지만, 일부 문자 조합은 여전히 의도하지 않은 결과를 일으킬 수 있습니다. posix_escape를 사용하더라도 다음이 발생할 수 있습니다.

  • 문자열에 포함된 셸 코드가 실행될 수 있습니다.
  • 작은따옴표나 큰따옴표가 주변 인용을 벗어나는 데 사용될 수 있습니다.
  • 변수 참조가 보호된 변수에 접근하는 데 사용될 수 있습니다.
  • 입력 또는 출력 리다이렉션이 로컬 파일을 읽거나 쓰는 데 사용될 수 있습니다.
  • 이스케이프되지 않은 공백은 셸이 문자열을 여러 인수로 분할하는 데 사용됩니다.

보안을 위해 입력이 신뢰할 수 있는지 확인해야 합니다. 다음을 사용할 수 있습니다.

  • 문제가 될 수 있는 문자를 포함할 수 없는 spec:input:type number 또는 boolean.
  • 문제가 될 수 있는 입력을 방지하는 spec:input:regex 키워드.
  • 미리 정의된 입력 옵션 목록을 정의하는 spec:input:options 키워드.

posix_escape를 expand_vars와 함께 사용하려면 expand_vars를 먼저 설정해야 합니다. 그렇지 않으면 posix_escape가 변수의 $를 이스케이프해 확장을 막습니다. 예를 들면:

test-job:
  script: echo $[[ inputs.test | expand_vars | posix_escape ]]

split#

히스토리
  • GitLab 19.2에서 ci_interpolation_split_function이라는 이름의
  • GitLab 19.2에서 일반 공급되었습니다.

구분자를 기준으로 문자열 입력을 하위 문자열 배열로 나누려면 split을 사용합니다. 예를 들면 다음과 같습니다:

  • split('<separator>')
이름 유형 설명
separator String 분할 기준이 되는 문자 또는 문자열입니다.

split은 각 요소의 앞뒤 공백을 제거하고 빈 요소를 제거합니다.

예시:

spec:
  inputs:
    runner_tags:
      default: 'docker,linux'
---

deploy:
  tags: $[[ inputs.runner_tags | split(',') ]]
  script: echo "Deploying..."

이 예시에서 'docker,linux'를 사용하는 inputs.runner_tags는 ['docker', 'linux']를 생성하며, 이는 배열로 tags에 할당됩니다.

문제 해결#

rules에서 inputs를 사용할 때 발생하는 YAML 구문 오류#

입력을 사용해 rules:if 표현식을 수정하면 다양한 구문 오류 중 하나가 발생할 수 있습니다.

이러한 오류는 대개 CI/CD 변수 표현식에서 문자열을 처리하는 방식과 관련이 있습니다. rules:if의 표현식은 CI/CD 변수를 인용된 문자열(' 또는 ") 또는 다른 변수와 비교할 것으로 예상합니다. 파이프라인 실행 시점에 입력 값이 rules 설정에 삽입되면 결과 값이 인용된 문자열이나 변수가 아닐 수 있습니다. 이 불일치가 오류를 일으킵니다.

예를 들어 다음과 같이 포함할 설정이 있다고 가정합니다:

spec:
  inputs:
    branch:
      default: $CI_DEFAULT_BRANCH
    branch2:
      default: $CI_DEFAULT_BRANCH
---

job-name:
  rules:
    - if: $CI_COMMIT_REF_NAME == $[[ inputs.branch ]]
    - if: $CI_COMMIT_REF_NAME == $[[ inputs.branch2 ]]

그리고 메인 설정 파일에서는 다음과 같습니다:

include:
  inputs:
    branch: $CI_DEFAULT_BRANCH  # Valid
    branch2: main               # Invalid

이 예시에서:

  • branch: $CI_DEFAULT_BRANCH를 사용하는 것은 유효합니다. if: 절은 if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH로 평가되며, 이는 유효한 변수 표현식입니다. 이 변수는 인용 부호로 묶을 필요가 없습니다.
  • branch2: main을 사용하는 것은 유효하지 않습니다. if: 절은 if: $CI_COMMIT_REF_NAME == main으로 평가되며, main이 문자열인데 인용 부호로 묶이지 않았기 때문에 유효하지 않습니다.

이 문제를 해결하려면 입력 값이 설정에 삽입된 후에도 표현식이 올바른 형식을 유지하도록 해야 합니다. 이를 위해 인용 부호를 추가해야 할 수 있습니다. 예를 들어 문자열 값을 사용하는 rules에 인용 부호를 추가합니다:

rules:
  if: $CI_COMMIT_REF_NAME == "$[[ inputs.branch2 ]]"

expand_vars와 같은 보간 함수의 경우 if: 표현식 전체를 인용 부호로 묶어야 할 수도 있습니다. 예를 들면 다음과 같습니다:

spec:
  inputs:
    environment:
      default: "$ENVIRONMENT"
---

$[[ inputs.environment | expand_vars ]] job:
  script: echo
  rules:
    - if: '"$[[ inputs.environment | expand_vars ]]" == "production"'

이 예시에서는 입력과 if: 표현식 전체를 모두 인용 부호로 묶어 입력이 평가된 후에도 구문이 유효하도록 합니다. 인용 부호가 중첩되는 경우 안쪽에는 "를 바깥쪽에는 '를 사용하거나 그 반대로 사용합니다.

job 이름은 인용 부호로 묶을 필요가 없습니다.

Input 값이 #처럼 보이는 경우#

input 값에 기대한 값 대신 # 같은 문자열이 포함될 수 있습니다.

!reference 태그를 input 값으로 사용하면 이런 일이 발생합니다. 예를 들면 다음과 같습니다.

.my-shared-list:
  - value1
  - value2

include:
  - local: include.yml
    inputs:
      my_input: !reference [.my-shared-list]

input은 reference 태그보다 먼저 보간되므로, input이 reference 태그의 내부 객체로 해석됩니다. 대안으로 외부 파일에 배열 input을 정의하고 추가 항목으로 확장할 수 있습니다.