🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Terraform ML 인프라 구축 실전 - 슬라이드 1/7
A

AI Generated

2025. 11. 30. · 19 Views

Terraform ML 인프라 구축 실전

Terraform을 활용하여 AWS 기반 머신러닝 인프라를 체계적으로 구축하는 방법을 다룹니다. Module 설계부터 SageMaker 배포, CI/CD 통합, 보안 설정, 비용 최적화까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.


목차

  1. Module_설계_및_재사용
  2. AWS_ML_인프라_구축
  3. Workspace로_환경_분리
  4. CICD_파이프라인_통합
  5. 보안_설정_및_관리
  6. 비용_최적화_전략

1. Module 설계 및 재사용

김개발 씨는 ML 엔지니어로 입사한 지 6개월이 되었습니다. 오늘도 새로운 ML 프로젝트를 위해 인프라를 구축하려는데, 지난번에 만들었던 코드와 거의 비슷한 구조를 또 처음부터 작성해야 합니다.

"분명히 저번에도 이거 만들었는데..." 한숨이 절로 나옵니다.

Terraform Module은 한마디로 재사용 가능한 인프라 코드 조각입니다. 마치 레고 블록처럼 필요한 모듈을 조립해서 전체 인프라를 구성할 수 있습니다.

이것을 제대로 활용하면 같은 코드를 반복 작성하지 않아도 되고, 팀 전체가 일관된 인프라를 유지할 수 있습니다.

다음 코드를 살펴봅시다.

# modules/sagemaker-endpoint/main.tf
variable "model_name" {
  description = "ML 모델 이름"
  type        = string
}

variable "instance_type" {
  description = "엔드포인트 인스턴스 타입"
  type        = string
  default     = "ml.t2.medium"
}

# SageMaker 엔드포인트 설정 구성
resource "aws_sagemaker_endpoint_configuration" "this" {
  name = "${var.model_name}-config"

  production_variants {
    variant_name           = "primary"
    model_name            = var.model_name
    instance_type         = var.instance_type
    initial_instance_count = 1
  }
}

# 실제 엔드포인트 생성
resource "aws_sagemaker_endpoint" "this" {
  name                 = "${var.model_name}-endpoint"
  endpoint_config_name = aws_sagemaker_endpoint_configuration.this.name
}

김개발 씨는 입사 후 세 번째 ML 프로젝트를 시작하려 합니다. 매번 SageMaker 엔드포인트, S3 버킷, IAM 역할을 처음부터 Terraform으로 작성했습니다.

코드를 복사해서 붙여넣기를 반복하다 보니 어느 순간 프로젝트마다 미묘하게 다른 설정이 생겨버렸습니다. 선배 개발자 박시니어 씨가 김개발 씨의 코드를 보더니 조언을 건넵니다.

"이렇게 하면 나중에 유지보수가 힘들어요. Module로 만들어서 재사용하는 게 좋아요." 그렇다면 Terraform Module이란 정확히 무엇일까요?

쉽게 비유하자면, Module은 마치 요리 레시피와 같습니다. 된장찌개를 끓일 때마다 재료 목록부터 새로 적지 않듯이, 인프라를 구축할 때도 검증된 레시피를 재사용하면 됩니다.

레시피에서 재료의 양만 조절하듯, Module에서는 변수만 바꿔서 다양한 환경에 적용할 수 있습니다. Module이 없던 시절에는 어땠을까요?

개발자들은 매번 비슷한 리소스 정의를 복사해서 붙여넣었습니다. 프로젝트가 10개, 20개로 늘어나면 관리가 불가능해졌습니다.

더 큰 문제는 보안 패치나 설정 변경이 필요할 때였습니다. 모든 프로젝트를 하나씩 수정해야 했고, 실수로 빠뜨리는 경우도 많았습니다.

