AWS CLI와 SDK 셋업
aws cli v2 설치와 aws configure, 프로파일과 자격 증명 파일, boto3 / aws-sdk-js 같은 SDK의 용도, 그리고 자격 증명 체인이 흐르는 순서까지 — 콘솔 밖에서 AWS와 일하는 셋업을 정리합니다.
2장 IAM에서 만든 사용자의 액세스 키, 그리고 3장 비용 관리에서 켠 결제 알림이 준비됐습니다. 이제 콘솔 밖에서 AWS와 일할 차례입니다.
콘솔은 학습이나 일회성 작업에 좋지만 반복 / 자동화 / 정밀한 작업에는 한계가 옵니다. 그때 두 가지가 등장합니다. 하나는 AWS CLI로, 터미널에서 aws s3 cp ... 같은 명령으로 AWS를 부리는 도구입니다. 다른 하나는 SDK로, 코드 안에서 AWS를 부르는 라이브러리(Python의 boto3, JS의 aws-sdk 등)입니다.
본 챕터는 그 둘의 셋업과, 그 뒤에서 자격이 흐르는 순서(credential chain)를 정리합니다. 여기서 잡는 자격 증명 체인은 5장 CloudShell과 SSO의 SSO 로그인까지 그대로 이어집니다.
AWS CLI v2 설치 #
CLI는 v1과 v2가 있습니다. v2가 표준입니다. v1은 더 이상 쓰지 않습니다. v2의 차이는 다음과 같습니다.
- 단일 실행 파일(Python 환경 의존 없음)
- IAM Identity Center (SSO) 네이티브 지원(5장 CloudShell과 SSO)
- 더 빠른 출력과 더 풍부한 자동완성
aws configure import같은 새 명령
macOS #
brew install awscli또는 공식 pkg로 설치합니다.
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /Linux #
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/installWindows #
winget 또는 MSI 인스톨러를 씁니다.
winget install -e --id Amazon.AWSCLI설치 확인 #
aws --version
# aws-cli/2.x.x Python/3.x.x ...2.x.x가 안 보이면 which aws로 v1 잔재를 확인한 뒤 제거합니다.
aws configure — 자격 등록 #
CLI가 설치되었으면 2장 IAM의 사용자 액세스 키를 등록합니다.
aws configure
# AWS Access Key ID [None]: AKIA...
# AWS Secret Access Key [None]: wJal...
# Default region name [None]: ap-northeast-2
# Default output format [None]: json이 네 값이 두 파일에 나뉘어 저장됩니다.
~/.aws/credentials # 키 (민감)
~/.aws/config # region / output / role / 등~/.aws/credentials의 모양
#
[default]
aws_access_key_id = AKIA...
aws_secret_access_key = wJal...~/.aws/config의 모양
#
[default]
region = ap-northeast-2
output = json프로파일 — 여러 자격을 동시에 #
여러 계정 / 환경 / 역할을 다루면 default 하나로는 부족합니다. 프로파일로 여러 자격을 분리합니다.
프로파일 추가 #
aws configure --profile dev
aws configure --profile prod[default]
aws_access_key_id = AKIA...
[dev]
aws_access_key_id = AKIA-DEV-...
aws_secret_access_key = ...
[prod]
aws_access_key_id = AKIA-PROD-...
aws_secret_access_key = ...프로파일 사용 #
세 가지 방법이 있습니다.
aws s3 ls --profile prodexport AWS_PROFILE=prod
aws s3 lsfunction awsenv() {
export AWS_PROFILE=$1
echo "AWS_PROFILE=$AWS_PROFILE"
}
# 사용: awsenv prod운영에서는 환경 변수와 함께 셸 프롬프트에 현재 프로파일을 표시하는 패턴이 흔합니다.
셸 프롬프트에 현재 프로파일 표시 #
AWS_PROFILE을 프롬프트에 띄우면 사고가 줍니다.
PROMPT='%n@%m %1~ ${AWS_PROFILE:+[aws:$AWS_PROFILE]} %# '운영용 터미널 색을 다르게 하는 패턴도 흔합니다. prod 프로파일일 때 빨간색, dev 일 때 초록처럼 두는 식입니다.
Role 사용 — assume-role 흐름 #
2장 IAM에서 다룬 역할(Role)을 CLI에서 빌리는 흐름입니다. 멀티 어카운트 셋업의 표준 패턴입니다.
[profile prod]
role_arn = arn:aws:iam::222222222222:role/AdminRole
source_profile = default
mfa_serial = arn:aws:iam::111111111111:mfa/curtis
region = ap-northeast-2이 프로파일을 쓰면 다음 순서로 작동합니다.
default프로파일의 자격으로 STS AssumeRole을 호출합니다.- MFA 코드를 묻습니다(
mfa_serial이 있으면). - 임시 자격을 받아 명령에 사용합니다.
- 1시간 동안 캐시해 재사용합니다.
aws s3 ls --profile prod
# Enter MFA code for arn:aws:iam::111111111111:mfa/curtis: 123456
# (이후 1 시간 캐시)CI 환경에서는 5장 CloudShell과 SSO의 IAM Identity Center (SSO)가 더 매끈합니다.
환경 변수 — CI와 컨테이너의 자격 #
~/.aws/credentials가 없는 환경(CI, 컨테이너, 임시 셸)에서는 환경 변수를 씁니다.
| 변수 | 무엇 |
|---|---|
AWS_ACCESS_KEY_ID | 액세스 키 |
AWS_SECRET_ACCESS_KEY | 비밀 키 |
AWS_SESSION_TOKEN | 임시 자격일 때 함께 (STS / SSO) |
AWS_REGION 또는 AWS_DEFAULT_REGION | 리전 |
AWS_PROFILE | 프로파일 이름 |
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=ap-northeast-2
aws s3 ls자격 증명 체인 — 어디서 자격을 찾는가 #
CLI와 SDK가 자격을 찾는 순서가 정해져 있습니다. 이걸 모르면 “왜 이 키로 도는 거지?” 디버깅에 시간을 버립니다.
1. 명령행 옵션 (--profile, --region 등)
2. 환경 변수 (AWS_ACCESS_KEY_ID 등)
3. 어시스턴트 파일 (CLI Web Identity Token, Container Credentials)
4. ~/.aws/credentials의 default 또는 지정 프로파일
5. ~/.aws/config의 프로파일 (role_arn, sso_session 등)
6. EC2 / ECS / Lambda의 인스턴스 / 컨테이너 자격EC2 안에서 aws s3 ls가 자격 없이 작동하는 이유는 6단계의 인스턴스 메타데이터가 잡아 주기 때문입니다(2장 IAM의 인스턴스 프로파일).
어떤 자격이 쓰이는지 확인 #
aws sts get-caller-identity
# {
# "UserId": "AIDA...",
# "Account": "111111111111",
# "Arn": "arn:aws:iam::111111111111:user/curtis"
# }이 한 줄이 디버깅의 첫 단계입니다. 어느 사용자 / 어느 계정으로 도는지가 나옵니다.
자주 쓰는 CLI 명령 #
출력 포맷 #
aws ec2 describe-instances --output json # 기본
aws ec2 describe-instances --output table # 사람용
aws ec2 describe-instances --output text # grep / awk 용
aws ec2 describe-instances --output yaml # YAML–query — JMESPath로 골라내기 #
JSON 출력이 길어서 grep으로는 한계가 옵니다. --query로 필요한 부분만 골라냅니다.
aws ec2 describe-instances \
--query 'Reservations[].Instances[?State.Name==`running`].[InstanceId,InstanceType]' \
--output tableJMESPath 문법은 처음에는 어렵지만 자주 쓰는 패턴 5~10개만 외우면 일상 작업이 빨라집니다.
| 패턴 | 의미 |
|---|---|
[] | 배열 평탄화 |
[?key==\value`]` | 필터 |
[].field | 필드 꺼내기 |
[].[a,b,c] | 여러 필드를 새 배열로 |
length(@) | 길이 |
sort_by(@, &date) | 정렬 |
자주 쓰는 명령들 #
aws sts get-caller-identity
aws configure list
aws configure list-profilesaws s3 ls # 모든 버킷
aws s3 ls s3://my-bucket/ # 버킷 안
aws s3 cp file.txt s3://my-bucket/ # 업로드
aws s3 sync ./local s3://my-bucket/ # 폴더 동기화
aws s3 rm s3://my-bucket/file.txt # 삭제
aws s3 presign s3://my-bucket/file.pdf --expires-in 3600aws ec2 describe-instances
aws ec2 start-instances --instance-ids i-...
aws ec2 stop-instances --instance-ids i-...
aws ec2 describe-regions --query 'Regions[].RegionName'aws iam list-users
aws iam get-user --user-name curtis
aws iam list-attached-user-policies --user-name curtis
aws iam create-access-key --user-name curtisSDK — 코드 안의 AWS #
CLI가 터미널이라면 SDK는 코드입니다. 같은 자격 체인을 공유합니다.
Python — boto3 #
pip install boto3import boto3
s3 = boto3.client("s3")
res = s3.list_buckets()
for b in res["Buckets"]:
print(b["Name"])자격은 자동으로 자격 체인에서 찾습니다 — ~/.aws/credentials, 환경 변수, EC2 인스턴스 프로파일 등입니다.
명시적 프로파일 / 리전 #
session = boto3.Session(profile_name="prod", region_name="ap-northeast-2")
s3 = session.client("s3")리소스 vs 클라이언트 #
boto3에는 두 인터페이스가 있습니다.
s3 = boto3.client("s3")
res = s3.list_objects_v2(Bucket="my-bucket")
for obj in res.get("Contents", []):
print(obj["Key"])s3 = boto3.resource("s3")
for obj in s3.Bucket("my-bucket").objects.all():
print(obj.key)현대 boto3는 client를 권장합니다. resource는 일부 서비스만 지원하고, 새로운 서비스는 더 이상 추가되지 않습니다.
Pagination — 자주 만나는 함정 #
list_objects_v2는 한 번에 최대 1000 개입니다. 그 이상은 paginator로 받습니다.
s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")
for page in paginator.paginate(Bucket="my-bucket"):
for obj in page.get("Contents", []):
print(obj["Key"])JavaScript / TypeScript — aws-sdk v3 #
v2는 deprecated입니다. v3로 갑니다.
npm install @aws-sdk/client-s3import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
const client = new S3Client({ region: "ap-northeast-2" });
const res = await client.send(new ListBucketsCommand({}));
for (const b of res.Buckets ?? []) {
console.log(b.Name);
}v3의 특징은 다음과 같습니다.
- 모듈식 — 필요한 서비스만 import (번들 크기 감소)
- 트리 셰이킹 친화
- 모든 호출이
client.send(new XxxCommand(...))패턴
Go — aws-sdk-go-v2 #
go get github.com/aws/aws-sdk-go-v2/aws
go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/service/s3package main
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
func main() {
ctx := context.Background()
cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("ap-northeast-2"))
if err != nil {
panic(err)
}
client := s3.NewFromConfig(cfg)
res, err := client.ListBuckets(ctx, &s3.ListBucketsInput{})
if err != nil {
panic(err)
}
for _, b := range res.Buckets {
fmt.Println(*b.Name)
}
}Go 트랙의 컨벤션대로 context 우선과 명시적 에러를 따릅니다.
자동완성 켜기 #
탭 자동완성을 켜면 CLI가 훨씬 부드러워집니다.
autoload bashcompinit && bashcompinit
autoload -Uz compinit && compinit
complete -C "$(which aws_completer)" awscomplete -C "$(which aws_completer)" aws.zshrc나 .bashrc에 넣고 새 셸을 엽니다. 이제 aws s3 <TAB> 하면 명령과 옵션이 보입니다.
자주 만나는 함정 #
~/.aws/credentials를 git에 커밋 — 가장 위험한 사고입니다. 반드시.gitignore에.aws/또는 글로벌 gitignore에 넣습니다. 그리고 액세스 키는 가능한 한 환경 변수 / SSO로 두고 파일에 두지 않는 것이 점점 표준입니다.- 잘못된 프로파일에서 운영 명령 —
AWS_PROFILE=dev로 일하다가 명령에--profile prod가 따로 적혀 있어 prod 버킷이 보이는 경우가 있습니다. 출처를 명시하고aws sts get-caller-identity로 먼저 점검하는 것이 답입니다. - 자격 체인 디버깅 — “환경 변수에 키를 넣었는데 옛날 키로 도네” 라면 자격 체인 1 단계(명령행
--profile)가 우선이거나, 셸이 export를 못 받았을 가능성입니다.aws sts get-caller-identity로 먼저 진단합니다. - v1 잔재 —
aws --version이 1.x 라면(특히 macOS / Linux의pip install awscli흔적) v1 잔재입니다. v1과 v2가 동시에 PATH에 있으면 의도하지 않은 v1이 실행되니,which aws로 확인하고 제거합니다. - 페이지네이션 누락 —
list_*API는 거의 모두 페이지네이션이 있습니다. 첫 페이지만 처리하고 끝내면 1000번째 이후 데이터가 누락됩니다.paginator또는NextToken루프를 씁니다. - SDK의 자격을 코드에 넣기 — 아래처럼 코드에 키를 넣으면 git으로 노출되어 사고로 이어집니다.
boto3.client("s3", aws_access_key_id="AKIA...", aws_secret_access_key="...")자격은 환경 / 프로파일 / 인스턴스 프로파일에서 받습니다.
연습문제 #
- §“자격 증명 체인"의 여섯 단계를 보지 않고 순서대로 적어 보세요. 그런 다음, EC2 안에서
aws s3 ls가 키 없이 작동하는 이유가 몇 번째 단계인지 2장 IAM의 인스턴스 프로파일과 연결해 설명해 보세요. - §“Role 사용 — assume-role 흐름"의
role_arn+source_profile+mfa_serial프로파일이 2장 IAM의 Trust Policy와 Permission Policy 중 어느 흐름을 재현하는지 한 단락으로 설명해 보세요. aws ec2 describe-instances의 출력에서 실행 중인 인스턴스의 ID와 타입만 뽑는--query표현을 §”–query"의 표를 참고해 직접 작성해 보세요.
한 줄 요약: AWS CLI v2와 SDK는 같은 자격 증명 체인을 공유하며, 자격은 명령행 → 환경 변수 → 파일 → 인스턴스 프로파일 순으로 찾는다.
aws configure는 자격을~/.aws/credentials와~/.aws/config두 파일에 나눠 저장하고, 프로파일로 여러 계정을 분리한다. 키를 코드나 git에 넣지 않고aws sts get-caller-identity로 먼저 신원을 확인하는 것이 디버깅과 사고 예방의 기본이다.
다음 챕터 #
로컬 셋업이 끝났습니다. 그런데 다른 사람의 노트북이나 회사 임시 환경에서도 같은 CLI가 필요할 때가 있고, 멀티 어카운트가 시작되면 로그인 자체가 더 정교해져야 합니다. 다음 5장 CloudShell과 SSO에서는 콘솔 안의 브라우저 터미널 CloudShell과, 멀티 어카운트의 표준 로그인이 된 IAM Identity Center (SSO) 셋업을 정리합니다.