Cursor AI를 활용한 Macie 대체 서비스 개발기
작성자 - S1ON개요
AI가 보안. IT를 넘어 모든 분야의 시장을 씹어먹고 있다.
며칠 전엔 생성형 AI인 DeepSeek가 ChatGPT에 도전을 했고. 세계 증시가 850조 이상 출렁거릴 정도로 폭풍을 몰고왔다.
이는 나의 일자리도 언제나 새로운 변화에 신속대응하는 후발주자에게 충분히 도전받을 수 있음을 시사한다.
그래도 이대로 죽을 순 없기 때문에 난 AI 기술을 적극 활용하고 시대의 흐름에 편승할 수 있는 방법을 찾아야만 한다.
그 해답은 바로 값비싼 클라우드 보안 네이티브 서비스인 Macie를 생성형 AI를 이용해 자체 개발해보는 것..!
"지금 가장 인기있는 프로그래밍 언어는 영어다" - 테슬라 AI Lead 카파시 - |
Cursor AI 편집기
Cursor AI는 Visual Studio(VS Code)를 기반으로 만들어진 AI 코드 편집기로,
필자와 같은 딸피 까막눈도 코딩을 할 수 있게 도와주는 아주 효자같은 프로그램이다.
주요 특징은 다음과 같다
- AI 기반 코드 제안 및 자동 완성 (TAB)

- 자연어로 코드 생성 가능 (Ctrl + K)

- 실시간 오류 감지 및 수정 제안
- 다양한 프로그래밍 언어 지원
- 직관적인 사용자 인터페이스
나는 여러 기능 중에서도 특히 코드 구조나 변수를 인지하여 자동완성 코드를 제안하는 기능, Chat으로 작성한 기능 요구사항이나 디버깅 내용에 대한 답변을 실제 소스코드 파일에 바로 적용(Apply)하는 기능, 제안코드를 반영하기 전 기존 코드와 비교(Diff)하는 기능이 아주 마음에 쏙 들었다.
본인의 경험 상 위 기능이 메인이며, 나머지 기능 테스트는 메인디쉬가 아니기 때문에 자세한 기능 설명은 공식 홈페이지(https://www.cursor.com/)를 참고할 것을 추천하고, 무료 체험판 모드(2주)를 사용해보면 충분할 것으로 생각된다.
AWS Macie란?
Macie는 패턴 매칭을 기반으로 S3 버킷에 대한 민감 데이터를 검색하고 보호하는 데이터 보안 및 개인정보보호 서비스이다.

아주 그럴싸한 녀석이지만 피지컬 대비 상당히 비싼 몸값을 자랑하기 때문에 검사대상인 S3 버킷의 크기에 따라 다르겠지만 경우에 따라서는 AWS 보안 서비스 중 가장 비용부담이 클 수도 있다.
아래는 조직에서 월 1회, 1TB 사이즈의 1000개 파일을 보유하고 있는 S3버킷 대상 민감정보 정기스캔 예상 견적이다.
서비스 | 월간 비용 | 장점 | 단점 |
AWS Macie | 약 $1,500 (S3 분석 비용-용량기반) |
- 고급 데이터 분석, 민감 정보 자동 감지 - 보안 자동화 - 쉬운 관리 |
- 매우 높은 비용 - 대규모 데이터 분석에 비효율적일 수 있음 |
EC2 + Bash | 약 $90.21 (EC2 인스턴스 운영 비용) (S3 다운로드 비용) |
- 유연성 높음 - 데이터를 직접 처리 가능 - 커스터마이징 가능 |
- 스크립트 관리 필요 - S3 다운로드 비용 발생 - EC2 관리 필요 |
AWS Lambda | 약 $0.20 (Lambda 요청 비용) (Lambda 실행시간 비용) (S3 Get 요청 비용) |
- 비용 효율적 - 서버리스 방식으로 관리 용이 - 이벤트 기반 자동화 |
- 실행 시간 및 메모리 제한 있음 - 대규모 데이터 처리 시 한계 가능 |
기존에 Macie를 사용하고 있다면 Lambda로 전환해서 보안과 비용절감 두마리 토끼를 잡아 사장님께 예쁨을 받아보자.
Cursor AI로 Macie 만들어보기
생성형 AI는 개똥같이 말해도 찰떡같이 알아듣는 능력자지만,
내가 바라는 찰떡과 최대한 근접하게 질문을 해준다면 한 큐에 의도한 바를 얻을 수 있다.
나는 특정 S3 버킷에 대한 개인정보 검출을 수행할 수 있는 Lambda 함수를 만들고자 한다.
※ 아래 질문은 내가 10번 정도 반복을 거듭한 뒤에야 얻을 수 있었던 한방짜리 질문이다.
[Chat] aws macie와 유사한 기능을 하는 lambda 함수를 만들고 싶어 test1-s3-demo-bucket 이라는 s3 버킷에 있는 모든 파일을 검색하고 개인정보를 확인할거야 개인정보는 주민등록번호, 여권번호, 핸드폰번호, 이메일주소 네가지로 정의해줘 결과는 한글 인코딩 적용한 csv로 출력하고, 필드명 구성은 아래와 같이 해줘 - 버킷명 - 경로 - 파일명 - 검출유형 - 검출 값 - 라인번호 - 시작위치 - 종료위치 - 검출시간
import boto3
import re
import csv
import io
from datetime import datetime
import codecs
from typing import List, Dict, Any
# 개인정보 패턴 정의
PATTERNS = {
'주민등록번호': r'\d{6}[-]\d{7}',
'여권번호': r'[A-Z]{1}[0-9]{8}|[M]{1}[0-9]{8}',
'핸드폰번호': r'01[016789][-]\d{3,4}[-]\d{4}|01[016789]\d{3,4}\d{4}',
'이메일주소': r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
}
def find_pii(content: str, pattern: str, pattern_name: str) -> List[Dict[Any, Any]]:
findings = []
for match in re.finditer(pattern, content):
findings.append({
'검출유형': pattern_name,
'검출값': match.group(),
'시작위치': match.start(),
'종료위치': match.end()
})
return findings
def process_file(bucket: str, key: str) -> List[Dict[Any, Any]]:
s3_client = boto3.client('s3')
try:
response = s3_client.get_object(Bucket=bucket, Key=key)
content = response['Body'].read().decode('utf-8')
results = []
for line_num, line in enumerate(content.splitlines(), 1):
for pattern_name, pattern in PATTERNS.items():
findings = find_pii(line, pattern, pattern_name)
for finding in findings:
results.append({
'버킷명': bucket,
'경로': '/'.join(key.split('/')[:-1]),
'파일명': key.split('/')[-1],
'검출유형': finding['검출유형'],
'검출값': finding['검출값'],
'라인번호': line_num,
'시작위치': finding['시작위치'],
'종료위치': finding['종료위치'],
'검출시간': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
})
return results
except Exception as e:
print(f"파일 처리 중 오류 발생: {str(e)}")
return []
def lambda_handler(event, context):
s3_client = boto3.client('s3')
bucket_name = 'test1-s3-demo-bucket'
try:
# S3 버킷의 모든 객체 나열
paginator = s3_client.get_paginator('list_objects_v2')
all_findings = []
for page in paginator.paginate(Bucket=bucket_name):
if 'Contents' in page:
for obj in page['Contents']:
findings = process_file(bucket_name, obj['Key'])
all_findings.extend(findings)
# CSV 파일 생성
if all_findings:
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=[
'버킷명', '경로', '파일명', '검출유형', '검출값',
'라인번호', '시작위치', '종료위치', '검출시간'
])
writer.writeheader()
for finding in all_findings:
writer.writerow(finding)
# BOM 추가하여 한글 인코딩 처리
csv_data = '\ufeff' + output.getvalue()
# 결과 파일 업로드
result_key = f'scan_results/pii_scan_result_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'
s3_client.put_object(
Bucket=bucket_name,
Key=result_key,
Body=csv_data.encode('utf-8'),
ContentType='text/csv;charset=utf-8'
)
return {
'statusCode': 200,
'body': f'검사 완료. 결과 파일: {result_key}'
}
return {
'statusCode': 200,
'body': '검사 완료. 개인정보가 발견되지 않았습니다.'
}
except Exception as e:
return {
'statusCode': 500,
'body': f'오류 발생: {str(e)}'
}