바로 이런 문제를 해결하기 위해 Module 개념이 등장했습니다. Module을 사용하면 DRY 원칙(Don't Repeat Yourself)을 인프라 코드에도 적용할 수 있습니다.

또한 팀 전체가 동일한 모듈을 사용하므로 일관성이 보장됩니다. 무엇보다 모듈 하나만 수정하면 이를 사용하는 모든 프로젝트에 변경사항이 반영됩니다.

위의 코드를 살펴보겠습니다. 먼저 variable 블록에서 외부에서 주입받을 값들을 정의합니다.

model_name은 필수이고, instance_type은 기본값이 있어서 선택적입니다. 다음으로 aws_sagemaker_endpoint_configuration 리소스에서 엔드포인트 설정을 구성합니다.

변수를 활용해 동적으로 이름을 생성하는 것이 핵심입니다. 실제 현업에서는 이런 모듈을 어떻게 활용할까요?

예를 들어 추천 시스템, 이미지 분류, 자연어 처리 등 여러 ML 모델을 운영한다고 가정해봅시다. 각 모델마다 SageMaker 엔드포인트가 필요합니다.

모듈을 만들어두면 model_name과 instance_type만 바꿔서 동일한 구조의 엔드포인트를 빠르게 생성할 수 있습니다. 하지만 주의할 점도 있습니다.

초보 개발자들이 흔히 하는 실수 중 하나는 모듈을 너무 범용적으로 만들려는 것입니다. 모든 경우를 커버하려다 보면 변수가 수십 개로 늘어나고, 오히려 사용하기 어려워집니다.

따라서 팀에서 실제로 필요한 범위 내에서 적절히 추상화해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 조언을 듣고 공통 모듈을 만든 김개발 씨는 이제 새 프로젝트를 시작할 때 몇 줄의 코드만으로 전체 인프라를 구축합니다. "이렇게 편할 줄 몰랐어요!"

실전 팁

💡 - 모듈은 하나의 명확한 목적을 가지도록 설계하세요

  • output 블록을 활용해 다른 모듈에서 참조할 수 있게 만드세요
  • 버전 관리를 위해 Git 태그를 활용하세요

2. AWS ML 인프라 구축

김개발 씨가 드디어 모듈 설계를 마쳤습니다. 이제 본격적으로 ML 인프라를 구축할 차례입니다.

SageMaker, S3, EC2, RDS... 어디서부터 시작해야 할지 막막합니다.

"이것들이 어떻게 연결되는 거지?" 구조도를 그려보지만 쉽지 않습니다.

AWS ML 인프라는 데이터 저장소(S3), 모델 학습 및 배포(SageMaker), 컴퓨팅 리소스(EC2), 메타데이터 관리(RDS)가 유기적으로 연결된 시스템입니다. 마치 공장의 생산 라인처럼 각 구성 요소가 자신의 역할을 수행하며 전체 ML 파이프라인을 완성합니다.

다음 코드를 살펴봅시다.

# main.tf - ML 인프라 핵심 구성
# 학습 데이터와 모델 아티팩트 저장용 S3
resource "aws_s3_bucket" "ml_data" {
  bucket = "ml-pipeline-data-${var.environment}"

  tags = {
    Purpose = "ML Training Data and Model Artifacts"
  }
}

# SageMaker 실행 역할
resource "aws_iam_role" "sagemaker_role" {
  name = "sagemaker-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "sagemaker.amazonaws.com" }
    }]
  })
}

# SageMaker 노트북 인스턴스
resource "aws_sagemaker_notebook_instance" "ml_notebook" {
  name          = "ml-dev-notebook"
  role_arn      = aws_iam_role.sagemaker_role.arn
  instance_type = "ml.t3.medium"

  tags = { Environment = var.environment }
}

김개발 씨는 화이트보드 앞에 섰습니다. ML 프로젝트에 필요한 AWS 서비스들을 나열해봅니다.

S3, SageMaker, EC2, RDS... 서비스는 알겠는데 이것들을 어떻게 엮어야 할지 감이 잡히지 않습니다.

박시니어 씨가 다가와 화이트보드에 그림을 그리기 시작합니다. "ML 인프라를 공장에 비유해볼게요.

각 부서가 자기 역할을 하듯이 AWS 서비스도 그렇거든요." 그렇다면 각 서비스의 역할은 무엇일까요? S3는 창고입니다.

원재료인 학습 데이터를 보관하고, 완성품인 학습된 모델도 저장합니다. SageMaker는 생산 라인입니다.

데이터를 가져와 모델을 학습시키고, 완성된 모델을 배포합니다. EC2는 유연한 작업 공간입니다.

전처리나 특수 작업이 필요할 때 사용합니다. RDS는 관리 사무실입니다.

실험 기록, 모델 버전, 메타데이터를 체계적으로 관리합니다. 이런 구조 없이 ML 프로젝트를 진행하면 어떻게 될까요?

