alltools.one
YAML
2025-06-19
7 min
alltools.one Team
YAMLAnchorsAliasesDRYConfiguration

YAML 앵커와 별칭: DRY 설정 패턴

YAML 파일의 여러 섹션에서 같은 설정을 반복하면 DRY (Don't Repeat Yourself) 원칙을 위반하고 유지보수 문제를 만듭니다. YAML 앵커와 별칭은 값을 한 번 정의하고 여러 번 참조할 수 있게 해결합니다.

기본 구문

앵커 (&): 재사용을 위해 값을 표시 별칭 (*): 앵커된 값을 참조

# 앵커 정의
defaults: &default_settings
  timeout: 30
  retries: 3
  log_level: info

# 별칭으로 참조
development:
  <<: *default_settings
  log_level: debug

production:
  <<: *default_settings
  retries: 5

<< 병합 키는 참조된 앵커의 모든 키-값 쌍을 포함합니다. 병합 후 정의된 속성은 앵커된 값을 오버라이드합니다.

해석 후 결과:

development:
  timeout: 30
  retries: 3
  log_level: debug  # 오버라이드됨

production:
  timeout: 30
  retries: 5        # 오버라이드됨
  log_level: info

앵커 유형

스칼라 앵커

단일 값 재사용:

max_connections: &max_conn 100

database:
  pool_size: *max_conn
cache:
  pool_size: *max_conn

시퀀스 앵커

전체 목록 재사용:

common_ports: &ports
  - 80
  - 443

web_server:
  ports: *ports
load_balancer:
  ports: *ports

매핑 앵커

전체 객체 재사용 (가장 일반적인 패턴):

logging: &log_config
  driver: json-file
  options:
    max-size: "10m"
    max-file: "3"

services:
  api:
    logging: *log_config
  worker:
    logging: *log_config

병합 키 (<<)

병합 키의 특정 동작:

  1. 참조된 매핑의 모든 키-값 쌍을 복사
  2. 명시적으로 설정된 키가 병합된 키보다 우선
  3. 여러 병합은 순서대로 처리 (충돌 시 먼저 오는 것이 우선)
# 다중 병합
base: &base
  a: 1
  b: 2

extra: &extra
  b: 3
  c: 4

combined:
  <<: [*base, *extra]
  # 결과: a=1, b=2 (base가 우선), c=4

실제 예제

Docker Compose

x-common: &common
  restart: unless-stopped
  networks:
    - app-network
  logging:
    driver: json-file
    options:
      max-size: "10m"

services:
  api:
    <<: *common
    image: myapp/api:latest
    ports:
      - "8080:8080"
    environment:
      DATABASE_URL: postgres://db:5432/myapp

  worker:
    <<: *common
    image: myapp/worker:latest
    environment:
      QUEUE_URL: redis://cache:6379

  scheduler:
    <<: *common
    image: myapp/scheduler:latest

Docker Compose는 앵커를 보유하는 확장 필드에 x- 접두사 관례를 사용합니다. 더 많은 패턴은 Docker Compose를 위한 YAML 가이드를 참조하세요.

GitHub Actions

jobs:
  test:
    runs-on: ubuntu-latest
    env: &common_env
      NODE_VERSION: '20'
      CI: true
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - run: npm test

  build:
    runs-on: ubuntu-latest
    needs: test
    env:
      <<: *common_env
      BUILD_TARGET: production
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

Kubernetes

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - name: app
          resources: &resources
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
        - name: sidecar
          resources: *resources  # 동일한 리소스 제한

제한사항과 함정

1. 파일 간 참조 불가

앵커는 단일 YAML 파일 내에서만 작동합니다. 다른 파일에 정의된 앵커를 참조할 수 없습니다. 파일 간 재사용에는 Helm, Jsonnet, 또는 Kustomize 같은 템플릿 도구를 사용하세요.

2. 시퀀스에서 부분 오버라이드 불가

목록을 병합하고 부분적으로 오버라이드할 수 없습니다 — 전체 목록을 교체합니다:

base_ports: &ports
  - 80
  - 443

service:
  ports: *ports  # 정확히 [80, 443]을 얻음
  # 이 목록에 포트 8080을 병합으로 추가할 수 없음

해결책: 확장된 목록을 별도로 정의하세요.

3. 순서 중요

앵커는 참조되기 전에 정의되어야 합니다:

# 잘못됨 - 앵커 전에 별칭
service:
  settings: *defaults

defaults: &defaults
  timeout: 30

# 올바름 - 별칭 전에 앵커
defaults: &defaults
  timeout: 30

service:
  settings: *defaults

4. 모든 도구가 병합 키를 지원하지 않음

<< 병합 키는 핵심 YAML 사양의 일부가 아닙니다 — 유형별 확장입니다. 대부분의 인기 YAML 파서가 지원하지만 일부 엄격한 파서는 지원하지 않을 수 있습니다.

YAML 검증기로 YAML 앵커 사용을 검증하세요.

FAQ

YAML을 JSON으로 변환하면 앵커가 유지되나요?

아닙니다. YAML이 파싱될 때 앵커와 별칭은 값으로 해석됩니다. 결과 JSON에는 값이 인라인으로 확장됩니다. 이는 JSON으로 변환 후 다시 돌아오면 DRY 구조가 사라진다는 것을 의미합니다. 앵커는 YAML 소스 포맷에만 존재합니다.

앵커를 복잡한 중첩 오버라이드와 함께 사용할 수 있나요?

병합 키 (<<)는 얕은 병합만 수행합니다 — 앵커된 매핑의 최상위 키만 복사합니다. 중첩 객체는 딥 병합되지 않고 완전히 교체됩니다. 딥 병합 동작에는 도구별 솔루션 (Helm의 merge 함수, 커스텀 YAML 프로세서)이 필요합니다.

관련 리소스

Published on 2025-06-19
YAML Anchors and Aliases: DRY Configuration Patterns | alltools.one