AWS 기초: Region, IAM 및 주요 서비스
1. 개요
이 글은 AWS 입문자가 꼭 알아야 할 세 가지 핵심을 빠르게 이해하도록 도와줍니다: region (인프라가 어디에 위치할지 선택), IAM (누가 무엇을 할 수 있는지), 그리고 주요 서비스 (EC2, S3, RDS, Lambda, VPC…). 이 글을 다 읽고 나면 AWS 계정을 안전하게 조직하는 방법, 애플리케이션을 위한 IAM role을 만드는 방법, 그리고 AWS SDK v2로 S3를 호출하는 Java 코드를 작성할 수 있을 것입니다.
2. Region과 Availability Zone
AWS는 인프라를 region (지역 단위, 예: 싱가포르의 ap-southeast-1)으로 나누고, 각 region은 여러 개의 Availability Zone (AZ) - 전기, 네트워크 측면에서 독립적이고 서로 가까워 지연 시간은 낮지만 장애를 격리시킬 수 있는 데이터 센터들로 구성됩니다.
aws ec2 describe-availability-zones --region ap-southeast-1
위 명령어는 싱가포르 region의 AZ들을 나열합니다. 결과는 대개 다음과 같은 형태입니다:
ZoneName: ap-southeast-1a
ZoneName: ap-southeast-1b
ZoneName: ap-southeast-1c
시스템을 설계할 때는 장애 허용성을 위해 최소 2개의 AZ에 배포해야 합니다. 예를 들어 Auto Scaling Group이나 RDS Multi-AZ 인스턴스 모두 이 원칙을 따릅니다.
주의: IAM, Route 53, CloudFront 같은 일부 서비스는 global (특정 region에 묶여있지 않음)입니다. 대부분의 다른 서비스 (EC2, S3, RDS…)는 regional이며, 별도로 설정하지 않으면 데이터가 다른 region으로 자동 복제되지 않습니다.
2.1. Region을 어떻게 선택할까요
세 가지 핵심 기준이 있습니다: 지연 시간 (사용자와 가까운), 규정 준수 (데이터 저장 위치 요구사항), 그리고 비용 (region별로 서비스 가격이 다름). 베트남 사용자의 경우 ap-southeast-1 (싱가포르)이 낮은 지연 시간과 충분한 서비스 가용성 때문에 보통 기본 선택입니다.
3. IAM: User, Group, Role, Policy
IAM (Identity and Access Management)은 누가 어떤 리소스에 접근할 수 있는지를 제어합니다. 네 가지 핵심 개념이 있습니다:
- User: 고유한 자격증명을 가진 특정 신원 (사람 또는 서비스).
- Group: user들의 모음으로, 공통 policy를 쉽게 관리하기 위해 사용됩니다.
- Role: 임시적인 권한 집합으로, 고정 자격증명이 없습니다 — EC2, Lambda, 또는 교차 계정 액세스에 사용됩니다.
- Policy: 행동과 리소스에 대한 권한(허용/거부)을 나타내는 JSON 문서입니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::order-invoices-bucket/*"
}
]
}
이 policy는 order-invoices-bucket 버킷의 객체를 읽고 쓸 수 있는 권한을 부여합니다. policy를 role에 연결한 다음 그 role을 EC2 인스턴스나 InvoiceStorageService를 실행하는 Lambda 함수에 할당하면 — 애플리케이션은 access key/secret key를 하드코딩하지 않고도 자동으로 권한을 갖게 됩니다.
aws iam create-role \
--role-name InvoiceServiceRole \
--assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy \
--role-name InvoiceServiceRole \
--policy-arn arn:aws:iam::123456789012:policy/InvoiceBucketAccess
첫 번째 명령어는 이 role을 “assume”할 수 있는 대상을 정의하는 trust-policy.json을 이용하여 role을 만듭니다 (예: EC2 서비스). 두 번째 명령어는 구체적인 권한 policy를 이 role에 연결합니다.
주의: access key/secret key를 절대로 코드에 직접 포함하거나 Git에 커밋하지 마세요. AWS에서 실행되는 리소스의 경우 IAM Role을, 사람 사용자의 경우 IAM Identity Center/SSO를 사용하세요.
3.1. 최소 권한 원칙
필요한 권한만 정확히 부여하고, 서비스 계정에 AdministratorAccess policy를 사용하지 마세요. 예를 들어 Lambda가 한 버킷만 읽으면 되면 계정 전체의 s3:*을 부여해서는 안 됩니다.
{
"Effect": "Deny",
"Action": "s3:DeleteBucket",
"Resource": "*"
}
Deny statement는 항상 Allow보다 우선합니다 — 이것은 중요한 버킷을 실수로 삭제하는 것을 방지하는 “안전 장치”입니다.
4. 주요 서비스
4.1. Compute
- EC2: 시간/초 단위로 임대하는 가상 머신으로, OS 관리는 직접 합니다.
- Lambda: 이벤트 기반으로 코드를 실행하며, 서버를 관리하지 않고 호출 수와 실행 시간으로 요금을 계산합니다.
- ECS/EKS: 오케스트레이션이 있는 컨테이너 (Docker)를 실행합니다.
aws lambda invoke \
--function-name CalculateOrderTotal \
--payload '{"orderId":"ORD-1001"}' \
response.json
이 명령어는 JSON payload와 함께 CalculateOrderTotal 함수를 호출하고, 결과를 response.json에 기록합니다.
4.2. Storage
- S3: 객체 저장소로, 모든 종류의 파일 (이미지, 로그, 백업)을 저장할 수 있으며, 가용성이 99.999999999%입니다.
- EBS: EC2에 연결되는 블록 스토리지 볼륨입니다.
- EFS: 여러 EC2가 마운트할 수 있는 공유 파일 시스템입니다.
4.3. Database
- RDS: 관리형 관계형 데이터베이스 (MySQL, PostgreSQL…)로, 자동 백업과 패칭이 있습니다.
- DynamoDB: NoSQL로, 자동으로 수평 확장되며 밀리초 단위의 지연 시간을 제공합니다.
4.4. Network
- VPC: 가상 프라이빗 네트워크로, 서브넷, 라우팅 테이블, 보안 그룹을 직접 정의합니다.
- Security Group: 인스턴스 수준의 상태 저장 방화벽입니다.
Resources:
OrderServiceSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: HTTPS 인바운드 허용
VpcId: vpc-0123456789abcdef0
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
이 CloudFormation 스니펫은 OrderServiceSG라는 보안 그룹을 만들고, 모든 IP에서 443 포트(HTTPS)만 열도록 설정합니다 — 다른 모든 인바운드 규칙은 기본적으로 거부됩니다.
5. Java 애플리케이션에서 S3 호출하기
이 섹션은 Spring Boot 서비스가 AWS SDK for Java v2를 사용하여 S3에 파일을 업로드하는 방법을 보여줍니다.
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.25.16</version>
</dependency>
public class InvoiceStorageService {
private final S3Client s3Client;
private final String bucketName;
public InvoiceStorageService(S3Client s3Client, String bucketName) {
this.s3Client = s3Client;
this.bucketName = bucketName;
}
public void uploadInvoice(String orderId, byte[] content) {
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucketName)
.key("invoices/" + orderId + ".pdf")
.build();
s3Client.putObject(request, RequestBody.fromBytes(content));
}
}
S3Client는 생성자를 통해 주입되며 (EC2/Lambda에서 실행할 때 IAM Role에서 자동으로 자격증명을 가져오므로 하드코딩할 필요 없음), uploadInvoice 메서드는 버킷의 객체 경로를 나타내는 key를 포함한 PutObjectRequest를 만든 다음 putObject를 호출하여 내용을 S3에 업로드합니다.
S3Client bean 설정:
@Bean
public S3Client s3Client() {
return S3Client.builder()
.region(Region.AP_SOUTHEAST_1)
.build();
}
credentialsProvider를 명시적으로 전달할 필요가 없습니다 — SDK는 자동으로 Default Credentials Provider Chain을 사용합니다: 환경 변수, ~/.aws/credentials 파일, 그리고 EC2/ECS/Lambda에 연결된 IAM Role 순서로 찾습니다.
5.1. Mock S3Client로 테스트하기
@Test
void shouldCallPutObjectWithCorrectKey() {
S3Client mockS3 = mock(S3Client.class);
InvoiceStorageService service = new InvoiceStorageService(mockS3, "order-invoices-bucket");
service.uploadInvoice("ORD-1001", "인보이스 내용".getBytes());
ArgumentCaptor<PutObjectRequest> captor = ArgumentCaptor.forClass(PutObjectRequest.class);
verify(mockS3).putObject(captor.capture(), any(RequestBody.class));
assertThat(captor.getValue().bucket()).isEqualTo("order-invoices-bucket");
assertThat(captor.getValue().key()).isEqualTo("invoices/ORD-1001.pdf");
}
Mock S3Client (Mockito 사용)로 테스트하면 CI 실행 중 실제 AWS를 호출하지 않습니다. ArgumentCaptor는 실제로 전송된 PutObjectRequest를 캡처하고, AssertJ는 bucket과 key가 예상대로인지 검증합니다 — 요청 구성 로직이 올바른지 네트워크 비용이나 데이터 위험 없이 확인할 수 있습니다.
주의: S3와의 실제 통합 테스트를 원한다면 실제 production 버킷을 호출하는 대신 LocalStack 또는 Testcontainers 라이브러리를 사용하세요 — 비용 발생과 데이터 위험을 피할 수 있습니다.
6. 자주 하는 실수
- S3 버킷을 실수로 공개하기: “Block Public Access”를 계정 수준에서 활성화하세요. 버킷을 정말 공개해야 할 때 (예: 정적 웹사이트)를 제외하고는요.
- 너무 넓은 policy를 role에 연결하기 (
"Action": "*", "Resource": "*"): 테스트 후 production으로 올릴 때 이를 제거하는 것을 잊으세요. - root 계정에 MFA를 활성화하지 않기: root 계정은 모든 권한을 가지므로, root 액세스를 잃는 것은 가장 심각한 위험입니다.
- 코드에 access key를 하드코딩하기: IAM Role, Secrets Manager, 또는 CI/CD secret으로 관리되는 환경 변수를 사용하세요.
- region을 잘못 선택하기: 최종 사용자의 지연 시간이 높아지거나, 데이터 저장소 규정 위반이 발생할 수 있습니다.
7. 결론
Region은 인프라 위치를 선택할 때 지연 시간, 비용, 규정 준수의 균형을 맞추도록 도와줍니다. IAM은 가장 첫 번째이자 가장 중요한 보안 계층입니다 — 항상 최소 권한 원칙을 적용하고 정적 access key보다는 Role을 우선하세요. 핵심 서비스들 (EC2, S3, RDS, Lambda, VPC)과 AWS SDK를 통한 통합 방법을 이해하는 것은 AWS에서 실제 시스템을 배포하기 위한 충분한 기초가 될 것입니다.