데이터가 여기저기 흩어지고, 어떤 모델이 최신인지 파악하기 어려워집니다. 팀원마다 다른 환경에서 작업하다 보니 "제 컴퓨터에서는 되는데요"라는 말이 일상이 됩니다.

재현 가능한 실험도 불가능해집니다. 위의 코드를 살펴보면 세 가지 핵심 리소스가 있습니다.

먼저 aws_s3_bucket은 ML 데이터의 중앙 저장소입니다. 환경별로 버킷을 분리하여 개발과 운영 데이터가 섞이지 않게 합니다.

aws_iam_role은 SageMaker가 다른 AWS 서비스에 접근할 수 있도록 권한을 부여합니다. aws_sagemaker_notebook_instance는 데이터 과학자들이 실험하고 모델을 개발하는 공간입니다.

실제 ML 파이프라인에서는 이렇게 흐릅니다. 데이터 엔지니어가 원본 데이터를 S3에 업로드합니다.

데이터 과학자는 SageMaker 노트북에서 데이터를 탐색하고 모델을 개발합니다. 학습이 완료되면 모델 아티팩트가 다시 S3에 저장됩니다.

이 과정에서 모든 실험 기록은 RDS에 남습니다. 주의해야 할 점이 있습니다.

IAM 역할 설정을 너무 느슨하게 하면 보안 문제가 생기고, 너무 타이트하게 하면 작업이 안 됩니다. 최소 권한 원칙을 지키되, 실제 필요한 권한은 빠짐없이 부여해야 합니다.

김개발 씨는 이제 전체 그림이 보이기 시작했습니다. "아, 각 서비스가 레고 블록처럼 연결되는 거군요!" 화이트보드의 그림이 Terraform 코드로 바뀌어 가는 모습에 뿌듯함을 느낍니다.

실전 팁

💡 - S3 버킷 이름은 전 세계에서 고유해야 하므로 환경명이나 계정 ID를 포함하세요

  • SageMaker 인스턴스 타입은 작업 특성에 맞게 선택하세요
  • IAM 역할은 필요한 최소 권한만 부여하세요

3. Workspace로 환경 분리

김개발 씨의 ML 인프라가 개발 환경에서 잘 돌아갑니다. 이제 스테이징과 프로덕션 환경도 만들어야 합니다.

"개발용 코드를 복사해서 staging 폴더 만들까?" 생각했지만 왠지 찜찜합니다. 코드가 세 벌이 되면 관리가 엉망이 될 것 같습니다.

Terraform Workspace는 하나의 코드베이스로 여러 환경을 관리하는 기능입니다. 마치 하나의 건축 설계도로 여러 건물을 짓되, 각 건물의 규모나 마감재만 다르게 하는 것과 같습니다.

코드 중복 없이 dev, staging, prod 환경을 깔끔하게 분리할 수 있습니다.

다음 코드를 살펴봅시다.

# variables.tf - 환경별 설정
variable "environment" {
  description = "배포 환경"
  type        = string
}

# 환경별 인스턴스 타입 매핑
locals {
  instance_types = {
    dev     = "ml.t3.medium"
    staging = "ml.t3.large"
    prod    = "ml.c5.xlarge"
  }

  instance_counts = {
    dev     = 1
    staging = 2
    prod    = 4
  }
}

# Workspace 기반 리소스 생성
resource "aws_sagemaker_endpoint" "ml_endpoint" {
  name = "ml-endpoint-${terraform.workspace}"

  tags = {
    Environment = terraform.workspace
    ManagedBy   = "Terraform"
  }
}

# 환경별 설정 적용
resource "aws_instance" "ml_worker" {
  instance_type = local.instance_types[terraform.workspace]
  count         = local.instance_counts[terraform.workspace]

  tags = { Name = "ml-worker-${terraform.workspace}" }
}

김개발 씨는 고민에 빠졌습니다. 개발 환경의 Terraform 코드가 완성되었는데, 스테이징과 프로덕션은 어떻게 만들어야 할까요?

폴더를 세 개 만들어서 코드를 복사하면 될 것 같지만, 직감적으로 이게 좋은 방법이 아닌 것 같습니다. "코드가 세 벌이면 수정할 때마다 세 군데를 다 고쳐야 하잖아요." 박시니어 씨의 말에 김개발 씨는 고개를 끄덕였습니다.

"Workspace를 쓰면 코드는 하나인데 환경만 바꿀 수 있어요." Terraform Workspace는 어떤 개념일까요? 음식점 프랜차이즈를 떠올려보세요.