위 내용으로 Lambda 함수를 일단 만들어보자.

S3 버킷을 조회하고, 다운로드하고, 결과파일을 업로드할 수 있도록 권한을 추가해야한다. 자세한건 Cursor한테 물어보자.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListObjectsV2"
],
"Resource": "arn:aws:s3:::test1-s3-demo-bucket"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::test1-s3-demo-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
Lambda 함수에 부여된 역할에 설정된 정책을 확인해서 위 json 정책을 넣어주자.

권한이 부여된 Lambda 함수를 실행 해보니 아래와 같이 개인정보가 없다고 나온다. 샘플 데이터 만드는걸 깜빡했다.

Cursor 한테 샘플파일 4개만 요청해보자. 각 생성 데이터 별로 Apply를 누르면 실제 프로젝트 경로에 파일이 생성된다.

S3 버킷에 개인정보 샘플파일을 업로드하자.

다시 돌아가서 Lambda 함수를 실행해보니 이제는 검사가 완료되어 결과파일이 동일 S3 버킷으로 업로드 된 것 같다.

S3 버킷으로 돌아가서 생성된 csv 결과 파일을 열어보자.

신문기사를 참고해서 더미데이터를 넣었더니 의도했던 정탐 외 오탐도 확인이 된다.
아마 구분자(공백, 특수문자)를 식별하는 패턴이 없어 문자열의 일부 패턴만 일치한다면 민감정보로 검출해낸 것 같다.
실제 Macie를 대체하기엔 아직 아쉽지만 조금만 손보면 아주 저렴하고 좋은 놈을 만들 수 있을 것 같다.
결론
생성형 AI는 이미 모든 분야에서 높은 수준의 활용도를 보이고 있다. 보안영역도 많은 부분에서 AI로 대체될 것 같다.
오늘 Macie 서비스를 10분만에 흉내낼 수 있었던 것처럼 나는 Why와 What을 고민하는데 시간을 좀 더 쓰고,
How는 나보다 훨씬 똑똑한 AI가 수행하도록 한다면 이 불경기에서 구조조정 위기 없이 좀 더 길게 갈 수 있지 않을까 싶다.