☁️ 클라우드

자동화

Automation

수동 작업을 자동으로 수행하게 만드는 것. 인프라, 배포, 테스트 자동화. DevOps의 핵심.

📖 상세 설명

자동화(Automation)는 사람이 수동으로 수행하던 반복적인 작업을 스크립트, 도구, 또는 시스템을 통해 자동으로 실행되게 만드는 것입니다. IT 분야에서 자동화는 인프라 프로비저닝, 코드 빌드/테스트/배포, 모니터링 및 경보, 보안 점검 등 거의 모든 영역에 적용됩니다. 자동화의 핵심 목표는 인적 오류 감소, 작업 속도 향상, 일관성 확보, 그리고 엔지니어가 창의적인 업무에 집중할 수 있게 하는 것입니다.

인프라 자동화(Infrastructure as Code, IaC)는 서버, 네트워크, 스토리지 등 인프라를 코드로 정의하고 자동으로 프로비저닝하는 방식입니다. Terraform, Pulumi, AWS CloudFormation 등의 도구를 사용하면 수백 대의 서버를 몇 분 만에 동일한 구성으로 생성할 수 있습니다. 인프라 코드는 버전 관리되므로 변경 이력 추적, 롤백, 코드 리뷰가 가능하며, 개발/스테이징/프로덕션 환경 간 일관성을 보장합니다.

CI/CD(Continuous Integration/Continuous Deployment)는 소프트웨어 개발 자동화의 핵심입니다. 개발자가 코드를 커밋하면 자동으로 빌드, 단위 테스트, 통합 테스트, 코드 품질 검사가 실행되고(CI), 검증된 코드는 자동으로 스테이징이나 프로덕션 환경에 배포됩니다(CD). GitHub Actions, GitLab CI, Jenkins, CircleCI 등의 도구가 널리 사용됩니다. 테스트 자동화는 특히 중요한데, 변경이 기존 기능을 손상시키지 않는지(회귀 테스트) 사람의 개입 없이 확인할 수 있습니다.

운영 자동화는 시스템 모니터링, 로그 분석, 경보 발생, 인시던트 대응까지 포함합니다. 예를 들어, 서버 CPU 사용률이 90%를 초과하면 자동으로 인스턴스를 추가(Auto Scaling)하거나, 보안 이상 징후가 감지되면 자동으로 IP를 차단하고 담당자에게 알림을 보낼 수 있습니다. Ansible, Chef, Puppet 등의 구성 관리 도구는 수천 대의 서버에 동일한 설정을 일괄 적용하고 드리프트(설정 불일치)를 감지합니다. MLOps에서는 모델 학습, 평가, 배포, 재학습까지 자동화하여 AI 시스템의 지속적인 개선을 가능케 합니다.

💻 코드 예제

GitHub Actions - CI/CD 파이프라인 자동화

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '20'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # 1. 코드 품질 검사 (병렬 실행)
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run type check
        run: npm run type-check

      - name: Run unit tests
        run: npm test -- --coverage

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  # 2. 보안 스캔
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          severity: 'CRITICAL,HIGH'
          format: 'sarif'
          output: 'trivy-results.sarif'

      - name: Upload Trivy scan results
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'trivy-results.sarif'

  # 3. Docker 이미지 빌드 및 푸시
  build-and-push:
    needs: [lint-and-test, security-scan]
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'

    permissions:
      contents: read
      packages: write

    outputs:
      image-tag: ${{ steps.meta.outputs.tags }}

    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=sha,prefix=
            type=raw,value=latest

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  # 4. 스테이징 환경 배포
  deploy-staging:
    needs: build-and-push
    runs-on: ubuntu-latest
    environment: staging

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Kubernetes (Staging)
        uses: azure/k8s-deploy@v4
        with:
          manifests: k8s/staging/
          images: ${{ needs.build-and-push.outputs.image-tag }}
          namespace: staging

      - name: Run smoke tests
        run: |
          sleep 30  # 배포 안정화 대기
          curl -f https://staging.example.com/health || exit 1

  # 5. 프로덕션 배포 (수동 승인 필요)
  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production  # 승인 필요 설정

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Kubernetes (Production)
        uses: azure/k8s-deploy@v5
        with:
          manifests: k8s/production/
          images: ${{ needs.build-and-push.outputs.image-tag }}
          namespace: production
          strategy: canary
          percentage: 20

      - name: Monitor canary deployment
        run: |
          # 카나리 배포 모니터링 (에러율 체크)
          ./scripts/monitor-canary.sh --threshold 1%

Terraform - 인프라 자동화 (AWS)

# main.tf - AWS 인프라 자동 프로비저닝
terraform {
  required_version = ">= 1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  # 상태 파일 원격 저장 (팀 협업)
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "ap-northeast-2"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "Terraform"
      Project     = var.project_name
    }
  }
}

# 변수 정의
variable "environment" {
  description = "배포 환경 (staging, production)"
  type        = string
}

variable "aws_region" {
  default = "ap-northeast-2"
}

variable "project_name" {
  default = "my-app"
}

# VPC 및 네트워크 (모듈 사용)
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = "${var.project_name}-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["${var.aws_region}a", "${var.aws_region}b", "${var.aws_region}c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway     = true
  single_nat_gateway     = var.environment == "staging" ? true : false
  enable_dns_hostnames   = true
  enable_dns_support     = true
}