본사에서 만든 레시피는 하나지만, 강남점과 홍대점의 매장 크기는 다릅니다. 레시피(코드)는 동일하게 유지하면서, 매장별 특성(환경 변수)만 조절하는 것입니다.

Workspace가 바로 이 역할을 합니다. Workspace 없이 환경을 분리하면 어떤 문제가 생길까요?

첫째, 코드 동기화 문제가 발생합니다. 개발 환경에서 버그를 고쳤는데 프로덕션에는 반영을 깜빡할 수 있습니다.

둘째, 코드 리뷰가 세 배로 늘어납니다. 셋째, 어떤 환경에 어떤 버전이 배포되어 있는지 추적하기 어려워집니다.

코드를 자세히 살펴봅시다. locals 블록에서 환경별 설정을 맵으로 정의합니다.

개발 환경은 작은 인스턴스 하나, 프로덕션은 큰 인스턴스 네 개입니다. terraform.workspace 변수는 현재 활성화된 workspace 이름을 반환합니다.

이를 활용해 리소스 이름과 설정을 동적으로 결정합니다. 실제로 workspace를 어떻게 사용할까요?

터미널에서 terraform workspace new staging을 실행하면 staging workspace가 생성됩니다. terraform workspace select prod로 프로덕션 workspace로 전환합니다.

같은 terraform apply 명령어를 실행해도 현재 workspace에 따라 다른 리소스가 생성됩니다. 하지만 workspace에도 한계가 있습니다.

상태 파일이 같은 백엔드에 저장되므로 완전한 격리가 필요한 경우에는 적합하지 않습니다. 프로덕션과 개발 환경을 완전히 분리된 AWS 계정에서 운영한다면 별도의 Terraform 루트 모듈을 사용하는 것이 좋습니다.

workspace는 같은 계정 내에서 환경을 분리할 때 가장 효과적입니다. 김개발 씨는 workspace를 적용하고 나서 한결 마음이 편해졌습니다.

"이제 코드 한 벌만 관리하면 되네요. 수정사항도 한 번만 반영하면 모든 환경에 적용되고요."

실전 팁

💡 - 환경별 차이가 큰 경우 locals 맵을 활용해 설정을 중앙 관리하세요

  • workspace 이름은 환경 이름과 일치시켜 혼란을 방지하세요
  • 프로덕션 배포 전 staging에서 충분히 테스트하세요

4. CICD 파이프라인 통합

김개발 씨가 Terraform 코드를 열심히 작성하고 있습니다. 그런데 동료 이주니어 씨가 같은 인프라를 수정하다가 충돌이 발생했습니다.

"누가 마지막에 apply 했어요? 제 변경사항이 사라졌어요!" 수동으로 Terraform을 실행하다 보니 이런 사고가 종종 일어납니다.

CI/CD 파이프라인은 Terraform 코드의 검증, 계획, 배포를 자동화하는 시스템입니다. 마치 공장의 컨베이어 벨트처럼 코드가 커밋되면 자동으로 검증되고, 승인 후 배포됩니다.

수동 실행으로 인한 실수를 방지하고 팀 협업을 원활하게 만듭니다.

다음 코드를 살펴봅시다.

# .github/workflows/terraform.yml
name: Terraform ML Infrastructure

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

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2

      # 코드 포맷 검사
      - name: Terraform Format
        run: terraform fmt -check

      # 초기화 및 검증
      - name: Terraform Init
        run: terraform init

      - name: Terraform Validate
        run: terraform validate

      # 변경 계획 생성 (PR에서만)
      - name: Terraform Plan
        if: github.event_name == 'pull_request'
        run: terraform plan -no-color

      # 실제 적용 (main 브랜치 푸시시)
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve

김개발 씨와 이주니어 씨는 같은 프로젝트의 인프라를 담당하고 있습니다. 오늘도 각자 로컬에서 Terraform을 수정하고 apply를 실행했습니다.

결과는 혼란이었습니다. 서로의 변경사항이 덮어쓰여지고, 누가 뭘 바꿨는지 추적하기 어려웠습니다.

"이러다 프로덕션에서 사고 나겠어요." 박시니어 씨가 팀 회의에서 말했습니다. "CI/CD 파이프라인을 구축해서 Terraform도 자동화합시다." CI/CD 파이프라인이란 무엇일까요?

