23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
Backend 개발은 서비스의 성능과 안정성을 결정하는 중요한 요소입니다.
최근 인공지능 기술이 발전하면서 개발자의 생산성을 획기적으로 높일 수 있는 도구가 많이 등장하고 있는데요,
그 중에서도 Cursor AI를 활용한 효율적인 Backend-API 개발 방법을 소개하겠습니다.
Cursor AI는 개발자의 생산성을 높여주는 AI 기반의 코드 작성 도구입니다.
Claude, GPT, Gemini 등 다양한 모델을 기반으로 하며, 코드 생성, 디버깅, 코드 최적화 등의 기능을 제공하여 반복적이고 지루한 개발 업무를 크게 줄여줍니다.
AWS EC2의 리스트를 수집하고, CloudWatch 메트릭으로 성능 데이터를 호출하는 API를 작성하도록 합니다.
Fast API를 기반으로 Open API를 지원하는 프로젝트를 구성합니다.
Cursor AI의 채팅창에 다음과 같이 입력합니다.
Fast API를 사용하여 Open API 형태의 Backend API를 생성해주세요. AWS EC2의 리스트 가져오고, 개별 VM의 상세 정보를 가져오는 API가 필요합니다.main.py
from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import boto3
from botocore.exceptions import ClientError, NoCredentialsError
import os
from datetime import datetime
app = FastAPI(
title="AWS EC2 Management API",
description="AWS EC2 인스턴스를 관리하는 REST API",
version="1.0.0"
)
# CORS 미들웨어 추가
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Pydantic 모델 정의
class EC2Instance(BaseModel):
instance_id: str
instance_type: str
state: str
public_ip: Optional[str] = None
private_ip: Optional[str] = None
launch_time: Optional[datetime] = None
tags: Optional[dict] = None
class EC2InstanceDetail(BaseModel):
instance_id: str
instance_type: str
state: str
public_ip: Optional[str] = None
private_ip: Optional[str] = None
launch_time: Optional[datetime] = None
tags: Optional[dict] = None
vpc_id: Optional[str] = None
subnet_id: Optional[str] = None
availability_zone: Optional[str] = None
security_groups: Optional[List[str]] = None
key_name: Optional[str] = None
platform: Optional[str] = None
architecture: Optional[str] = None
root_device_name: Optional[str] = None
root_device_type: Optional[str] = None
class ErrorResponse(BaseModel):
error: str
message: str
def get_ec2_client():
"""EC2 클라이언트를 생성하고 반환합니다."""
try:
# AWS 자격 증명은 환경 변수나 AWS CLI 설정에서 가져옵니다
ec2_client = boto3.client('ec2')
return ec2_client
except NoCredentialsError:
raise HTTPException(
status_code=500,
detail="AWS 자격 증명을 찾을 수 없습니다. AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY를 설정해주세요."
)
@app.get("/", tags=["Root"])
async def root():
"""API 루트 엔드포인트"""
return {
"message": "AWS EC2 Management API",
"version": "1.0.0",
"endpoints": {
"instances": "/api/v1/instances",
"instance_detail": "/api/v1/instances/{instance_id}"
}
}
@app.get("/api/v1/instances",
response_model=List[EC2Instance],
responses={
200: {"description": "EC2 인스턴스 목록을 성공적으로 가져왔습니다"},
500: {"model": ErrorResponse, "description": "서버 오류"}
},
tags=["EC2 Instances"])
async def get_instances(region: Optional[str] = None):
"""모든 EC2 인스턴스 목록을 가져옵니다."""
try:
ec2_client = get_ec2_client()
# 특정 리전이 지정된 경우 해당 리전의 클라이언트 사용
if region:
ec2_client = boto3.client('ec2', region_name=region)
response = ec2_client.describe_instances()
instances = []
for reservation in response['Reservations']:
for instance in reservation['Instances']:
# 태그를 딕셔너리로 변환
tags = {}
if 'Tags' in instance:
for tag in instance['Tags']:
tags[tag['Key']] = tag['Value']
instance_data = EC2Instance(
instance_id=instance['InstanceId'],
instance_type=instance['InstanceType'],
state=instance['State']['Name'],
public_ip=instance.get('PublicIpAddress'),
private_ip=instance.get('PrivateIpAddress'),
launch_time=instance.get('LaunchTime'),
tags=tags
)
instances.append(instance_data)
return instances
except ClientError as e:
error_code = e.response['Error']['Code']
error_message = e.response['Error']['Message']
raise HTTPException(
status_code=500,
detail=f"AWS API 오류: {error_code} - {error_message}"
)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"서버 오류: {str(e)}"
)
@app.get("/api/v1/instances/{instance_id}",
response_model=EC2InstanceDetail,
responses={
200: {"description": "EC2 인스턴스 상세 정보를 성공적으로 가져왔습니다"},
404: {"model": ErrorResponse, "description": "인스턴스를 찾을 수 없습니다"},
500: {"model": ErrorResponse, "description": "서버 오류"}
},
tags=["EC2 Instances"])
async def get_instance_detail(instance_id: str, region: Optional[str] = None):
"""특정 EC2 인스턴스의 상세 정보를 가져옵니다."""
try:
ec2_client = get_ec2_client()
# 특정 리전이 지정된 경우 해당 리전의 클라이언트 사용
if region:
ec2_client = boto3.client('ec2', region_name=region)
response = ec2_client.describe_instances(InstanceIds=[instance_id])
if not response['Reservations']:
raise HTTPException(
status_code=404,
detail=f"인스턴스 {instance_id}를 찾을 수 없습니다."
)
instance = response['Reservations'][0]['Instances'][0]
# 태그를 딕셔너리로 변환
tags = {}
if 'Tags' in instance:
for tag in instance['Tags']:
tags[tag['Key']] = tag['Value']
# 보안 그룹 이름 추출
security_groups = []
if 'SecurityGroups' in instance:
for sg in instance['SecurityGroups']:
security_groups.append(sg['GroupName'])
instance_detail = EC2InstanceDetail(
instance_id=instance['InstanceId'],
instance_type=instance['InstanceType'],
state=instance['State']['Name'],
public_ip=instance.get('PublicIpAddress'),
private_ip=instance.get('PrivateIpAddress'),
launch_time=instance.get('LaunchTime'),
tags=tags,
vpc_id=instance.get('VpcId'),
subnet_id=instance.get('SubnetId'),
availability_zone=instance.get('Placement', {}).get('AvailabilityZone'),
security_groups=security_groups,
key_name=instance.get('KeyName'),
platform=instance.get('Platform'),
architecture=instance.get('Architecture'),
root_device_name=instance.get('RootDeviceName'),
root_device_type=instance.get('RootDeviceType')
)
return instance_detail
except ClientError as e:
error_code = e.response['Error']['Code']
error_message = e.response['Error']['Message']
if error_code == 'InvalidInstanceID.NotFound':
raise HTTPException(
status_code=404,
detail=f"인스턴스 {instance_id}를 찾을 수 없습니다."
)
raise HTTPException(
status_code=500,
detail=f"AWS API 오류: {error_code} - {error_message}"
)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"서버 오류: {str(e)}"
)
@app.get("/api/v1/regions",
responses={
200: {"description": "사용 가능한 AWS 리전 목록을 성공적으로 가져왔습니다"},
500: {"model": ErrorResponse, "description": "서버 오류"}
},
tags=["AWS Regions"])
async def get_regions():
"""사용 가능한 AWS 리전 목록을 가져옵니다."""
try:
ec2_client = get_ec2_client()
response = ec2_client.describe_regions()
regions = []
for region in response['Regions']:
regions.append({
"region_name": region['RegionName'],
"endpoint": region['Endpoint'],
"opt_in_status": region.get('OptInStatus', 'N/A')
})
return {"regions": regions}
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"서버 오류: {str(e)}"
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000) Cursor AI가 점점 더 스마트해져서 이제 자동으로 테스트 코드도 만들고 생성합니다.
이미 Step 1에서 python test_api.py 를 통하여 정상적으로 API가 동작되는 것을 확인할 수 있습니다.
✅ 성공: 6개의 인스턴스 발견
📋 인스턴스 목록:
- i-001fec85e372503fc (r5.4xlarge) - running
- i-0f35f3b9ec3e22662 (t3.xlarge) - running
- i-0925002c592dc5124 (t3.xlarge) - running
🔍 EC2 인스턴스 상세 정보 엔드포인트 테스트...
📋 인스턴스 i-001fec85e372503fc 상세 정보 조회...
✅ 성공: 인스턴스 i-001fec85e372503fc 상세 정보
- 타입: r5.4xlarge
- 상태: running
- VPC: vpc-0e33360553007834f
- 가용영역: ap-northeast-2a
🔍 존재하지 않는 인스턴스 테스트...
❌ 실패: 예상된 404가 아닌 HTTP 500
📊 테스트 결과: 4/5 통과
⚠️ 일부 테스트가 실패했습니다.메서드 | 엔드포인트 | 설명 |
|---|---|---|
GET | / | API 정보 및 엔드포인트 목록 |
GET | /api/v1/instances | EC2 인스턴스 목록 |
GET | /api/v1/instances/{instance_id} | 특정 인스턴스 상세 정보 |
GET | /api/v1/regions | AWS 리전 목록 |
Cursor AI를 효율적으로 활용하기 위해서는 AI가 이해하기 쉬운 문장을 작성하는 것이 중요합니다.
사용자가 원하는 결과를 정확하게 전달할 수 있도록 상황과 목적을 명확히 설명하고, 불필요한 정보는 최대한 줄이는 것이 좋습니다.
이렇게 하면 보다 빠르고 정확한 결과물을 얻을 수 있습니다.
명확한 지시어 사용: Cursor AI가 원하는 결과물을 정확히 생성하도록 지시어를 명확하게 작성합니다.
작은 단위로 요청: 한 번에 너무 많은 기능을 요청하지 말고 작은 단위로 나누어 요청하면 더 정확한 결과를 얻을 수 있습니다.
반복적으로 피드백 주기: Cursor AI와의 소통을 반복하며 점차 원하는 형태로 코드를 발전시킵니다.
Cursor AI를 Backend API 개발에 활용하면 반복적인 작업을 줄이고, 더욱 중요한 비즈니스 로직에 집중할 수 있습니다.
개발 효율성을 높이고 빠른 프로토타이핑이 가능하게 해주는 Cursor AI로 여러분도 더 스마트한 Backend 개발자가 되어 보세요.
다음 연재에서는 Backend API를 활용하여 포털을 쉽게 구성하는 방법에 대해서 공유드리겠습니다.
감사합니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.