Role: Infra & DevOps — 인프라 아키텍처 설계∙구축, Terraform IaC, EKS 운영 환경 구성
Period: 2025.10 – 2025.12
Team: 7인
Link: [GitHub] [RCA Report]
1. 프로젝트 소개
COME2US는 트래픽 증가 상황을 가정한 MSA 기반 전자상거래 플랫폼입니다.
초기에는 단일 EC2 기반 Monolith 구조로 MVP를 빠르게 검증했고, 이후 ECS Fargate 기반 MSA로 서비스를 분리했습니다. 그러나 서비스 수가 늘어나면서 서비스 디스커버리, 공통 정책 관리, 배포 운영 방식, 인프라 재현성 측면에서 한계가 드러났습니다.
이를 해결하기 위해 최종적으로 EKS 기반 Cloud-Native 환경으로 전환했고, VPC, EKS, RDS, ElastiCache, MSK, IAM, SSM, Route53 등 주요 AWS 리소스를 Terraform으로 코드화했습니다.
COME2US는 각 단계에서 경험한 운영 한계를 바탕으로 클라우드 아키텍처를 전환하며, 네트워크 격리, 보안 경계, 데이터 계층 보호, 확장성, 비용 최적화, 운영 지표 기반 개선을 함께 고려한 프로젝트입니다.
2. 왜 아키텍처 구조를 전환했는가
COME2US의 아키텍처는 Monolith → ECS → EKS로 전환을 거쳤습니다. 이는 단순히 새로운 기술을 적용하기 위한 전환이 아닌, 각 단계에서 드러난 운영 한계를 근거로 다음 구조를 선택했습니다.
[이미지 1] Event-Driven MSA Architecture
Phase 1. Monolith
초기 구조는 단일 EC2 위에 애플리케이션을 Docker 컨테이너로 배포해 MVP를 빠르게 검증했습니다. 이 구조는 초기 개발과 테스트에는 유리했지만, 운영 관점에서 한계가 분명했습니다.
•
확장성 한계 — 특정 서비스에만 부하가 증가해도 서버 전체를 키워야 하는 수직 확장에 의존
•
장애 전파 — 서비스 간 경계가 없었기 때문에 하나의 서비스 장애가 동일 서버의 다른 기능에도 영향을 줄 수 있는 구조
이 한계를 해결하기 위해 서비스 독립성과 수평 확장을 목표로 ECS Fargate 기반 MSA 구조로 전환했습니다.
Phase 2. ECS Fargate 기반 MSA
ECS 기반 MSA 전환 이후 장애 격리와 서비스 분리는 개선되었지만, 서비스 수가 늘어나면서 새로운 운영 부담이 생겼습니다.
•
ECS Fargate의 서비스 디스커버리 문제
ECS의 내부 IP/외부 IP 차이로 서비스 디스커버리가 기대한 방식으로 동작하지 않아 hostname을 환경변수로 직접 주입하는 방식으로 임시 대응
•
Spring Cloud 의존 증가
서비스 디스커버리, 라우팅, 정책 변경이 애플리케이션 스택에 결합되어 정책 변경이 서비스 재배포로 이어지는 구조
서비스 실행 환경과 공통 운영 정책을 더 선언적이고 추적 가능한 방식으로 관리할 필요가 있다고 판단했습니다.
Phase 3. EKS 기반 Cloud-Native 인프라
최종적으로 EKS 기반 환경으로 전환하며 Kubernetes, GitOps, Service Mesh를 활용한 운영 구조를 설계했습니다. 컴퓨팅, 네트워크, 보안, 데이터 계층을 AWS 인프라 위에서 일관된 방식으로 운영할 수 있는 기반을 만드는 것을 목표로 서비스별로 흩어질 수 있는 운영 책임을 줄이고, 인프라와 클러스터 상태를 코드 기준으로 관리할 수 있는 구조를 만들었습니다.
3. 네트워크와 보안 경계를 어떻게 설계했는가 — Network & Security
VPC 3계층 서브넷 설계
서비스의 외부 노출 범위를 최소화하고 계층별 보안 경계를 명확히 하기 위해 VPC 내부를 역할에 따라 계층화하고, Public Subnet, Private Subnet, Data Subnet으로 나누어 네트워크 경계를 설계했습니다.
Public Subnet | 외부 트래픽을 받는 Load Balancer, NAT Gateway 등 인터넷과 직접 연결이 필요한 리소스 배치 |
Private Subnet | EKS Worker Node와 애플리케이션 워크로드 배치 |
Data Subnet | RDS, ElastiCache, MSK 등 데이터 계층 리소스 배치 |
이 구조를 통해 애플리케이션은 외부 요청을 처리할 수 있으면서도, 데이터 계층은 외부에서 직접 접근할 수 없도록 격리했습니다.
Security Group 기반 접근 제어
보안 그룹은 IP 기반으로 넓게 열기보다, 가능한 한 리소스 간 참조 기반으로 접근 범위를 제한했습니다.
ALB → EKS 노드 → RDS/ElastiCache/MSK 순서로 허용 트래픽을 명시적으로 제한하며 각 계층은 이전 계층에서 오는 트래픽만 허용하는 최소 권한 네트워크 구조를 적용했습니다.
IAM / IRSA 기반 최소 권한
Kubernetes Pod가 AWS 리소스에 접근해야 하는 경우 IAM Role을 부여하는 IRSA를 활용했습니다. IRSA를 통해 External Secrets, AWS Load Balancer Controller, ExternalDNS 등 클러스터 컴포넌트가 필요한 권한만 갖도록 구성해 자격 증명 범위를 최소화했습니다.
Secret 관리
애플리케이션 시크릿은 Git 저장소에 직접 포함하지 않고, AWS SSM Parameter Store와 External Secrets를 활용해 관리했습니다. 민감 정보를 Git이 아닌 AWS 관리형 서비스에서 관리하도록 구성하며 코드베이스에 시크릿을 노출시키지 않도록 했습니다.
내부 통신 보안
서비스 간 내부 통신은 Istio mTLS를 활용해 평문 통신으로 인한 내부 네트워크 보안 위험을 차단했습니다.
4. 데이터 계층을 어떻게 분리하고 보호했는가 — Data Layer
데이터 계층 보안
COME2US는 E-Commerce MSA 프로젝트였기 때문에 애플리케이션 계층과 데이터 계층의 접근 경계를 분리하는 것이 중요했습니다. 따라서 데이터 계층은 별도의 Data Subnet(Private)에 격리해 외부 인터넷에서의 접근을 차단하고, 애플리케이션 레이어에서만 접근 가능하도록 보안 그룹을 제한했습니다.
또한 민감 정보는 코드나 Manifest에 직접 포함하지 않고 AWS SSM Parameter Store와 External Secrets를 통해 클러스터 내부로 주입되도록 구성했습니다.
데이터 계층 구성
트래픽 특성상 조회 요청이 쓰기 요청보다 많을 것으로 판단해 Read Replica를 분리해 조회 트래픽을 분산했습니다. Multi-AZ 구성으로 Primary 장애 시 자동 Failover를 보장했습니다.
세션 관리와 캐싱을 위한 ElastiCache Redis를 각각 구성했습니다.
•
세션 관리용
사용자 인증 세션을 저장하는 Redis는 장애 시 로그인 상태가 유실될 수 있기 때문에 Primary + Replica 구조로 구성해 가용성을 확보했습니다.
•
캐싱용
캐싱 데이터는 데이터 유실 시 DB에서 재조회하면 되기 때문에 단일 노드로 구성해 비용을 절감했습니다.
용도별로 가용성 요구사항이 다르다고 판단해 Redis 클러스터를 목적에 맞게 분리하고 구성 방식을 달리 적용했습니다.
SAGA 보상 트랜잭션 처리, 서비스 간 강결합 제거, 장애 전파 차단을 위해 주문∙결제 서비스에 Kafka를 적용했습니다.
5. 인프라를 어떻게 코드로 관리했는가 — Infrastructure as Code
재현성 확보
수동 구성에 의존하면 환경이 사람의 기억에 종속되고 재구성 시 드리프트가 발생할 수 있기 때문에, 이를 해결하기 위해 전체 AWS 인프라를 Terraform으로 코드화했습니다.
Terraform으로 관리한 주요 범위는 다음과 같습니다:
•
VPC, Subnet, Route Table, NAT Gateway
•
EKS Cluster, Node Group
•
RDS, ElastiCache, MSK
•
IAM Role, IRSA
•
SSM Parameter Store
•
Route53, ACM
Remote Backend 구성 — S3 + DynamoDB
Terraform state는 로컬 파일에 의존하지 않고 S3 Remote Backend로 관리했습니다. 인프라 상태를 중앙에서 관리함으로써, 로컬 환경 차이로 인한 state 유실이나 불일치 가능성을 줄이고자 했습니다.
또한 DynamoDB Lock Table을 함께 구성해, 동시에 Terraform이 실행될 때 state가 충돌하지 않도록 해 팀원들과 일관된 방식으로 상태를 관리할 수 있도록 구성했습니다.
State 분리
클러스터를 재구성할 때 생명주기가 다른 리소스가 변경되지 않도록 하고자 했습니다. Route53 Hosted Zone, ACM 인증서와 같이 외부 도메인 위임이나 인증 절차와 연결된 리소스는 일반 인프라와 생명주기가 다르기 때문에 별도의 state로 분리해 관리했습니다.
Terraform과 GitOps의 책임 경계 분리
Terraform이 관리해야 할 영역과 GitOps가 관리해야 할 영역을 분리했습니다.
•
Terraform: VPC, EKS, IAM, 데이터 계층, 클라우드 인프라 리소스 관리
•
ArgoCD: Kubernetes 내부 애플리케이션, 플랫폼 컴포넌트, Manifest 관리
인프라 레이어와 클러스터 운영 레이어의 변경 주기와 책임 범위가 다르다고 판단해, 이와 같이 책임 경계를 나눴습니다. 인프라는 Terraform으로 재현성을 확보하고, 클러스터 내부 리소스는 GitOps로 선언적 상태 수렴을 유지하는 방향을 선택했습니다.
Packer 기반 CI 환경 재구성
프로젝트 환경에서는 비용 제약으로 인해 AWS 리소스를 자주 Destroy/Recreate해야 했고, 이로 인해 Jenkins 서버와 Docker 환경을 매번 다시 구성해야 하는 문제가 있었습니다. 이 과정은 휴먼 에러와 설정 드리프트로 이어질 수 있었기 때문에, 이를 줄이기 위해 Packer를 사용했습니다.
[이미지 2] Packer 흐름
Packer를 통해 Docker가 사전 구성된 Golden AMI를 만들고, Terraform으로 Jenkins EC2, EBS, ALB, 컨테이너 기동까지 자동화했습니다.
그 결과 terraform apply만으로 CI 환경을 반복적으로 재구성할 수 있는 운영 모델을 만들었습니다.
6. EKS 운영 환경에서 확장성과 비용을 어떻게 고려했는가 — Compute, Scaling & Cost Optimization
EKS 기반 운영 환경에서는 워크로드 특성에 따라 어떤 노드에서 어떤 컴포넌트를 실행할지, 확장성과 비용 효율을 어떻게 함께 가져갈지가 중요하다고 보았습니다. COME2US에서는 핵심 운영 컴포넌트와 애플리케이션 워크로드가 서로 영향을 주지 않도록 노드 그룹을 분리하고, 기본 처리 용량은 On-Demand로 보장하되 트래픽 증가 구간은 Karpenter와 Spot Instance를 활용해 비용 효율적으로 확장하는 구조를 설계했습니다.
노드 그룹 분리
플랫폼 컴포넌트와 애플리케이션 워크로드가 같은 노드에서 경쟁할 경우, 애플리케이션 부하 증가로 인해 운영 컴포넌트가 Pending 상태가 될 수 있다고 판단했습니다. 이를 방지하기 위해 노드 그룹을 역할별로 분리했습니다.
구분 | 운영 방식 | 목적 |
Infra Node Group | On-Demand | Karpenter, ArgoCD, Istio, 모니터링 등 핵심 운영 컴포넌트 안정성 확보 |
App Baseline Node Group | On-Demand | 일반 트래픽 구간의 기본 애플리케이션 처리 용량 보장 |
Dynamic Node | Karpenter + Spot | 트래픽 증가 시 비용 효율적인 확장 처리 |
•
핵심 운영 컴포넌트 안정성 확보:
infra 노드 그룹에는 Taint를 적용해 핵심 운영 컴포넌트가 애플리케이션 부하에 밀려 Pending 상태가 되는 상황을 방지했습니다.
•
Karpenter + Spot 기반 확장:
애플리케이션 워크로드는 평상시에는 On-Demand 기반 노드에서 안정적으로 운영하고, 트래픽 증가 구간에서는 Karpenter가 Spot 노드를 동적으로 프로비저닝해 확장하도록 구성했습니다.
On-Demand / Spot 혼합 전략
클라우드 인프라에서는 비용 절감만큼이나 안정성과 가용성도 중요하다고 보았습니다. Spot Instance는 비용 측면에서 유리하지만 Interruption이 발생할 수 있다는 단점이 있습니다.
따라서 기본 워크로드는 On-Demand 노드에서 처리하도록 구성하고, 트래픽 증가 구간에서 추가로 필요한 용량은 Karpenter + Spot Instance를 통해 확보하도록 함으로써, 안정적인 처리와 가용성을 확보했습니다.
•
On-Demand: 기본 애플리케이션 처리 용량과 운영 컴포넌트 안정성 확보
•
Spot Instance: 트래픽 증가 시 추가 워크로드를 비용 효율적으로 처리
•
Karpenter: Pod 요구 리소스에 맞춰 필요한 노드를 동적으로 프로비저닝
Karpenter + Spot 기반 확장 구조
Karpenter는 Pod의 요구 리소스를 기준으로 필요한 노드를 동적으로 프로비저닝할 수 있기 때문에, 고정 ASG보다 유연한 확장이 가능했으며 프로비저닝 속도 또한 빠르다는 장점을 얻을 수 있었습니다.
이러한 확장 구간에 Spot Instance를 사용함으로써 기존 On-Demand 중심 구성 대비 약 70%의 비용 절감 효과를 얻을 수 있었습니다.
HPA + Karpenter Race Condition — minReplicas 버퍼 전략
HPA는 메트릭 감지 즉시 Pod 생성을 요청하지만 Karpenter는 노드 프로비저닝에 약 60초가 소요됩니다. 이 시간 차이로 인해 트래픽이 급격히 증가할 경우, 노드가 Ready되기 전 Pod Pending이 누적되는 문제가 발생할 수 있다고 판단했습니다.
이를 완화하기 위해 핵심 도메인에는 더 높은 minReplicas를 설정하고, 조회성 서비스에는 상대적으로 낮은 minReplicas를 적용했습니다.
•
주문∙결제: 높은 minReplicas로 기본 처리 여유 확보
•
조회성 서비스: 낮은 minReplicas로 비용 효율 유지
7. 장애를 어떻게 분석했는가 — RCA
Issue. Jenkins Node Hang 장애 — EBS gp2 병목 장애
CI 환경에서 Docker 이미지 빌드 중 노드 전체가 Hang 상태로 전환되는 문제가 발생했습니다. 일반적인 CPU와 Memory의 리소스 부족을 의심했지만 정상범위였습니다. 따라서 다른 병목 가능성을 확인하기 위해 CloudWatch 지표를 확인했습니다.
CloudWatch 지표를 통해 다음 패턴을 확인했습니다.
[이미지 3] BurstBalance 고갈
[이미지 4] VolumeQueueLength 급증
[이미지 5] VolumeTotalReadTime 급증
•
BurstBalance 고갈
•
VolumeTotalReadTime 급증
•
VolumeQueueLength 급증
Jenkins 서버는 단일 Root EBS(gp2)에서 OS I/O와 Docker I/O가 경합하는 구조였습니다. 따라서 Docker 이미지 빌드 과정에서 I/O가 집중되면서 gp2의 크레딧 기반 IOPS 구조가 한계에 도달했고, 그 결과 EBS I/O Throttling이 발생한 것으로 판단했습니다.
해결은 두 방향으로 진행했습니다.
1.
Root/Data 볼륨 분리
OS 레이어와 Docker 빌드 워크로드의 I/O 경합을 분리했습니다.
2.
gp2 → gp3 전환
크레딧 기반 가변 IOPS에서 고정 IOPS 구조로 전환했습니다.
Jenkins Node의 Node Hang 현상이 해소되었고, 지표도 안정화되었습니다.
이 경험을 바탕으로 EKS 환경에서 gp3를 Default StorageClass로 설정함으로써 Prometheus, Loki, Tempo와 같이 지속적인 쓰기 I/O가 발생하는 컴포넌트에서 유사한 문제가 반복되지 않도록 했습니다.
[이미지 6] QueueLength 안정화 (피크 후 안정화)
[이미지 7] TotalReadTime 안정화 (피크 후 안정화)
8. 어떤 결과를 만들었는가
COME2US에서의 클라우드 엔지니어 관점 결과는 다음과 같습니다.
영역 | 변화 |
클라우드 아키텍처 | Monolith → ECS → EKS로 운영 한계에 따라 구조 고도화 |
네트워크 격리 | Public / Private / Data Subnet 분리 |
보안 경계 | Security Group 참조, IAM / IRSA, SSM 기반 접근 제어 |
데이터 계층 | RDS, ElastiCache, MSK를 외부 노출 없이 분리 구성 |
인프라 재현성 | Terraform 기반 AWS 인프라 코드화 |
클러스터 운영 | EKS Node Group 분리와 Karpenter 기반 확장 구조 설계 |
비용 최적화 | Karpenter + Spot 기반 확장, gp3 전환 |
운영 가시성 | CloudWatch, Prometheus, Grafana, Loki, Tempo 기반 지표 확인 |
장애 대응 | EBS gp2 I/O 병목을 CloudWatch로 규명하고 gp3 전환 및 볼륨 분리로 개선 |
서비스 특성과 운영 조건에 맞는 아키텍처를 설계하고, 네트워크와 보안 경계 설계, 비용과 가용성 사이의 균형점을 찾으며, 운영 지표를 통해 구조를 개선하는 과정이 안정적인 클라우드 운영 환경을 만든다고 생각합니다.