은행 창구를 생각해보세요. 예전에는 돈을 찾으려면 창구 직원이 일일이 처리했습니다.

지금은 ATM이 자동으로 처리합니다. 인증하고, 잔액을 확인하고, 출금합니다.

CI/CD도 마찬가지입니다. 코드가 올라오면 자동으로 검증하고, 계획을 세우고, 승인 후 배포합니다.

자동화 없이 Terraform을 운영하면 어떤 문제가 있을까요? 먼저 휴먼 에러가 발생합니다.

피곤한 금요일 오후에 실수로 프로덕션 데이터베이스를 삭제할 수도 있습니다. 또한 감사 추적이 어렵습니다.

누가 언제 무엇을 변경했는지 기록이 남지 않습니다. 마지막으로 코드 리뷰 없이 인프라가 변경될 수 있습니다.

GitHub Actions 워크플로우를 살펴봅시다. on 섹션에서 트리거 조건을 정의합니다.

main 브랜치로의 푸시와 PR에서 실행됩니다. terraform fmt -check는 코드 스타일을 검사합니다.

terraform validate는 문법 오류를 찾아냅니다. PR에서는 plan만 실행하여 변경 예정 사항을 보여주고, main 브랜치에서는 실제 apply가 실행됩니다.

이런 구조가 왜 좋을까요? PR을 올리면 자동으로 plan 결과가 코멘트로 달립니다.

리뷰어는 어떤 리소스가 생성되고 삭제되는지 미리 확인할 수 있습니다. "이거 삭제되면 안 되는데요!"라는 피드백을 배포 전에 받을 수 있습니다.

승인 후 머지하면 자동으로 배포됩니다. 주의할 점이 있습니다.

Terraform state 파일의 동시 접근 문제를 해결해야 합니다. S3 백엔드와 DynamoDB를 사용한 state locking을 반드시 설정하세요.

또한 AWS 자격 증명은 GitHub Secrets에 안전하게 저장해야 합니다. 코드에 직접 넣으면 큰일 납니다.

파이프라인을 구축한 후 팀의 분위기가 달라졌습니다. "이제 PR 올리면 자동으로 검증되니까 안심이에요." 김개발 씨의 말에 이주니어 씨도 동의했습니다.

더 이상 서로의 변경사항을 덮어쓰는 일은 없습니다.

실전 팁

💡 - Terraform state는 S3 + DynamoDB로 원격 관리하고 locking을 활성화하세요

  • 프로덕션 apply는 수동 승인 단계를 추가하세요
  • plan 결과를 PR 코멘트로 자동 게시하면 리뷰가 편해집니다

5. 보안 설정 및 관리

김개발 씨가 만든 ML 인프라가 잘 돌아가고 있습니다. 그런데 어느 날 보안팀에서 연락이 왔습니다.

"Terraform 코드에 하드코딩된 비밀번호가 있던데요?" 얼굴이 화끈거립니다. 빨리 배포하려고 임시로 넣어둔 것이 그대로 남아있었습니다.

인프라 보안은 민감한 정보를 안전하게 관리하고, 최소 권한 원칙을 적용하며, 암호화와 네트워크 격리를 구현하는 것입니다. 마치 은행 금고처럼 여러 겹의 보안 장치가 필요합니다.

Terraform에서는 AWS Secrets Manager, KMS, VPC 설정 등을 통해 이를 구현합니다.

다음 코드를 살펴봅시다.

# 민감한 정보는 Secrets Manager에 저장
resource "aws_secretsmanager_secret" "db_credentials" {
  name        = "ml-pipeline/db-credentials"
  description = "ML 파이프라인 데이터베이스 자격 증명"

  # KMS 키로 암호화
  kms_key_id = aws_kms_key.ml_secrets.id
}

# 데이터 암호화를 위한 KMS 키
resource "aws_kms_key" "ml_secrets" {
  description             = "ML 인프라 암호화 키"
  deletion_window_in_days = 30
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" }
      Action    = "kms:*"
      Resource  = "*"
    }]
  })
}

# VPC 내부에서만 접근 가능한 SageMaker
resource "aws_sagemaker_notebook_instance" "secure_notebook" {
  name            = "secure-ml-notebook"
  role_arn        = aws_iam_role.sagemaker_role.arn
  instance_type   = "ml.t3.medium"
  subnet_id       = aws_subnet.private.id
  security_groups = [aws_security_group.sagemaker_sg.id]

  direct_internet_access = "Disabled"
}

