Chapter 14 - 강사용 답안

모니터링 & 리소스 정리 (답안)

"서비스를 모니터링하고, 실습 후 반드시 정리하자"

강사 안내

  • 각 단계의 웹 콘솔 방법과 AWS CLI 명령어를 모두 제공합니다
  • 리소스 정리는 순서가 매우 중요합니다. 학생들이 순서를 어기지 않도록 안내하세요
  • NAT Gateway, RDS 삭제는 시간이 걸리므로 미리 삭제를 시작하도록 유도하세요
  • 마지막에 반드시 전체 리소스 삭제 확인을 함께 진행하세요

답안 개요

이 답안은 Chapter 14의 모든 실습 단계에 대해 웹 콘솔 절차AWS CLI 명령어를 모두 제공합니다. CLI 명령어에서 <값>으로 표시된 부분은 학생의 실제 환경에 맞게 변경해야 합니다.

강사 주의사항

리소스 정리 시 학생마다 리소스 ID가 다르므로, AWS CLI 명령어의 ID 값은 각 학생의 환경에 맞게 수정해야 합니다. 웹 콘솔에서 리소스 ID를 먼저 확인한 후 CLI 명령어를 실행하도록 안내하세요.

Part 1-1. SNS 주제 생성 및 이메일 구독 추가

답안

웹 콘솔 절차

  1. AWS 콘솔 상단 검색창에 "SNS" 입력 → Simple Notification Service 클릭
  2. 왼쪽 메뉴에서 "주제" 클릭 → "주제 생성" 버튼 클릭
  3. 유형: 표준(Standard) 선택
  4. 이름: ShopEasy-Alerts 입력
  5. "주제 생성" 클릭
  6. 생성된 주제 상세 페이지에서 "구독 생성" 버튼 클릭
  7. 프로토콜: 이메일 선택
  8. 엔드포인트: 본인 이메일 주소 입력
  9. "구독 생성" 클릭
  10. 이메일함에서 AWS 확인 메일을 찾아 "Confirm subscription" 링크 클릭

구독 상태가 "확인됨(Confirmed)"으로 변경되면 성공입니다.

AWS CLI 명령어

bash
# 1. SNS 주제 생성
aws sns create-topic \
  --name ShopEasy-Alerts \
  --region ap-northeast-2

출력에서 TopicArn 값을 복사합니다. 예: arn:aws:sns:ap-northeast-2:123456789012:ShopEasy-Alerts

bash
# 2. 이메일 구독 추가
aws sns subscribe \
  --topic-arn arn:aws:sns:ap-northeast-2:<계정ID>:ShopEasy-Alerts \
  --protocol email \
  --notification-endpoint <본인이메일@example.com> \
  --region ap-northeast-2

이메일함에서 확인 메일의 "Confirm subscription" 링크를 클릭해야 구독이 활성화됩니다.

bash
# 3. 구독 상태 확인
aws sns list-subscriptions-by-topic \
  --topic-arn arn:aws:sns:ap-northeast-2:<계정ID>:ShopEasy-Alerts \
  --region ap-northeast-2
강사 해설

SNS 주제(Topic)는 "게시-구독(Pub/Sub)" 패턴의 메시징 서비스입니다. 주제에 메시지를 발행(Publish)하면, 해당 주제를 구독(Subscribe)하는 모든 엔드포인트에 메시지가 전달됩니다. 이메일 외에도 SMS, HTTP/HTTPS, Lambda, SQS 등 다양한 프로토콜을 구독으로 추가할 수 있습니다.

Part 1-2. CloudWatch 대시보드 생성

답안

웹 콘솔 절차

  1. AWS 콘솔 상단 검색창에 "CloudWatch" 입력 → CloudWatch 클릭
  2. 왼쪽 메뉴에서 "대시보드" 클릭 → "대시보드 생성" 클릭
  3. 대시보드 이름: ShopEasy-Dashboard 입력 → "대시보드 생성"
  4. 위젯 1 - EC2 CPU 사용률:
    • "위젯 추가" → "꺾은선" 선택 → "메트릭" 선택
    • EC2 → 인스턴스별 메트릭 → ShopEasy EC2 인스턴스의 CPUUtilization 체크
    • "위젯 생성" 클릭
  5. 위젯 2 - RDS 연결 수:
    • "+" 또는 "위젯 추가" → "꺾은선" → "메트릭"
    • RDS → 인스턴스별 메트릭 → ShopEasy RDS의 DatabaseConnections 체크
    • "위젯 생성" 클릭
  6. 위젯 3 - RDS 저장 공간:
    • "+" 또는 "위젯 추가" → "꺾은선" → "메트릭"
    • RDS → 인스턴스별 메트릭 → ShopEasy RDS의 FreeStorageSpace 체크
    • "위젯 생성" 클릭
  7. 우측 상단 "대시보드 저장" 클릭 (저장하지 않으면 위젯이 사라집니다!)

AWS CLI 명령어

CLI로 대시보드를 생성하려면 JSON 형식의 위젯 정의가 필요합니다.

bash
# CloudWatch 대시보드 생성 (JSON 위젯 정의)
aws cloudwatch put-dashboard \
  --dashboard-name ShopEasy-Dashboard \
  --dashboard-body '{
    "widgets": [
      {
        "type": "metric",
        "x": 0, "y": 0, "width": 12, "height": 6,
        "properties": {
          "title": "EC2 CPU Utilization",
          "metrics": [
            ["AWS/EC2", "CPUUtilization", "InstanceId", "<EC2-인스턴스-ID>"]
          ],
          "period": 300,
          "region": "ap-northeast-2",
          "stat": "Average"
        }
      },
      {
        "type": "metric",
        "x": 0, "y": 6, "width": 12, "height": 6,
        "properties": {
          "title": "RDS Database Connections",
          "metrics": [
            ["AWS/RDS", "DatabaseConnections", "DBInstanceIdentifier", "<RDS-인스턴스-이름>"]
          ],
          "period": 300,
          "region": "ap-northeast-2",
          "stat": "Average"
        }
      },
      {
        "type": "metric",
        "x": 12, "y": 6, "width": 12, "height": 6,
        "properties": {
          "title": "RDS Free Storage Space",
          "metrics": [
            ["AWS/RDS", "FreeStorageSpace", "DBInstanceIdentifier", "<RDS-인스턴스-이름>"]
          ],
          "period": 300,
          "region": "ap-northeast-2",
          "stat": "Average"
        }
      }
    ]
  }' \
  --region ap-northeast-2