# EKS 클러스터
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 19.0"

  cluster_name    = "${var.project_name}-${var.environment}"
  cluster_version = "1.28"

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  eks_managed_node_groups = {
    main = {
      min_size       = var.environment == "production" ? 3 : 1
      max_size       = var.environment == "production" ? 10 : 3
      desired_size   = var.environment == "production" ? 3 : 1
      instance_types = ["t3.medium"]

      labels = {
        Environment = var.environment
      }
    }
  }

  # 클러스터 오토스케일링 활성화
  cluster_addons = {
    coredns = { most_recent = true }
    kube-proxy = { most_recent = true }
    vpc-cni = { most_recent = true }
  }
}

# RDS (PostgreSQL)
module "rds" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~> 6.0"

  identifier = "${var.project_name}-${var.environment}"

  engine               = "postgres"
  engine_version       = "15"
  family              = "postgres15"
  major_engine_version = "15"
  instance_class       = var.environment == "production" ? "db.r6g.large" : "db.t3.micro"

  allocated_storage     = 20
  max_allocated_storage = 100

  db_name  = "myapp"
  username = "admin"
  port     = 5432

  multi_az               = var.environment == "production"
  db_subnet_group_name   = module.vpc.database_subnet_group_name
  vpc_security_group_ids = [aws_security_group.rds.id]

  backup_retention_period = var.environment == "production" ? 7 : 1
  deletion_protection     = var.environment == "production"
}

# 출력
output "eks_cluster_endpoint" {
  value = module.eks.cluster_endpoint
}

output "rds_endpoint" {
  value     = module.rds.db_instance_endpoint
  sensitive = true
}

Ansible - 서버 구성 자동화

# playbooks/setup-webserver.yml
---
- name: 웹 서버 구성 자동화
  hosts: webservers
  become: yes
  vars:
    app_user: appuser
    app_dir: /opt/myapp
    nginx_version: "1.24"

  tasks:
    - name: 시스템 패키지 업데이트
      apt:
        update_cache: yes
        upgrade: safe
      when: ansible_os_family == "Debian"

    - name: 필수 패키지 설치
      apt:
        name:
          - nginx
          - python3-pip
          - certbot
          - python3-certbot-nginx
          - fail2ban
        state: present

    - name: 애플리케이션 사용자 생성
      user:
        name: "{{ app_user }}"
        shell: /bin/bash
        home: "{{ app_dir }}"
        create_home: yes

    - name: Nginx 설정 파일 배포
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/myapp
        validate: 'nginx -t -c /etc/nginx/nginx.conf'
      notify: Reload Nginx

    - name: 사이트 활성화
      file:
        src: /etc/nginx/sites-available/myapp
        dest: /etc/nginx/sites-enabled/myapp
        state: link
      notify: Reload Nginx

    - name: 방화벽 규칙 설정
      ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - "22"
        - "80"
        - "443"

    - name: Fail2ban 설정
      template:
        src: templates/jail.local.j2
        dest: /etc/fail2ban/jail.local
      notify: Restart Fail2ban

    - name: 로그 로테이션 설정
      template:
        src: templates/logrotate.conf.j2
        dest: /etc/logrotate.d/myapp

  handlers:
    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded

    - name: Restart Fail2ban
      service:
        name: fail2ban
        state: restarted

# inventory/production.yml
---
all:
  children:
    webservers:
      hosts:
        web1:
          ansible_host: 10.0.1.10
        web2:
          ansible_host: 10.0.1.11
        web3:
          ansible_host: 10.0.1.12
      vars:
        ansible_user: deploy
        ansible_python_interpreter: /usr/bin/python3

🗣️ 실무에서 이렇게 말해요

  • "배포 자동화 완료됐어요. 이제 main에 머지하면 자동으로 스테이징 배포되고, 승인하면 프로덕션까지 가요"
  • "반복 작업 스크립트화해서 Cron으로 돌려야 할 것 같아요. 매번 수동으로 하다 보면 실수해요"
  • "인프라는 전부 Terraform으로 관리하고 있어서, 새 환경 띄우려면 terraform apply 한 번이면 돼요"
  • "테스트 자동화 커버리지 80% 넘기면 일단 안심하고 배포할 수 있어요. 회귀 버그 잡는 데 효과 좋아요"
  • "자동화는 반복 작업을 코드화하여 인적 오류를 줄이고 일관성과 속도를 확보하는 것입니다. DevOps의 핵심 원칙 중 하나입니다."
  • "Infrastructure as Code를 통해 서버, 네트워크 등 인프라를 코드로 관리하면 버전 관리, 코드 리뷰, 롤백이 가능해집니다."
  • "CI/CD 파이프라인을 구축하면 코드 커밋부터 프로덕션 배포까지 자동화되어 릴리스 주기를 단축할 수 있습니다."
  • "자동화할 때는 멱등성(Idempotency)을 고려해야 합니다. 같은 작업을 여러 번 실행해도 결과가 동일해야 안전합니다."
  • "이 수동 배포 스크립트를 GitHub Actions로 옮기면 좋겠어요. 로컬에서 실행하면 환경 차이 때문에 문제 생겨요"
  • "Terraform state 파일 로컬에 있으면 안 돼요. S3 backend로 원격 저장하고 락 걸어야 팀원끼리 충돌 안 나요"
  • "Ansible Playbook에 handlers 써서 설정 변경 시에만 서비스 재시작되게 해주세요. 매번 재시작하면 다운타임 생겨요"
  • "테스트 자동화 커버리지가 낮아서 수동 QA에 의존하고 있네요. 핵심 비즈니스 로직부터 테스트 추가해주세요"

⚠️ 주의사항

🔗 관련 용어

📚 더 배우기