김개발 씨는 식은땀을 흘리며 Git 히스토리를 뒤졌습니다. 3개월 전 커밋에 데이터베이스 비밀번호가 그대로 노출되어 있었습니다.

다행히 프라이빗 리포지토리였지만, 보안팀의 지적은 정확했습니다. "비밀번호가 Git에 남으면 히스토리에서 완전히 지우기 어려워요." 박시니어 씨가 설명했습니다.

"처음부터 Secrets Manager를 써야 했어요." 인프라 보안은 왜 중요할까요? ML 인프라에는 민감한 정보가 많습니다.

데이터베이스 접속 정보, API 키, 학습 데이터 접근 권한 등이 있습니다. 이런 정보가 유출되면 데이터 유출, 서비스 중단, 심각한 금전적 손실로 이어질 수 있습니다.

보안은 나중에 추가하는 것이 아니라 처음부터 설계해야 합니다. 코드에서 세 가지 핵심 보안 요소를 볼 수 있습니다.

첫째, AWS Secrets Manager입니다. 비밀번호나 API 키를 코드에 직접 쓰지 않고 Secrets Manager에 저장합니다.

애플리케이션은 런타임에 이 값을 가져옵니다. 로테이션도 자동으로 처리할 수 있습니다.

둘째, **KMS(Key Management Service)**입니다. 저장된 비밀을 한 번 더 암호화합니다.

키 로테이션을 활성화하면 정기적으로 암호화 키가 교체됩니다. 누군가 Secrets Manager에 접근해도 KMS 권한이 없으면 복호화할 수 없습니다.

셋째, 네트워크 격리입니다. SageMaker 노트북을 프라이빗 서브넷에 배치하고 인터넷 직접 접근을 차단했습니다.

외부에서 이 노트북에 직접 접근하는 것이 불가능합니다. VPC 엔드포인트를 통해서만 AWS 서비스에 접근합니다.

최소 권한 원칙도 중요합니다. IAM 역할에 * 권한을 주는 것은 위험합니다.

SageMaker가 S3에 접근해야 한다면 특정 버킷에 대한 읽기/쓰기 권한만 부여하세요. 필요한 것 이상의 권한은 공격 표면을 넓힙니다.

실무에서 자주 하는 실수가 있습니다. 개발 환경에서 "일단 되게 하자"며 보안을 느슨하게 설정하고, 그 설정이 프로덕션까지 가는 경우입니다.

개발 환경에서도 프로덕션과 동일한 보안 수준을 유지하세요. 습관이 되면 실수도 줄어듭니다.

김개발 씨는 보안 설정을 모두 적용한 후 마음이 편해졌습니다. "이제 Secrets Manager만 보면 되니까 관리도 편하고, 유출 걱정도 없어요." 보안팀 감사도 무사히 통과했습니다.

실전 팁

💡 - 절대로 민감한 정보를 코드에 하드코딩하지 마세요

  • Terraform 변수로 받더라도 tfvars 파일은 .gitignore에 추가하세요
  • 정기적으로 IAM 권한을 감사하고 불필요한 권한을 제거하세요

6. 비용 최적화 전략

김개발 씨가 월말 AWS 청구서를 보고 깜짝 놀랐습니다. "이번 달 비용이 왜 이렇게 많이 나왔지?" ML 인프라는 잘 돌아가지만 비용이 예상의 두 배입니다.

어디서 새는지 찾아봐야 합니다.

비용 최적화는 필요한 성능은 유지하면서 불필요한 지출을 줄이는 전략입니다. 마치 가계부를 쓰듯이 리소스 사용을 모니터링하고, 자동 종료, 적절한 인스턴스 선택, 스팟 인스턴스 활용 등을 통해 비용을 관리합니다.

ML 인프라는 특히 비용이 크므로 최적화가 필수입니다.

다음 코드를 살펴봅시다.

# 개발 환경 자동 종료 스케줄
resource "aws_autoscaling_schedule" "dev_stop" {
  scheduled_action_name  = "stop-dev-instances"
  min_size              = 0
  max_size              = 0
  desired_capacity      = 0
  recurrence            = "0 19 * * MON-FRI"  # 평일 저녁 7시
  autoscaling_group_name = aws_autoscaling_group.ml_workers.name
}