<EC2-인스턴스-ID><RDS-인스턴스-이름>을 실제 값으로 변경하세요.

bash
# EC2 인스턴스 ID 확인
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=*ShopEasy*" \
  --query "Reservations[*].Instances[*].[InstanceId,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# RDS 인스턴스 이름 확인
aws rds describe-db-instances \
  --query "DBInstances[*].[DBInstanceIdentifier,DBInstanceStatus]" \
  --output table \
  --region ap-northeast-2
강사 해설

대시보드는 무료 티어에서 월 3개까지 무료입니다 (각 대시보드 최대 50개 메트릭). 실무에서는 서비스별 대시보드를 분리하거나, 전체 인프라를 한눈에 보는 통합 대시보드를 만듭니다. 위젯 유형으로는 꺾은선(Line), 막대(Bar), 숫자(Number), 텍스트(Text) 등이 있습니다.

Part 1-3. CloudWatch 경보 생성

답안

웹 콘솔 절차

  1. CloudWatch → 왼쪽 메뉴 "경보""모든 경보""경보 생성"
  2. 메트릭 선택:
    • "메트릭 선택" 클릭
    • EC2 → 인스턴스별 메트릭
    • ShopEasy EC2 인스턴스의 CPUUtilization 체크 → "메트릭 선택"
  3. 조건 지정:
    • 통계: 평균(Average)
    • 기간: 5분
    • 조건: 보다 큼(>)
    • 임계값: 80
  4. "다음" 클릭
  5. 알림 설정:
    • 경보 상태 트리거: "경보 상태"
    • SNS 주제 선택: "기존 SNS 주제 선택"
    • 알림 전송 대상: ShopEasy-Alerts 선택
  6. "다음" 클릭
  7. 경보 이름: ShopEasy-EC2-High-CPU 입력
  8. "다음" → 설정 미리 보기 확인 → "경보 생성"

생성 직후 상태가 "데이터 부족(Insufficient Data)"으로 표시되는 것은 정상입니다. 5분 후 데이터가 수집되면 "확인(OK)" 상태로 변경됩니다.

AWS CLI 명령어

bash
# CloudWatch 경보 생성
aws cloudwatch put-metric-alarm \
  --alarm-name ShopEasy-EC2-High-CPU \
  --alarm-description "ShopEasy EC2 CPU 사용률 80% 초과 경보" \
  --metric-name CPUUtilization \
  --namespace AWS/EC2 \
  --statistic Average \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 1 \
  --dimensions Name=InstanceId,Value=<EC2-인스턴스-ID> \
  --alarm-actions arn:aws:sns:ap-northeast-2:<계정ID>:ShopEasy-Alerts \
  --region ap-northeast-2
bash
# 경보 상태 확인
aws cloudwatch describe-alarms \
  --alarm-names ShopEasy-EC2-High-CPU \
  --query "MetricAlarms[*].[AlarmName,StateValue]" \
  --output table \
  --region ap-northeast-2
강사 해설

--period 300은 5분(300초) 간격으로 메트릭을 평가한다는 의미입니다. --evaluation-periods 1은 1회의 평가 기간(5분) 동안 임계값을 초과하면 경보를 발생시킵니다. 실무에서는 --evaluation-periods 3으로 설정하여 15분간 지속적으로 초과할 때만 경보를 발생시키는 것이 일반적입니다. 이렇게 하면 일시적인 CPU 스파이크에 의한 오경보(False Alarm)를 줄일 수 있습니다.

Part 1-4. 비용 탐색기(Cost Explorer) 확인

답안

웹 콘솔 절차

  1. 콘솔 우측 상단의 계정 이름 클릭 → "결제 대시보드" (또는 검색창에 "Billing")
  2. 왼쪽 메뉴에서 "Cost Explorer" 클릭
  3. 처음 사용하는 경우 "Cost Explorer 시작" 버튼 클릭 (활성화에 최대 24시간 소요)
  4. 기간: "이번 달" 선택
  5. 그룹 기준: "서비스" 선택
  6. 각 서비스별 비용 확인:
    • Amazon Virtual Private Cloud (NAT Gateway 비용 포함)
    • Amazon Relational Database Service
    • Amazon Elastic Compute Cloud
    • Amazon Simple Storage Service

Cost Explorer가 활성화되지 않은 경우, "청구서" 페이지에서도 서비스별 현재 비용을 확인할 수 있습니다.

AWS CLI 명령어

bash
# 이번 달 서비스별 비용 조회
aws ce get-cost-and-usage \
  --time-period Start=$(date -u +%Y-%m-01),End=$(date -u +%Y-%m-%d) \
  --granularity MONTHLY \
  --metrics "BlendedCost" \
  --group-by Type=DIMENSION,Key=SERVICE \
  --region us-east-1

Cost Explorer API는 us-east-1 리전에서만 사용할 수 있습니다 (글로벌 서비스).

bash
# 오늘 날짜 기준 일별 비용 조회 (최근 7일)
aws ce get-cost-and-usage \
  --time-period Start=$(date -u -v-7d +%Y-%m-%d),End=$(date -u +%Y-%m-%d) \
  --granularity DAILY \
  --metrics "BlendedCost" \
  --group-by Type=DIMENSION,Key=SERVICE \
  --region us-east-1
강사 해설

Cost Explorer는 처음 활성화하면 최대 24시간이 소요됩니다. 학생들이 처음 사용하는 경우 미리 활성화해 두도록 안내하거나, "청구서(Bills)" 페이지에서 현재 비용을 확인하도록 하세요. 프리 티어 계정이라면 EC2(t2.micro), RDS(db.t3.micro) 등이 프리 티어 한도 내에 있을 수 있지만, NAT Gateway는 프리 티어에 포함되지 않습니다.

Part 2-1. GuardDuty 비활성화

답안

웹 콘솔 절차

  1. AWS 콘솔 상단 검색창에 "GuardDuty" 입력 → GuardDuty 클릭
  2. 왼쪽 메뉴에서 "설정(Settings)" 클릭
  3. 페이지 하단으로 스크롤하여 "GuardDuty 비활성화" 섹션 찾기
  4. "비활성화(Disable)" 또는 "GuardDuty 일시 중지/비활성화" 버튼 클릭
  5. 확인 창에서 "비활성화" 클릭

비활성화 후 GuardDuty 콘솔에 "GuardDuty가 비활성화되었습니다" 메시지가 표시되면 성공입니다.

AWS CLI 명령어

bash
# 1. GuardDuty Detector ID 확인
aws guardduty list-detectors \
  --region ap-northeast-2

출력에서 DetectorIds 배열의 값을 복사합니다.

bash
# 2. GuardDuty Detector 삭제 (비활성화)
aws guardduty delete-detector \
  --detector-id <DETECTOR_ID> \
  --region ap-northeast-2
bash
# 3. 삭제 확인 (빈 배열이면 성공)
aws guardduty list-detectors \
  --region ap-northeast-2
강사 해설

GuardDuty는 사용량 기반 과금입니다. 분석한 CloudTrail 이벤트, VPC Flow Logs, DNS 쿼리 로그의 양에 따라 비용이 결정됩니다. 비활성화(Detector 삭제)하면 즉시 분석이 중지되어 추가 과금이 발생하지 않습니다. 처음 활성화 시 30일 무료 체험이 제공되므로, 실습 기간이 30일 이내라면 비용이 발생하지 않았을 수 있습니다. 단, Detector를 삭제하면 기존에 탐지된 모든 결과(Findings)가 삭제되므로, 실무에서는 비활성화 전에 결과를 내보내는 것이 좋습니다.

Part 2-2. CloudTrail 트레일 삭제

답안

웹 콘솔 절차

  1. AWS 콘솔 상단 검색창에 "CloudTrail" 입력 → CloudTrail 클릭
  2. 왼쪽 메뉴에서 "트레일" 클릭
  3. ShopEasy-Trail 선택 → "삭제" 클릭
  4. 확인 창에서 "삭제" 클릭
  5. CloudTrail 로그 S3 버킷 정리 (전용 버킷을 생성한 경우):
    • S3 → shopeasy-cloudtrail-logs-<ACCOUNT_ID> 버킷 선택
    • "비우기(Empty)" → "영구 삭제" 입력 → 비우기
    • 비워진 버킷 선택 → "삭제" → 버킷 이름 입력 → 삭제

AWS CLI 명령어

bash
# 1. CloudTrail 트레일 목록 확인
aws cloudtrail describe-trails \
  --region ap-northeast-2 \
  --query "trailList[*].[Name,S3BucketName]" \
  --output table
bash
# 2. CloudTrail 트레일 삭제
aws cloudtrail delete-trail \
  --name ShopEasy-Trail \
  --region ap-northeast-2
bash
# 3. CloudTrail 로그 S3 버킷 삭제 (전용 버킷을 생성한 경우)
aws s3 rb s3://shopeasy-cloudtrail-logs-<ACCOUNT_ID> --force
bash
# 4. 삭제 확인 (트레일이 없으면 성공)
aws cloudtrail describe-trails \
  --region ap-northeast-2 \
  --query "trailList[?TrailName=='ShopEasy-Trail']"
강사 해설

CloudTrail 트레일을 삭제해도 이미 S3에 저장된 로그 파일은 삭제되지 않습니다. S3 스토리지 비용이 계속 발생할 수 있으므로, 트레일 전용 S3 버킷을 생성한 경우 반드시 해당 버킷도 비우고 삭제해야 합니다. aws s3 rb --force 명령은 버킷 비우기와 삭제를 한 번에 수행합니다. 참고로 CloudTrail은 관리 이벤트 1개 트레일까지 무료이므로, 트레일 자체의 비용보다는 S3 저장 비용이 주요 과금 요인입니다.

Part 2-3. Secrets Manager 시크릿 삭제

답안

웹 콘솔 절차

  1. AWS 콘솔 상단 검색창에 "Secrets Manager" 입력 → Secrets Manager 클릭
  2. 보안 암호 목록에서 ShopEasy/DB-Credentials 선택
  3. "작업""보안 암호 삭제" 클릭
  4. 대기 기간 설정: "대기 기간 없이 강제 삭제" 체크 (또는 대기 기간을 최소 7일로 설정)
  5. "삭제 예약" 클릭

"대기 기간 없이 강제 삭제"를 선택하면 시크릿이 즉시 영구 삭제됩니다. 복구할 수 없으므로 주의하세요.

AWS CLI 명령어

bash
# 1. Secrets Manager 시크릿 목록 확인
aws secretsmanager list-secrets \
  --query "SecretList[*].[Name,ARN]" \
  --output table \
  --region ap-northeast-2
bash
# 2. 시크릿 즉시 삭제 (복구 대기 없이)
aws secretsmanager delete-secret \
  --secret-id ShopEasy/DB-Credentials \
  --force-delete-without-recovery \
  --region ap-northeast-2
bash
# 3. 삭제 확인
aws secretsmanager list-secrets \
  --query "SecretList[?Name=='ShopEasy/DB-Credentials']" \
  --region ap-northeast-2

--force-delete-without-recovery 옵션을 사용하면 30일 복구 대기 기간 없이 즉시 삭제됩니다. 이 옵션을 사용하지 않으면 기본 30일 동안 "삭제 예정" 상태로 유지되며, 이 기간 동안에도 과금이 발생합니다.

강사 해설

Secrets Manager는 시크릿당 월 $0.40이 과금됩니다. 비싸지는 않지만 불필요한 시크릿은 삭제하는 것이 좋습니다. 기본 삭제 시 30일 복구 대기 기간이 있어, 이 기간 동안 restore-secret으로 복구할 수 있습니다. 실습 정리 시에는 --force-delete-without-recovery로 즉시 삭제하여 과금을 중지합니다. 실무에서는 실수로 삭제하는 것을 방지하기 위해 복구 대기 기간을 활용하는 것이 권장됩니다.

Part 2-4. KMS 키 삭제 예약 (커스텀 키를 생성한 경우)

답안

웹 콘솔 절차

  1. AWS 콘솔 상단 검색창에 "KMS" 입력 → Key Management Service 클릭
  2. 왼쪽 메뉴에서 "고객 관리형 키" 클릭
  3. ShopEasy 관련 커스텀 키가 있는지 확인
  4. 커스텀 키가 있는 경우:
    • 키 선택 → "키 작업""키 삭제 예약"
    • 대기 기간: 7일 (최소값)
    • "이 키를 삭제하면..." 확인 체크 → "삭제 예약"
  5. 커스텀 키가 없는 경우 (AWS 관리형 키만 사용):
    • 이 단계를 건너뜁니다
    • AWS 관리형 키 (aws/s3, aws/rds 등)는 삭제할 필요가 없습니다

키가 "삭제 예정(Pending deletion)" 상태로 변경되면 성공입니다. 7일 후 자동으로 영구 삭제됩니다.

AWS CLI 명령어

bash
# 1. 고객 관리형 키 목록 확인
aws kms list-keys \
  --region ap-northeast-2 \
  --query "Keys[*].KeyId" \
  --output table
bash
# 2. 각 키의 상세 정보 확인 (관리형 여부 판단)
aws kms describe-key \
  --key-id <KEY_ID> \
  --region ap-northeast-2 \
  --query "KeyMetadata.[KeyId,KeyManager,Description,KeyState]" \
  --output table

KeyManager"CUSTOMER"인 키만 삭제 대상입니다. "AWS"인 키는 AWS 관리형이므로 삭제하지 않습니다.

bash
# 3. 커스텀 키 삭제 예약 (7일 대기)
aws kms schedule-key-deletion \
  --key-id <KEY_ID> \
  --pending-window-in-days 7 \
  --region ap-northeast-2
bash
# 4. 키 상태 확인 (PendingDeletion이면 성공)
aws kms describe-key \
  --key-id <KEY_ID> \
  --region ap-northeast-2 \
  --query "KeyMetadata.KeyState" \
  --output text
강사 해설

KMS 키는 보안상의 이유로 즉시 삭제할 수 없습니다. 최소 7일, 최대 30일의 대기 기간이 필요합니다. 대기 기간 동안 키는 "PendingDeletion" 상태가 되어 사용할 수 없지만, cancel-key-deletion으로 삭제를 취소할 수 있습니다. 이 실습에서 AWS 관리형 키만 사용한 경우 이 단계는 건너뛰어도 됩니다. AWS 관리형 키는 사용하지 않으면 비용이 발생하지 않습니다. 커스텀 CMK는 키당 월 $1이 과금되므로, 불필요하면 삭제 예약하는 것이 좋습니다.

Part 2-5. CloudWatch 경보 및 대시보드 삭제

답안

웹 콘솔 절차

  1. CloudWatch → 왼쪽 "경보""모든 경보"
  2. ShopEasy-EC2-High-CPU 체크 → "작업""삭제"
  3. CloudWatch → 왼쪽 "대시보드"
  4. ShopEasy-Dashboard 체크 → "삭제" → 확인 창에서 "삭제" 입력

AWS CLI 명령어

bash
# CloudWatch 경보 삭제
aws cloudwatch delete-alarms \
  --alarm-names ShopEasy-EC2-High-CPU \
  --region ap-northeast-2

# CloudWatch 대시보드 삭제
aws cloudwatch delete-dashboards \
  --dashboard-names ShopEasy-Dashboard \
  --region ap-northeast-2

Part 2-6. SNS 주제 삭제

답안

웹 콘솔 절차

  1. SNS → 왼쪽 "주제"
  2. ShopEasy-Alerts 체크 → "삭제"
  3. 확인 창에서 "삭제" 입력 → 삭제

주제를 삭제하면 연결된 구독도 자동으로 삭제됩니다.

AWS CLI 명령어

bash
# SNS 주제 ARN 확인
aws sns list-topics \
  --query "Topics[?contains(TopicArn, 'ShopEasy')]" \
  --region ap-northeast-2

# SNS 주제 삭제
aws sns delete-topic \
  --topic-arn arn:aws:sns:ap-northeast-2:<계정ID>:ShopEasy-Alerts \
  --region ap-northeast-2

Part 2-7. NAT Gateway 삭제

답안

웹 콘솔 절차

  1. VPC → 왼쪽 "NAT 게이트웨이"
  2. ShopEasy-NAT 선택 → "작업""NAT 게이트웨이 삭제"
  3. 확인 창에서 "삭제" 입력 → 삭제
  4. 상태가 "Deleting""Deleted"로 변경될 때까지 대기 (수 분 소요)

AWS CLI 명령어

bash
# NAT Gateway ID 확인
aws ec2 describe-nat-gateways \
  --filter "Name=tag:Name,Values=*ShopEasy*" \
  --query "NatGateways[*].[NatGatewayId,State,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# NAT Gateway 삭제
aws ec2 delete-nat-gateway \
  --nat-gateway-id <NAT-게이트웨이-ID> \
  --region ap-northeast-2
bash
# 삭제 상태 확인 (Deleted가 될 때까지 반복)
aws ec2 describe-nat-gateways \
  --nat-gateway-ids <NAT-게이트웨이-ID> \
  --query "NatGateways[0].State" \
  --output text \
  --region ap-northeast-2
강사 안내

NAT Gateway는 시간당 ~$0.059 과금이므로 가장 먼저 삭제하도록 강조하세요. 삭제에 2~5분 소요되며, 이 시간 동안 학생들에게 다른 삭제 작업의 순서를 설명할 수 있습니다. Elastic IP는 NAT Gateway가 완전히 삭제된 후에 해제할 수 있습니다.

Part 2-8. Elastic IP 해제

답안

웹 콘솔 절차

  1. VPC → 왼쪽 "탄력적 IP" (또는 EC2 → "탄력적 IP 주소")
  2. NAT Gateway에 사용했던 EIP 선택 (연결 ID가 비어 있는 것)
  3. "작업""탄력적 IP 주소 릴리스"
  4. 확인 → 릴리스

AWS CLI 명령어

bash
# 할당된 Elastic IP 목록 확인
aws ec2 describe-addresses \
  --query "Addresses[*].[AllocationId,PublicIp,AssociationId,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# Elastic IP 해제 (AssociationId가 없는 = 미연결 상태인 EIP)
aws ec2 release-address \
  --allocation-id <Elastic-IP-할당-ID> \
  --region ap-northeast-2

Part 2-9. RDS 인스턴스 삭제

답안

웹 콘솔 절차

  1. RDS → "데이터베이스"
  2. ShopEasy DB 인스턴스 선택 → "작업""삭제"
  3. 삭제 방지가 활성화된 경우 (삭제 버튼이 비활성화):
    • 인스턴스 선택 → "수정"
    • 맨 아래 "삭제 방지" 체크 해제
    • "계속""즉시 적용" 선택 → "DB 인스턴스 수정"
    • 다시 삭제 시도
  4. "최종 스냅샷을 생성하시겠습니까?" → "아니요" 선택
  5. "자동 백업 보존" 체크 해제
  6. "I acknowledge that upon instance deletion..." 체크
  7. 확인 입력란에 "delete me" 입력 → "삭제"

삭제 완료까지 수 분~10분 소요됩니다. 상태가 "Deleting"에서 사라질 때까지 기다리세요.

AWS CLI 명령어

bash
# RDS 인스턴스 목록 확인
aws rds describe-db-instances \
  --query "DBInstances[*].[DBInstanceIdentifier,DBInstanceStatus,DeletionProtection]" \
  --output table \
  --region ap-northeast-2

# 삭제 방지 비활성화 (필요한 경우)
aws rds modify-db-instance \
  --db-instance-identifier <RDS-인스턴스-이름> \
  --no-deletion-protection \
  --apply-immediately \
  --region ap-northeast-2

# RDS 인스턴스 삭제 (최종 스냅샷 생략)
aws rds delete-db-instance \
  --db-instance-identifier <RDS-인스턴스-이름> \
  --skip-final-snapshot \
  --delete-automated-backups \
  --region ap-northeast-2
bash
# 삭제 상태 확인
aws rds describe-db-instances \
  --db-instance-identifier <RDS-인스턴스-이름> \
  --query "DBInstances[0].DBInstanceStatus" \
  --output text \
  --region ap-northeast-2

Part 2-10. RDS 서브넷 그룹 삭제

답안

웹 콘솔 절차

  1. RDS → 왼쪽 "서브넷 그룹"
  2. ShopEasy DB 서브넷 그룹 선택 → "삭제"
  3. 확인 → 삭제

RDS 인스턴스가 아직 삭제 중이면 "서브넷 그룹이 사용 중" 오류가 발생합니다. RDS 삭제가 완료될 때까지 기다려주세요.

AWS CLI 명령어

bash
# DB 서브넷 그룹 목록 확인
aws rds describe-db-subnet-groups \
  --query "DBSubnetGroups[*].[DBSubnetGroupName,DBSubnetGroupDescription]" \
  --output table \
  --region ap-northeast-2

# DB 서브넷 그룹 삭제
aws rds delete-db-subnet-group \
  --db-subnet-group-name <서브넷-그룹-이름> \
  --region ap-northeast-2

Part 2-11. EC2 인스턴스 종료

답안

웹 콘솔 절차

  1. EC2 → "인스턴스"
  2. ShopEasy EC2 인스턴스 선택
  3. 종료 방지가 켜져 있는 경우:
    • 인스턴스 선택 → "작업""인스턴스 설정""종료 방지 변경"
    • "비활성화" 선택 → 저장
  4. "인스턴스 상태""인스턴스 종료"
  5. 확인 창에서 "종료" 클릭

상태가 "종료됨(Terminated)"으로 변경됩니다. 종료된 인스턴스는 약 1시간 후 목록에서 사라집니다.

AWS CLI 명령어

bash
# EC2 인스턴스 ID 확인
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=*ShopEasy*" "Name=instance-state-name,Values=running,stopped" \
  --query "Reservations[*].Instances[*].[InstanceId,Tags[?Key=='Name'].Value|[0],State.Name]" \
  --output table \
  --region ap-northeast-2

# 종료 방지 비활성화 (필요한 경우)
aws ec2 modify-instance-attribute \
  --instance-id <EC2-인스턴스-ID> \
  --no-disable-api-termination \
  --region ap-northeast-2

# EC2 인스턴스 종료
aws ec2 terminate-instances \
  --instance-ids <EC2-인스턴스-ID> \
  --region ap-northeast-2
강사 안내

"중지(Stop)"와 "종료(Terminate)"의 차이를 반드시 강조하세요. 중지는 EBS 볼륨이 유지되어 스토리지 비용이 계속 발생합니다. 종료해야 인스턴스와 연결된 EBS 볼륨(Delete on Termination 설정인 경우)이 함께 삭제됩니다.

Part 2-12. S3 버킷 비우기 + 삭제

답안

웹 콘솔 절차 (각 버킷에 대해 반복)

  1. S3 → "버킷"
  2. ShopEasy 이미지 버킷 선택 → "비우기"
  3. 확인 창에서 "영구 삭제" 입력 → "비우기"
  4. 비워진 버킷 선택 → "삭제"
  5. 버킷 이름 입력 → "버킷 삭제"
  6. ShopEasy 프론트엔드 버킷에 대해서도 동일하게 반복

AWS CLI 명령어

bash
# S3 버킷 목록 확인
aws s3 ls

# 이미지 버킷 비우기 + 삭제
aws s3 rm s3://<이미지-버킷-이름> --recursive
aws s3 rb s3://<이미지-버킷-이름>

# 프론트엔드 버킷 비우기 + 삭제
aws s3 rm s3://<프론트엔드-버킷-이름> --recursive
aws s3 rb s3://<프론트엔드-버킷-이름>

s3 rm --recursive는 버킷 내 모든 객체를 재귀적으로 삭제합니다. s3 rb는 빈 버킷을 삭제합니다. 또는 s3 rb --force를 사용하면 비우기와 삭제를 한 번에 할 수 있습니다:

bash
# 한 번에 비우기 + 삭제 (--force 옵션)
aws s3 rb s3://<이미지-버킷-이름> --force
aws s3 rb s3://<프론트엔드-버킷-이름> --force

Part 2-13. DynamoDB 테이블 삭제

답안

웹 콘솔 절차

  1. DynamoDB → "테이블"
  2. ShopEasy 리뷰 테이블 선택 → "삭제"
  3. "모든 CloudWatch 경보 삭제" 체크 (관련 경보가 있는 경우)
  4. "백업 생성" 체크 해제
  5. 확인 창에서 "삭제" 입력 → "테이블 삭제"

AWS CLI 명령어

bash
# DynamoDB 테이블 목록 확인
aws dynamodb list-tables \
  --region ap-northeast-2

# DynamoDB 테이블 삭제
aws dynamodb delete-table \
  --table-name <테이블-이름> \
  --region ap-northeast-2

Part 2-14. IAM 역할 정리

답안

웹 콘솔 절차

  1. 14-1. 인스턴스 프로파일에서 역할 확인:
    • IAM → "역할" → ShopEasy 역할 클릭
  2. 14-2. 역할에서 정책 분리:
    • 역할 상세 페이지 → "권한"
    • 각 정책 옆의 "분리" 또는 "X" 클릭 → 확인
    • 모든 정책이 분리될 때까지 반복
  3. 14-3. 커스텀 정책 삭제:
    • IAM → "정책" → 필터: "고객 관리형"
    • ShopEasy 관련 정책 선택 → "삭제"
    • 정책 이름 입력 → 삭제 확인
  4. 14-4. 역할 삭제:
    • IAM → "역할" → ShopEasy 역할 선택 → "삭제"
    • 역할 이름 입력 → 삭제 확인

AWS CLI 명령어

bash
# 역할에 연결된 정책 확인
aws iam list-attached-role-policies \
  --role-name <ShopEasy-역할-이름>

# 역할에서 관리형 정책 분리 (각 정책에 대해 반복)
aws iam detach-role-policy \
  --role-name <ShopEasy-역할-이름> \
  --policy-arn <정책-ARN>

# 역할에 연결된 인라인 정책 확인 및 삭제
aws iam list-role-policies \
  --role-name <ShopEasy-역할-이름>

aws iam delete-role-policy \
  --role-name <ShopEasy-역할-이름> \
  --policy-name <인라인-정책-이름>

# 인스턴스 프로파일에서 역할 제거 (인스턴스 프로파일이 있는 경우)
aws iam remove-role-from-instance-profile \
  --instance-profile-name <인스턴스-프로파일-이름> \
  --role-name <ShopEasy-역할-이름>

# 인스턴스 프로파일 삭제
aws iam delete-instance-profile \
  --instance-profile-name <인스턴스-프로파일-이름>

# 커스텀 정책 삭제
aws iam delete-policy \
  --policy-arn <커스텀-정책-ARN>

# 역할 삭제
aws iam delete-role \
  --role-name <ShopEasy-역할-이름>
강사 해설

IAM 역할 삭제는 여러 단계가 필요합니다. 역할에 정책이 연결되어 있으면 삭제할 수 없고, 인스턴스 프로파일에 역할이 연결되어 있으면 먼저 분리해야 합니다. 웹 콘솔에서 역할을 삭제하면 인스턴스 프로파일도 자동으로 정리되지만, CLI에서는 각 단계를 수동으로 처리해야 합니다.

Part 2-15. 보안 그룹 삭제

답안

웹 콘솔 절차

  1. VPC → "보안 그룹" (또는 EC2 → "보안 그룹")
  2. VPC 필터로 ShopEasy-VPC에 속한 보안 그룹만 표시
  3. 삭제 순서 (참조 관계 확인):
    • 먼저 다른 보안 그룹을 참조하지 않는 것부터 삭제
    • 예: RDS 보안 그룹이 EC2 보안 그룹을 참조하면, RDS SG의 해당 규칙을 먼저 수정/삭제 후 EC2 SG 삭제
  4. ShopEasy EC2 보안 그룹 선택 → "작업""보안 그룹 삭제"
  5. ShopEasy RDS 보안 그룹 선택 → "작업""보안 그룹 삭제"
  6. default 보안 그룹은 삭제하지 않음 (VPC 삭제 시 자동 삭제)

AWS CLI 명령어

bash
# ShopEasy VPC의 보안 그룹 목록 확인
aws ec2 describe-security-groups \
  --filters "Name=vpc-id,Values=<VPC-ID>" \
  --query "SecurityGroups[*].[GroupId,GroupName]" \
  --output table \
  --region ap-northeast-2

# 보안 그룹 간 참조 확인 (인그레스 규칙에 다른 SG가 있는지)
aws ec2 describe-security-groups \
  --group-ids <보안그룹-ID> \
  --query "SecurityGroups[*].IpPermissions[*].UserIdGroupPairs" \
  --region ap-northeast-2

# 보안 그룹 삭제 (default 제외)
aws ec2 delete-security-group \
  --group-id <EC2-보안그룹-ID> \
  --region ap-northeast-2

aws ec2 delete-security-group \
  --group-id <RDS-보안그룹-ID> \
  --region ap-northeast-2

Part 2-16. 인터넷 게이트웨이 분리 + 삭제

답안

웹 콘솔 절차

  1. VPC → "인터넷 게이트웨이"
  2. ShopEasy-IGW 선택 → "작업""VPC에서 분리"
  3. 확인 → "인터넷 게이트웨이 분리"
  4. 분리된 IGW 선택 → "작업""인터넷 게이트웨이 삭제"
  5. 확인 창에서 "삭제" 입력 → 삭제

AWS CLI 명령어

bash
# IGW 확인
aws ec2 describe-internet-gateways \
  --filters "Name=tag:Name,Values=*ShopEasy*" \
  --query "InternetGateways[*].[InternetGatewayId,Attachments[0].VpcId,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# IGW를 VPC에서 분리
aws ec2 detach-internet-gateway \
  --internet-gateway-id <IGW-ID> \
  --vpc-id <VPC-ID> \
  --region ap-northeast-2

# IGW 삭제
aws ec2 delete-internet-gateway \
  --internet-gateway-id <IGW-ID> \
  --region ap-northeast-2

Part 2-17. 서브넷 삭제 (4개)

답안

웹 콘솔 절차

  1. VPC → "서브넷"
  2. VPC 필터로 ShopEasy-VPC에 속한 서브넷만 표시
  3. 4개 서브넷 모두 체크: ShopEasy-Public-A, ShopEasy-Public-C, ShopEasy-Private-A, ShopEasy-Private-C
  4. "작업""서브넷 삭제"
  5. 확인 창에서 "삭제" 입력 → 삭제

AWS CLI 명령어

bash
# 서브넷 목록 확인
aws ec2 describe-subnets \
  --filters "Name=vpc-id,Values=<VPC-ID>" \
  --query "Subnets[*].[SubnetId,CidrBlock,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# 서브넷 삭제 (4개 각각)
aws ec2 delete-subnet --subnet-id <Public-A-서브넷-ID> --region ap-northeast-2
aws ec2 delete-subnet --subnet-id <Public-C-서브넷-ID> --region ap-northeast-2
aws ec2 delete-subnet --subnet-id <Private-A-서브넷-ID> --region ap-northeast-2
aws ec2 delete-subnet --subnet-id <Private-C-서브넷-ID> --region ap-northeast-2

Part 2-18. 라우트 테이블 삭제

답안

웹 콘솔 절차

  1. VPC → "라우트 테이블"
  2. VPC 필터로 ShopEasy-VPC에 속한 라우트 테이블만 표시
  3. "Main" 열이 "No"인 것만 선택 (기본 RT는 삭제하지 않음)
  4. ShopEasy-Public-RT 선택 → "작업""라우트 테이블 삭제"
  5. ShopEasy-Private-RT 선택 → "작업""라우트 테이블 삭제"

서브넷 연결이 아직 남아 있으면 먼저 "서브넷 연결" 탭에서 연결을 편집하여 해제하세요. (서브넷이 이미 삭제되었다면 연결도 자동으로 해제되어 있습니다)

AWS CLI 명령어

bash
# 라우트 테이블 목록 확인 (Main이 아닌 것만)
aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=<VPC-ID>" \
  --query "RouteTables[?Associations[0].Main!=\`true\`].[RouteTableId,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# 라우트 테이블 삭제
aws ec2 delete-route-table \
  --route-table-id <Public-RT-ID> \
  --region ap-northeast-2

aws ec2 delete-route-table \
  --route-table-id <Private-RT-ID> \
  --region ap-northeast-2

Part 2-19. VPC 삭제

답안

웹 콘솔 절차

  1. VPC → "VPC"
  2. ShopEasy-VPC 선택 → "작업""VPC 삭제"
  3. 확인 창에서 "삭제" 입력 → 삭제

VPC 삭제 시 기본(default) 라우트 테이블, 기본 보안 그룹, 기본 NACL이 함께 삭제됩니다.

오류가 발생하면 아직 삭제되지 않은 리소스가 있다는 의미입니다. 오류 메시지에서 리소스 ID를 확인하고 해당 리소스를 먼저 삭제하세요.

AWS CLI 명령어

bash
# VPC ID 확인
aws ec2 describe-vpcs \
  --filters "Name=tag:Name,Values=*ShopEasy*" \
  --query "Vpcs[*].[VpcId,CidrBlock,Tags[?Key=='Name'].Value|[0]]" \
  --output table \
  --region ap-northeast-2

# VPC 삭제
aws ec2 delete-vpc \
  --vpc-id <VPC-ID> \
  --region ap-northeast-2
bash
# VPC 삭제 확인 (결과가 비어 있으면 성공)
aws ec2 describe-vpcs \
  --filters "Name=tag:Name,Values=*ShopEasy*" \
  --query "Vpcs[*].VpcId" \
  --output text \
  --region ap-northeast-2
강사 확인 포인트

VPC가 성공적으로 삭제되면 모든 하위 네트워크 리소스가 정리된 것입니다. 학생들에게 VPC 목록에서 ShopEasy-VPC가 사라졌는지 확인하도록 안내하세요. default VPC는 그대로 남아 있어야 합니다.

트러블슈팅

자주 발생하는 문제와 해결 방법

NAT Gateway 삭제가 안 됨 / 오래 걸림

NAT Gateway 삭제 요청 후 상태가 "Deleting"으로 변경되며, 완전히 삭제되기까지 2~5분이 소요됩니다. 이것은 정상적인 동작입니다. "Deleted" 상태가 될 때까지 기다려주세요.

NAT Gateway가 삭제되는 동안 Elastic IP를 해제하려고 하면 실패합니다. NAT Gateway가 완전히 삭제된 후에 EIP를 해제하세요.

bash
# NAT Gateway 상태 확인
aws ec2 describe-nat-gateways \
  --nat-gateway-ids <NAT-GW-ID> \
  --query "NatGateways[0].State" \
  --output text \
  --region ap-northeast-2
VPC 삭제가 안 됨 - "has dependencies"

VPC에 연결된 리소스가 남아 있으면 삭제할 수 없습니다. 다음 명령어로 VPC에 남아 있는 리소스를 확인하세요:

bash
# VPC 내 남은 ENI(네트워크 인터페이스) 확인
aws ec2 describe-network-interfaces \
  --filters "Name=vpc-id,Values=<VPC-ID>" \
  --query "NetworkInterfaces[*].[NetworkInterfaceId,Description,Status]" \
  --output table \
  --region ap-northeast-2

# VPC 내 남은 보안 그룹 확인
aws ec2 describe-security-groups \
  --filters "Name=vpc-id,Values=<VPC-ID>" \
  --query "SecurityGroups[*].[GroupId,GroupName]" \
  --output table \
  --region ap-northeast-2

# VPC 내 남은 서브넷 확인
aws ec2 describe-subnets \
  --filters "Name=vpc-id,Values=<VPC-ID>" \
  --query "Subnets[*].[SubnetId,CidrBlock]" \
  --output table \
  --region ap-northeast-2

# VPC에 연결된 IGW 확인
aws ec2 describe-internet-gateways \
  --filters "Name=attachment.vpc-id,Values=<VPC-ID>" \
  --query "InternetGateways[*].InternetGatewayId" \
  --output text \
  --region ap-northeast-2

확인된 리소스를 먼저 삭제한 후 다시 VPC 삭제를 시도하세요. 특히 네트워크 인터페이스(ENI)가 남아 있는 경우가 많습니다. Lambda, ELB, NAT Gateway 등이 생성한 ENI가 아직 정리되지 않았을 수 있습니다.

S3 버킷 삭제가 안 됨 - "BucketNotEmpty"

S3 버킷은 비어 있어야 삭제할 수 있습니다. "비우기(Empty)"를 먼저 실행하세요. 버전 관리(Versioning)가 활성화된 경우, 삭제 마커와 이전 버전도 모두 제거해야 합니다.

bash
# 버킷 내 객체 확인
aws s3 ls s3://<버킷-이름> --recursive

# 모든 객체 삭제
aws s3 rm s3://<버킷-이름> --recursive

# 버전 관리가 활성화된 경우 - 모든 버전 삭제
aws s3api list-object-versions \
  --bucket <버킷-이름> \
  --query "Versions[*].[Key,VersionId]" \
  --output text

# 강제 삭제 (비우기 + 삭제)
aws s3 rb s3://<버킷-이름> --force
RDS 삭제가 오래 걸림

RDS 인스턴스 삭제는 정상적으로 수 분에서 최대 10분이 소요됩니다. 최종 스냅샷을 생성하도록 설정한 경우 더 오래 걸릴 수 있습니다. 삭제가 진행되는 동안("Deleting" 상태) 다른 리소스를 먼저 정리하도록 안내하세요.

단, RDS 서브넷 그룹은 RDS 삭제가 완료된 후에만 삭제할 수 있으므로, 서브넷 그룹 삭제는 RDS 삭제 완료 후 진행합니다.

보안 그룹 삭제가 안 됨 - "resource has a dependent object"

다른 보안 그룹의 인바운드/아웃바운드 규칙에서 이 보안 그룹 ID를 참조하고 있으면 삭제할 수 없습니다.

해결 방법:

  1. 참조하는 보안 그룹을 찾아서 해당 규칙을 수정하거나 삭제
  2. 또는 참조 관계에서 보안 그룹 ID 대신 IP CIDR로 변경
  3. 그런 다음 다시 삭제 시도
bash
# 특정 보안 그룹을 참조하는 다른 보안 그룹 찾기
aws ec2 describe-security-groups \
  --filters "Name=ip-permission.group-id,Values=<삭제하려는-SG-ID>" \
  --query "SecurityGroups[*].[GroupId,GroupName]" \
  --output table \
  --region ap-northeast-2
Elastic IP 해제가 안 됨 - "is associated with"

Elastic IP가 아직 다른 리소스(NAT Gateway, EC2 등)에 연결되어 있으면 해제할 수 없습니다. 연결된 리소스가 완전히 삭제될 때까지 기다린 후 다시 시도하세요.

bash
# EIP 연결 상태 확인
aws ec2 describe-addresses \
  --query "Addresses[*].[AllocationId,PublicIp,AssociationId,InstanceId,NetworkInterfaceId]" \
  --output table \
  --region ap-northeast-2

AssociationId가 있으면 아직 연결된 상태입니다. NAT Gateway 삭제가 완료되면 자동으로 연결이 해제됩니다.

강의 팁

시간 관리 전략
  • Part 1 (모니터링): 20~30분 할당. SNS 이메일 확인에 시간이 걸릴 수 있으므로 먼저 진행
  • Part 2 (리소스 정리): 30~40분 할당. NAT Gateway와 RDS 삭제를 먼저 시작하고, 삭제 대기 시간에 다른 리소스를 정리하도록 안내
  • NAT Gateway 먼저: 시간당 과금이 가장 크므로 Part 2 시작과 동시에 NAT Gateway 삭제를 먼저 실행하도록 안내
  • RDS 병렬 처리: RDS 삭제도 일찍 시작하고, 삭제가 진행되는 동안 EC2, S3, DynamoDB 등을 정리
학생 실수 대비
  • EC2 "중지"와 "종료" 혼동: 반드시 "종료(Terminate)"를 선택하도록 여러 번 강조하세요. "중지(Stop)"는 EBS 비용이 계속 발생합니다.
  • default VPC/SG 삭제 시도: ShopEasy-VPC의 리소스만 삭제하도록 안내하세요. 기본(default) VPC나 보안 그룹은 삭제하지 않도록 주의합니다.
  • 리전 확인: 다른 리전에 리소스를 만든 학생이 있을 수 있습니다. ap-northeast-2(서울) 리전인지 반드시 확인하도록 합니다.
  • S3 비우기 건너뛰기: S3 버킷을 비우지 않고 삭제하려다 오류가 나는 경우가 많습니다. "비우기 → 삭제" 2단계를 강조하세요.
수업 종료 전 최종 확인

수업을 마치기 전에 반드시 전체 학생의 리소스 삭제 상태를 확인하세요. 특히 다음 항목은 방치하면 높은 비용이 발생합니다:

  1. NAT Gateway - 삭제되었는지 반드시 확인 (월 ~$43)
  2. RDS 인스턴스 - "Deleting" 상태로 진행 중이면 OK, "Available"이면 삭제 안 된 것 (월 ~$19)
  3. EC2 인스턴스 - "Terminated" 상태인지 확인 (월 ~$8.5)
  4. Elastic IP - 모두 해제되었는지 확인 (월 ~$3.6)
  5. VPC - 삭제되었으면 위의 네트워크 리소스도 모두 정리된 것

학생의 AWS 계정에 로그인하여 직접 확인하거나, 학생에게 VPC 목록, EC2 목록, RDS 목록의 스크린샷을 제출하도록 하세요.

전체 과정 마무리 강의 포인트
  • 14개 챕터에서 배운 AWS 서비스를 정리하고, 각 서비스의 역할을 복습
  • VPC → EC2 → RDS → IAM → S3 → DynamoDB → S3 Hosting → 보안 그룹 → IAM 최소 권한 → S3 보안 → KMS → Secrets Manager → CloudTrail → GuardDuty → CloudWatch 흐름
  • 실무에서는 이 구조에 ALB, Auto Scaling, CloudFront, Route 53, ACM(HTTPS) 등을 추가
  • IaC(Infrastructure as Code) 도구인 CloudFormation, Terraform으로 리소스 생성/삭제를 자동화할 수 있음을 소개
  • 리소스 정리의 중요성 - 태그(Tag)를 활용한 비용 관리, AWS Config를 이용한 리소스 추적 등 실무 팁