
AWS 미경험자로부터 RHEL 취약점 알림 Bot을 Lambda로 구현한 이야기
요약
AWS 미경험자가 Claude Code와 Claude Desktop을 활용하여 RHEL 취약점 알림 봇을 Lambda로 구현한 사례입니다. AI 도구 간의 역할 분담을 통해 코드 구현과 인프라 운영 가이드를 효율적으로 처리하는 방법을 제시합니다.
핵심 포인트
- Claude Code는 코드 생성, 버그 수정, 테스트 등 구현 작업에 최적화됨
- Claude Desktop은 AWS 콘솔 조작 안내 및 운영 절차 가이드에 적합함
- AI를 활용한 단계별 가이드는 인프라 미경험자의 심리적 장벽과 실수 방지에 도움을 줌
- 비용 효율을 위해 Secrets Manager 대신 SSM Parameter Store를 활용함
평소에는 온프레미스 (On-premise) 인프라를 담당하고 있다. RHEL, vSphere.
그 정도는 다룰 수 있지만, AWS는 만져본 적이 없었다. IAM도 Lambda도 S3도, 단어로만 알고 있을 뿐.
그런 상태에서 「RHEL의 취약점 정보를 매일 아침 Discord로 보내는 도구」를 만들고, AWS Lambda에 올리는 것까지를,
Claude Code와 Claude Desktop에 역할을 분담시켜 진행한 기록입니다.
기술 기사라기보다는 체험담에 가깝지만, 「AI에게 개발을 맡길 때의 역할 분담 방식」을 통해 얻은 지견이
생각보다 재사용 가능했기에, 그 부분을 중심으로 작성합니다.
참고로, AWS의 프리 티어 (Free Tier) 범위 내에 들어오도록 구현했습니다. (아마도)
개요를 번역하고 있는 DeepL API도
프리 티어를 이용하고 있습니다.
DeepL API가
프리 티어를 초과할 경우에는 번역 없이 알림을 보내도록 설정했습니다.
AWS 계정 ID나 버킷 이름 등은 기사용을 위해 더미 값으로 교체했습니다.
매일 대량으로 공개되는 CVE (취약점 관리 번호) 중,
「RHEL과 관련이 있고, 심각도가 높은 것만」 자동으로 필터링하여 Discord에 알림을 보내는 도구입니다.
[NVD API] … 미국 정부 운영 취약점 DB. CVE 정보의 1차 취득원
↓ CVSS 스코어로 필터링
[Red Hat Security Data API] … RHEL 영향 여부 및 패치 제공 상황 확인
...
최종 구성은 다음과 같습니다.
EventBridge (평일 09:00 JST)
→ Lambda (python3.12 / 256MB / Timeout 600s)
- SSM Parameter Store에서 시크릿(Secret) 취득
...
Secrets Manager는 사용하지 않고, SSM Parameter Store (Standard)를 채택했습니다.
Secrets Manager는 시크릿 1건당 월 $0.40가 들지만, SSM Standard는 추가 과금이 없기 때문입니다.
개인 개발에서 시크릿을 몇 건 배치하는 정도라면, SSM으로 충분하다는 것이 이번의 결론입니다.
실제 Discord 알림입니다.
이 부분이 이번에 가장 쓰고 싶었던 부분입니다.
| 담당 | 수행한 작업 |
|---|---|
| Claude Code (터미널) | 구현: Python 코드 신규 생성, 버그 수정, 테스트, commit / push |
| Claude Desktop (GUI) | 운영 작업: AWS 콘솔 조작 안내, CLI 명령어 절차화, 배포 동행 |
처음에는 「전부 Claude Code로 해도 되지 않을까」라고 생각했습니다. 실제로 코드는 쓸 줄 알고,
터미널에서 CLI도 실행할 수 있으니까요.
하지만 직접 해보니, 이 두 가지는 적합한 업무가 다르다는 것을 확실히 알 수 있었습니다.
파일을 직접 읽고 직접 수정할 수 있기 때문에, 구현의 반복 속도가 빠릅니다.
「주말 분량이 누락되었다」라고 말하면, 해당 로직을 스스로 찾아 수정하고 테스트까지 통과시켜 줍니다.
이 속도감은 코드 작업에서 압도적입니다.
반대로, AWS 콘솔에서의 GUI 조작은 Claude Code의 영역 밖입니다.
「IAM 사용자를 생성한다」, 「결제 알림을 설정한다」는 브라우저에서의 클릭 작업이므로,
파일 조작 도구로는 손을 댈 수 없습니다.
그리고 또 하나 컸던 점은, **「한 단계씩 멈춰준다」**는 것이었습니다.
AWS 미경험자라면 명령어를 실행하라고 해도
「이거 과금되나?」, 「실수하면 되돌릴 수 있나?」를 몰라 손이 멈추게 됩니다.
Desktop 측에서는, 제가 질문하기 전에
- 이 명령어로 무엇이 일어나는지
- 과금이 발생하는지
- 되돌릴 수 있는지
를 먼저 설명해 주는 방식으로 진행했습니다. 결과적으로, **이해하지 못한 채 넘어간 부분이 제로(0)**로 끝났습니다.
이것은 전 자동으로 진행했다면 절대로 얻을 수 없었을 것입니다.
세션이 바뀌기 때문에 당연히 컨텍스트 (Context)는 공유되지 않습니다.
그래서 Claude Code에게 「인수인계서」를 쓰게 하고, 그것을 Claude Desktop에 전달하는 방식을 취했습니다.
HANDOFF_AWS_DEPLOY.md라는 파일을 하나 만들고, 그곳에
- 구현 완료된 내용과 파일별 역할
- 아키텍처 개요
- AWS 측에서 수행할 작업 절차
- 「작업 상대는 AWS 완전 초보자이므로, 이렇게 대해달라」는 지시
- 설계상의 제약 (프리 티어 전제이므로 Secrets Manager는 사용하지 않음 등)
을 정리해 달라고 했습니다.
이것이 상상 이상으로 효과적이었습니다. 특히 효과적이었던 것은 네 번째인 「접근 방식에 대한 지시」입니다.
실제로 다음과 같은 내용이 적혀 있었습니다.
- 명령어를 제시하기 전에, 그것이 「무엇을 하는 것인지」, 「실행하면 어떤 일이 발생하는지 (과금/리소스 생성/되돌리기 가능 여부)」를 한마디로 설명한 뒤 실행할 것
- 액세스 키(Access Key)/시크릿 키(Secret Key)는 절대로 채팅에 그대로 붙여넣거나 출력하게 하지 말 것
- 한 번에 대량의 명령어를 흘려보내지 말고, 1~2단계씩 진행하며 그때마다 결과를 확인할 것
「무엇을 만들었는가」뿐만 아니라 「어떻게 진행해주길 바라는가」까지 인계하면,
별도의 세션인 AI에서도 일관된 방식으로 진행할 수 있습니다. 이는 다른 프로젝트에서도 사용할 수 있을 것 같습니다.
보안 측면의 지시를 명문화해 둔 것도 좋았습니다.
실제로 액세스 키는 단 한 번도 채팅에 붙여넣지 않고 넘어갈 수 있었습니다.
sam deploy --guided를 통해 대화형 입력을 진행하던 중, 스케줄을
「평일 09:00 JST」로 변경했을 때 깨달았습니다.
cron(0 0 ? * MON-FRI *)
AWS의 cron 식은 cron(분 시 일 월 요일 년)의 6개 필드입니다.
요일을 지정하는 경우, 일(Day) 칸은 ?로 설정해야 합니다 (*를 사용하면 거부됩니다).
이 부분은 은근히 빠지기 쉬운 함정(ハマりポイント)입니다.
그리고 변경 세트(Change Set)의 프리뷰가 나온 화면이 이것입니다.
Operation LogicalResourceId ResourceType
+ Add NotifierFunctionDailySchedulePermission AWS::Lambda::Permission
+ Add NotifierFunctionDailySchedule AWS::Events::Rule
...
이 [y/N]을 눈앞에 두고 깨달았습니다.
평일에만 실행하면, 월요일 실행 시 토/일요일 분량의 CVE가 누락되지 않을까?
조사해 보니 예상대로였습니다. 지난 실행으로부터 경과 시간이 1일을 초과한 경우, 취득 범위를 「최근 1일분」으로 맞추는(rounding) 구현이 되어 있었습니다. 월요일 아침은 금요일로부터 3일이 지났는데도 1일치만 거슬러 올라갑니다.
일단 N으로 멈추고, Claude Code로 돌아가 수정, 테스트, push를 진행했습니다.
그 후 sam build && sam deploy로 재배포했습니다.
Confirm changeset before deploy를 y로 설정해 두길 정말 잘했습니다.
실제 리소스가 생성되기 전에 한 템포 쉬어가는 메커니즘은 초보자일수록 유효하다고 생각합니다.
배포 성공 후, 수동으로 실행해 보니 다음과 같이 되었습니다.
$ aws lambda invoke --function-name rhel-cve-notifier /dev/stdout
aws: [ERROR]: Read timeout on endpoint URL: "https://lambda.ap-northeast-1.amazonaws.com/..."
CLI 측의 타임아웃인지, Lambda 자체가 실패한 것인지 알 수 없습니다.
여기서 CloudWatch Logs를 확인합니다.
$ aws logs tail /aws/lambda/rhel-cve-notifier --since 10m
REPORT RequestId: 28a303ac-... Duration: 120000.00 ms Billed Duration: 120857 ms
Memory Size: 256 MB Max Memory Used: 196 MB Status: timeout
Status: timeout이 3번 나타났습니다. Lambda 측에서 120초 제한에 걸린 것입니다.
( aws lambda invoke는 재시도(retry)를 수행하므로, 동일한 처리가 여러 번 실행되고 있습니다.)
메모리는 196MB / 256MB이므로 메모리 부족은 아닙니다. 순수하게 처리 시간의 문제였습니다.
원인은 두 가지가 겹쳐 있었습니다.
- 최초 실행 시에는 S3에
last_run.json이 없어 취득 범위가 평소보다 넓음 - SSM Parameter Store에 대한 질의(query)에 타임아웃 설정이 없어, 막히면 계속 대기함
두 번째가 은근히 까다로운데, 아무것도 설정하지 않으면 SSM에 대한 질의가 Lambda의 제한 시간 끝까지 지속됩니다. 로그에도 아무것도 남지 않습니다.
묵묵히 계속 기다리는 것이죠.
대응책으로는:
- boto3 측에 「연결 5초 / 응답 대기 10초 / 재시도 2회」의 상한을 명시
template.yaml
의 Timeout
을 120초 → 600초로 연장
하여 해결했습니다.
덧붙여, Lambda 실행 환경에서는 logging이 이미 AWS 측에서 일부 설정되어 있기 때문에, Python의 표준적인 로그 초기화가 그대로는 적용되지 않는다는 문제도 발견되어 그 부분도 수정했습니다.
"로컬에서는 동작했는데 Lambda에서 로그가 나오지 않는다"는 바로 이것이 원인인 경우가 있는 듯합니다.
참고 삼아, 처음부터 동작하기까지의 흐름도 남겨둡니다.
루트 계정(가입 시 사용한 이메일 + 비밀번호)을 CLI 조작에 그대로 사용하는 것은 피하는 것이 정석이라고 배웠습니다. CLI 전용 IAM 사용자(IAM User)를 만듭니다.
- 콘솔 검색창에서 「IAM」 → 왼쪽 메뉴 「사용자(Users)」 → 「사용자 생성(Create user)"
- 콘솔 액세스는 부여하지 않음 (CLI 전용이므로 불필요)
- 정책(Policy)은
AdministratorAccess를 직접 어태치(Attach) - 「보안 자격 증명(Security credentials)」 탭 → 액세스 키(Access Key) 생성 (용도: CLI)
AdministratorAccess는 매우 강력한 권한이지만, Lambda, S3, IAM, EventBridge를 한꺼번에 만드는 배포 작업에서는 권한을 너무 제한하면 권한 부족 에러로 인해 어려움을 겪게 됩니다.
우선 통과시킨 후 제한한다는 방침으로 정했습니다 (제한하는 것은 향후 과제).
액세스 키는 생성 화면에서만 표시되므로, 패스워드 매니저(Password Manager)에 보관합니다.
이것은 정신 건강 측면에서 상당히 컸습니다.
Billing and Cost Management → Budgets → 「제로 지출 예산(Zero spend budget)」을 생성하여 이메일 알림 대상을 설정했습니다. 1엔이라도 과금이 발생하면 알림이 옵니다.
이메일을 잘 확인하지 않아서 Discord로 보내고 싶었지만, AWS 공식 Chatbot 연동은 Slack과 Chime만 지원하며 Discord는 지원하지 않았습니다. 직접 구현하려면 SNS → Lambda → Discord Webhook 구성으로 만들어야 하므로 이번에는 보류했습니다.
$ aws --version
aws-cli/2.36.8 Python/3.14.6 Linux/...
$ sam --version
...
AWS CLI는 설치되어 있었지만 SAM CLI는 없어서 도입했습니다.
$ curl -Lo aws-sam-cli.zip https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
$ unzip aws-sam-cli.zip -d sam-installation
$ sudo ./sam-installation/install
인증 설정 및 확인.
$ aws configure
# region: ap-northeast-1 / output: json
$ aws sts get-caller-identity
...
$ aws ssm put-parameter \
--name /rhel-cve-notifier/discord-webhook-url \
--type SecureString \
...
$ aws ssm get-parameters-by-path --path "/rhel-cve-notifier/" --query "Parameters[].Name"
[
"/rhel-cve-notifier/deepl-api-key",
...
put-parameter는 값이 커맨드라인에 남기 때문에, 셸 히스토리(Shell history) 취급에 주의가 필요합니다.
$ sam build
Build Succeeded
$ sam deploy --guided
.samignore에서 .venv/, .env, data/, logs/를 제외하고 있으므로, 시크릿(Secret)이 빌드 결과물에 번들(Bundle)되지 않도록 되어 있습니다. 이 부분이 중요합니다.
대화형 입력에서 특히 고민했던 부분:
| 항목 | 선택 | 이유 |
|---|---|---|
| 배포 전 변경 사항 확인 (Confirm changes before deploy) | y | 실제 리소스 생성 전에 내용을 확인할 수 있음. 첫 실행 시 필수 |
| 롤백 비활성화 (Disable rollback) | N | 실패 시 어중간한 리소스가 남으면 뒷정리가 번거로움 |
| 구성 파일에 인자 저장 (Save arguments to configuration file) | Y | samconfig.toml에 저장되어, 2회차부터는 sam deploy만으로 충분함 |
$ aws lambda invoke --function-name rhel-cve-notifier /dev/stdout
$ aws logs tail /aws/lambda/rhel-cve-notifier --follow
Discord로 알림이 도착하고, 다음 영업일의 자동 실행도 확인하며 완료.
"전부 다 해줘"라는 식으로 진행했다면, 아마 주말을 놓치는 버그는 알아차리지 못했을 것이다.
Deploy this changeset? [y/N]
화면을 자신의 눈으로 직접 보고,
"어라, 평일만 설정해두면 월요일은 어떻게 되지?"라고 의구심을 품은 것은 인간 쪽이었다.
AI는 지시된 범위 내에서는 완벽하게 수행하지만, 사양의 전제 자체를 의심하는 것은 그 업무를 알고 있는 인간 쪽이 더 빠른 상황이 있다.
나의 경우, 취약점 정보를 추적하는 운영 감각이 있었기에 알아차릴 수 있었다고 생각한다.
그렇다고는 해도, AWS 미경험 상태에서 실제로 동작하는 Lambda까지 실질적으로 1일 만에 도달할 수 있었다.
이것은 공식 문서(Official Documentation)를 처음부터 읽었다면 절대 불가능한 일이다.
모르는 단어가 나올 때마다 "IAM이 뭐야?"라고 물을 수 있고, 그 자리에서 한 줄로 답변이 돌아온다.
이 검색을 위한 왕복 시간이 사라지는 효과가 체감상 가장 컸다.
서로 다른 AI 도구 간, 혹은 동일한 도구의 다른 세션(Session) 간에 작업을 넘길 때,
- 무엇을 만들었는가
- 왜 그런 설계로 했는가 (제약 사항, 기각한 선택지와 그 이유)
- 어떻게 진행해주길 원하는가
를 파일 하나에 정리해 두는 것. 이것은 팀 내에서 인간에게 인수인계할 때와 거의 동일하며,
AI를 상대로 하더라도 잘 작성된 인수인계서는 좋은 인수인계서였다.
특히 "왜 Secrets Manager를 사용하지 않는가"와 같은 기각한 선택지의 이유를 적어두면, 다른 세션의 AI가 선의로 다시 제안하는 것을 방지할 수 있다.
온프레미스(On-premise) 분야의 사람이 클라우드를 접할 때, 가장 큰 장벽은 기술 그 자체보다
"모르는 사이에 과금되는 것이 무섭다", "실수하면 되돌릴 수 없는 것이 무섭다"라는 심리적인 면이라고 생각한다.
그 부분을 한 단계씩 해결하며 나아갈 수 있었던 것이 이번에 가장 좋았던 점이었다.
다음은 AdministratorAccess를 좁혀 나가는 작업부터 할 예정이다.
라고, 지금까지의 기사는 모두 Claude로 작성했습니다.
작업하며 느낀 점은, Claude Desktop도 사용했지만 Claude Code만으로 AWS 조작까지 모두 가능하다는 것. 이번에 처음으로 Pro 계약을 하고 사용해 보았는데, AI의 놀라움을 절감했습니다.
끝
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기