resource "aws_autoscaling_schedule" "dev_start" {
  scheduled_action_name  = "start-dev-instances"
  min_size              = 1
  max_size              = 3
  desired_capacity      = 1
  recurrence            = "0 9 * * MON-FRI"   # 평일 아침 9시
  autoscaling_group_name = aws_autoscaling_group.ml_workers.name
}

# 비용 효율적인 스팟 인스턴스 활용
resource "aws_spot_instance_request" "ml_training" {
  ami           = data.aws_ami.ml_optimized.id
  instance_type = "p3.2xlarge"
  spot_price    = "0.90"  # 온디맨드 대비 70% 절감

  # 스팟 중단시 체크포인트에서 재개
  instance_interruption_behavior = "stop"

  tags = { Name = "ml-training-spot" }
}

# 비용 알림 설정
resource "aws_budgets_budget" "ml_monthly" {
  name         = "ml-infrastructure-monthly"
  budget_type  = "COST"
  limit_amount = "1000"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator       = "GREATER_THAN"
    threshold                 = 80
    threshold_type           = "PERCENTAGE"
    notification_type        = "FORECASTED"
    subscriber_email_addresses = ["ml-team@company.com"]
  }
}

김개발 씨는 AWS Cost Explorer를 열어봤습니다. 비용의 대부분이 SageMaker와 EC2에서 발생하고 있었습니다.

자세히 보니 개발용 인스턴스가 밤새 돌아가고 있었습니다. 퇴근 후에는 아무도 사용하지 않는데도요.

"GPU 인스턴스가 24시간 돌아가면 한 달에 수백만 원이에요." 박시니어 씨가 말했습니다. "쓸 때만 켜고, 안 쓰면 꺼야 해요." 비용 최적화는 어떻게 접근해야 할까요?

월급을 받으면 어떻게 하시나요? 필요한 곳에 쓰고, 불필요한 지출은 줄이려고 노력합니다.

클라우드 비용도 마찬가지입니다. 어디에 돈이 나가는지 파악하고, 낭비를 줄이고, 더 저렴한 대안을 찾습니다.

코드에서 세 가지 최적화 전략을 볼 수 있습니다. 첫째, 자동 종료 스케줄입니다.

개발 환경은 업무 시간에만 필요합니다. Auto Scaling 스케줄을 사용해 평일 오전 9시에 시작하고 저녁 7시에 종료합니다.

이것만으로도 개발 환경 비용을 절반 이상 줄일 수 있습니다. 둘째, 스팟 인스턴스입니다.

ML 학습은 시간이 오래 걸리지만 중간에 중단되어도 체크포인트에서 재개할 수 있습니다. 스팟 인스턴스는 온디맨드 대비 최대 90%까지 저렴합니다.

중단 가능성이 있지만 학습 작업에는 충분히 활용 가능합니다. 셋째, 예산 알림입니다.

AWS Budgets를 설정해 예상 비용이 임계값을 넘으면 알림을 받습니다. 예산의 80%에 도달하면 미리 경고를 받아 대응할 수 있습니다.

추가로 고려할 최적화 방법이 있습니다. Reserved InstancesSavings Plans를 활용하면 1년 또는 3년 약정으로 30-60% 할인을 받을 수 있습니다.

꾸준히 사용하는 프로덕션 리소스에 적합합니다. S3 Intelligent-Tiering은 접근 패턴에 따라 자동으로 스토리지 클래스를 변경해 비용을 줄입니다.

흔히 하는 실수도 있습니다. 비용 최적화에만 집중해서 성능이 떨어지면 안 됩니다.

프로덕션 ML 엔드포인트를 너무 작은 인스턴스로 운영하면 응답 시간이 느려지고 사용자 경험이 나빠집니다. 비용과 성능의 균형을 찾아야 합니다.

김개발 씨는 최적화를 적용한 후 다음 달 청구서를 확인했습니다. 비용이 40% 줄어있었습니다.

"같은 일을 하는데 비용이 이렇게 줄다니!" 팀장님도 흐뭇해하셨습니다.

실전 팁

💡 - Cost Explorer에서 정기적으로 비용 추이를 확인하세요

  • 태그를 일관되게 적용해 프로젝트별 비용을 추적하세요
  • 개발 환경은 과감하게 작은 인스턴스를 사용하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Terraform#AWS#SageMaker#MLOps#IaC#Infrastructure#MLOps,Terraform,AWS

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.