Kiro, Amazon Q CLI, Claude Code 같은 AI 기반 CLI 도구들이 AWS 인프라 운영의 생산성을 극적으로 끌어올리고 있습니다. 리소스 생성, 설정 변경, 현황 조사까지 자연어 한 줄이면 되니까요. 그런데 이 편리함에는 조용한 함정이 숨어 있습니다.
AI가 "결과가 없습니다"라고 답했을 때, 그것이 정말로 리소스가 없는 것인지, 권한이 없어서 못 본 것인지 구분할 수 있으신가요?
이 글은 AI CLI 도구를 활용한 AWS 운영에서 흔히 발생하는 무음 실패(Silent Failure) 패턴과, 이를 방지하기 위한 프롬프트 레벨 검증 가드레일 설계에 대해 다룹니다.
AWS CLI 자체는 권한이 없으면 AccessDenied 에러를 명확히 뱉습니다. 문제는 AI 에이전트가 이 에러를 해석하는 과정에서 발생합니다.
IAM 권한이 부족한 상태에서 특정 리소스 현황을 조회하도록 요청했습니다. AI는 API 호출 후 다음과 같이 답변했습니다.
"조회 결과, 해당 리소스는 존재하지 않습니다."
실제로는 리소스가 존재했습니다. AI가 AccessDenied 응답을 받았지만, 이를 "데이터 없음"으로 해석해버린 것입니다. 만약 이 결과를 그대로 믿고 "리소스가 없으니 새로 만들자"고 진행했다면? 중복 생성, 설정 충돌, 혹은 기존 리소스를 덮어쓰는 운영 사고로 이어질 수 있었습니다.
AI CLI 에이전트의 동작 구조를 뜯어보면 원인이 명확해집니다.
AccessDenied일 때, 성공한 7개의 결과만 보여주고 3개의 실패는 언급하지 않는 경우가 빈번합니다.가장 흔하고 가장 위험한 패턴입니다. iam:ListRolePolicies 권한이 없는 상태에서 IAM Role의 정책을 조회하면, AI는 "이 Role에는 연결된 정책이 없습니다"라고 답할 수 있습니다. 실제로는 정책이 10개 붙어 있는데도요.
"모든 리전의 EC2 인스턴스를 조사해줘"라고 요청했는데, AI가 비용이나 시간을 고려해 현재 리전 또는 2~3개 리전만 조회하고 "전체 조회 완료"라고 보고하는 경우입니다. 나머지 리전에 존재하는 리소스는 아예 누락됩니다.
AWS API는 결과가 많으면 페이지네이션으로 분할 반환합니다. AI가 첫 번째 페이지(보통 최대 100건)만 가져오고 "총 N건입니다"라고 보고하면, 실제 수백 건의 리소스 중 일부만 확인한 셈이 됩니다.
Cross-account 조회 시 AssumeRole이 실패했는데, AI가 이를 건너뛰고 현재 계정의 결과만 반환하면서 마치 전체 조직의 결과인 것처럼 보고하는 경우입니다.
특정 서비스가 아직 활성화되지 않은 리전을 조회할 때 발생하는 에러를 "해당 리전에 리소스 없음"으로 해석해버리는 경우입니다.
문제를 인식했으면 대응해야 합니다. AI CLI 도구에 작업을 지시할 때 프롬프트 자체에 검증 로직을 내장하는 것이 핵심입니다.
프롬프트에 다음과 같은 지시를 포함합니다.
모든 AWS API 호출에 대해:
- HTTP 상태 코드가 200이 아닌 경우 반드시 원본 에러 메시지를 그대로 출력할 것
- AccessDenied, UnauthorizedAccess 등의 에러가 발생하면
"조회 불가"로 명시하고, "리소스 없음"과 명확히 구분할 것
- 에러가 발생한 API 호출 목록을 별도로 정리할 것
조회 대상 리전: ap-northeast-2, us-east-1, us-west-2, eu-west-1
(위 리전을 모두 조회하고, 각 리전별로 조회 성공/실패 여부를 표로 정리할 것)
임의로 리전을 축소하지 말 것.
단순히 "모든 리전"이라고 쓰면 AI가 해석의 여지를 갖습니다. 구체적으로 리전을 열거하고, 각 리전의 조회 상태를 보고하도록 강제해야 합니다.
AWS API 응답에 NextToken 또는 Marker가 포함된 경우,
모든 페이지를 순회하여 전체 결과를 수집할 것.
최종 결과에 "총 페이지 수"와 "총 레코드 수"를 함께 보고할 것.
실제 작업 전에 권한을 먼저 확인하는 단계를 프롬프트에 넣습니다.
본 작업을 수행하기 전에:
1. sts get-caller-identity로 현재 자격 증명을 확인할 것
2. iam simulate-principal-policy로 필요한 권한 보유 여부를 사전 검증할 것
3. 권한이 부족한 항목이 있으면 작업을 진행하지 말고
부족한 권한 목록을 먼저 보고할 것
조회 결과를 최소 2가지 방법으로 교차 검증할 것.
예:
- EC2 인스턴스 수를 describe-instances와
AWS Config의 resourceCounts로 비교
- S3 버킷 목록을 s3 ls와
CloudTrail의 CreateBucket 이벤트 이력으로 대조
수치가 불일치하면 그 차이와 가능한 원인을 보고할 것.
위 원칙들을 종합한 실전 프롬프트 예시입니다. 시스템 프롬프트나 작업 프롬프트의 앞부분에 삽입해서 사용할 수 있습니다.
## AWS 운영 검증 가드레일
당신은 AWS 인프라 운영 보조 에이전트입니다.
다음 규칙을 반드시 준수하십시오.
### 에러 처리
- AWS API 호출 실패 시 원본 에러 코드와 메시지를 반드시 출력
- AccessDenied와 "리소스 없음(empty result)"을 절대 혼동하지 말 것
- 부분 실패 시 성공/실패 항목을 분리하여 보고
### 범위 관리
- 사용자가 지정한 리전, 계정, 서비스 범위를 임의로 축소하지 말 것
- 범위를 줄여야 할 합리적 사유가 있으면 먼저 사용자에게 확인
- 각 리전/계정별 조회 상태를 요약표로 제공
### 데이터 완전성
- 페이지네이션이 있는 API는 전체 페이지를 순회
- 최종 결과에 총 API 호출 수, 총 레코드 수를 명시
### 사전 검증
- 작업 시작 전 sts get-caller-identity 실행
- 필요 권한을 사전 열거하고, 부족 시 작업 중단 후 보고
### 결과 보고 형식
- "리소스 없음" 보고 시 반드시 다음을 병기:
- 조회에 사용한 정확한 API 및 파라미터
- HTTP 응답 코드
- 조회 시점의 IAM 자격 증명 (ARN)
오해하지 말아야 할 것이 있습니다. AI CLI 도구가 나쁜 것이 아닙니다. 이 도구들은 지시받은 대로 동작하고 있을 뿐입니다. 문제는 우리가 지시를 충분히 정밀하게 하지 않았다는 데 있습니다.
전통적인 스크립트 기반 자동화에서는 에러 핸들링을 코드로 명시적으로 작성했습니다. set -e, trap, || exit 1 같은 장치들이 그 역할을 했습니다. AI 에이전트 기반 운영에서는 프롬프트가 곧 에러 핸들링 코드입니다.
셸 스크립트에 set -e를 넣듯이, AI 프롬프트에 검증 가드레일을 넣어야 합니다. 안 넣으면 에러가 조용히 삼켜지고, 우리는 틀린 정보 위에서 운영 판단을 내리게 됩니다.
AI 에이전트에게 AWS 운영을 맡기는 시대가 왔습니다. 하지만 "맡긴다"는 것은 "신뢰한다"는 뜻이 아닙니다. 검증 가능한 형태로 맡기는 것입니다.
프롬프트 엔지니어링은 더 이상 "좋은 답변을 얻는 기술"만이 아닙니다. 잘못된 답변을 걸러내는 기술이기도 합니다. 특히 인프라 운영처럼 오판의 비용이 큰 영역에서는, 가드레일 없는 프롬프트는 에러 핸들링 없는 프로덕션 코드와 같습니다.
AI에게 "해줘"가 아니라 "해주되, 이렇게 검증해서 보고해"라고 말합시다.