Skip to content

System Architecture

chaneee93 edited this page Oct 21, 2026 · 10 revisions

System Architecture

상태: 1주차 클라우드 설계안 / 팀 검토 전
작성일: 2026-10-07. 실제 구축·검증 결과가 아닌 목표 구조입니다. 다음 주 팀 검토를 거쳐 수정합니다. 계정·리전·AZ 이름은 미정입니다. 2026-10-14 공식 단가 기준의 가정 기반 비용 추정표를 추가했습니다. 실제 계정·사양·사용량 확인 후 재산정합니다. 2026-10-12 업데이트: 팀 확정 사항인 6분야·30분 갱신과 mock/real 운영 방식을 반영했습니다. 인프라 구성은 계속 설계안이며 실제 구축·검증 완료를 뜻하지 않습니다.

개요

AI 뉴스 브리핑 서비스의 개발 환경은 온프레미스(develop), 운영 환경은 AWS(main)로 분리합니다. AWS는 퍼블릭 입구, 프라이빗 앱, 프라이빗 데이터의 3Tier로 구성하고 두 AZ에 분산합니다.

AWS 3Tier A/B존 이중화 설계

  • 화면: 사용자 → CloudFront → 비공개 S3. 두 서비스는 VPC 서브넷 밖에 있습니다.
  • API: 사용자 → 두 AZ에 연결된 ALB → 정상 앱 파드.
  • 저장소: 양쪽 앱이 RDS·Redis의 현재 Primary 엔드포인트에 접속합니다. 각 AZ에 독립된 DB를 만들어 따로 쓰는 구조가 아닙니다.
  • 외부 호출: 앱 A → NAT-A → IGW → 뉴스·AI API, 앱 B → NAT-B → IGW → 뉴스·AI API.
  • ALB는 논리적 1개, NAT는 AZ별 1개로 총 2개입니다.

뉴스 수집과 AI 운영

2026-10-12 팀 확정 사항과 API 명세, 성능 테스트를 기준으로 정리합니다.

  • 분야별 요약: 정치·경제·사회·생활/문화·IT/과학·스포츠의 6개 분야를 30분마다 갱신합니다. 사용자는 저장된 요약을 조회하므로 조회 사용자 수만큼 AI를 호출하지 않습니다.
  • 기사 수집: 정치·경제·사회·생활/문화·스포츠는 연합뉴스 RSS, IT/과학은 전자신문 RSS를 사용합니다. 제목·요약문·링크·언론사·날짜를 저장하고 7일 보관합니다.
  • 질문 답변: 질문과 관련된 기사가 DB에 없으면 네이버 뉴스 검색 API로 보완합니다. 질문 1건당 AI 1회 호출을 비용 산정 기준으로 둡니다. 사용자당 하루 최대 10회이며 세부 차감 규칙은 API 명세를 따릅니다.
  • AI 제공 방식: 팀 AWS 계정에서 Amazon Bedrock을 사용할 수 있으면 Bedrock을 사용하고, 불가능하면 AI 회사 API를 직접 호출합니다. 요약·질문 답변에 같은 제공 방식을 사용하며 모델은 아직 미정입니다.
  • 평소 개발·테스트·k6 부하 테스트: AI_MODE=mock으로 실제 AI를 호출하지 않습니다. 이때 AI 호출료는 없지만 AWS 인프라 비용과는 별개입니다.
  • 점검·데모: 실제 AI는 품질 확인 및 데모에 필요한 시간에만 AI_MODE=real로 켭니다. 예정 시점은 4주차 점검과 6주차 데모 리허설·발표이며 정확한 일수·시간은 추후 확정합니다.
  • mock 결과는 화면에 샘플 데이터로 표시합니다. 실제 AI 지연을 소량 측정해 mock 지연에 반영하는 검증 방식은 성능 테스트 문서를 따릅니다.

AI 비용 산정용 사용량 가정

아래는 백엔드 담당이 제공한 추정치이며 실측값·청구 금액이 아닙니다. 모델별 입력·출력 단가와 실제 사용 시간 확정 후 비용을 계산합니다. 이전의 5분·3분야 가정은 적용하지 않습니다.

용도 호출 수 기준 1회 입력 토큰 1회 출력 토큰
분야별 요약 30분마다 6회. 24시간이면 288회 약 8,000 (기사 30개 기준) 약 1,500
질문 답변 질문 1건당 1회, 사용자당 하루 최대 10회 약 3,000 (기사 5~10개 기준) 약 500
  • 분야 요약 24시간 기준: 입력 288 × 8,000 = 2,304,000토큰, 출력 288 × 1,500 = 432,000토큰.
  • 실제 AI 가동 시간이 H시간이면 분야 요약은 H × 2 × 6회로 추정합니다. 4시간 예시는 48회, 입력 384,000·출력 72,000토큰입니다. 기동 시 추가 갱신·재시도는 별도 합산합니다.
  • 질문 수가 Q건이면 입력 Q × 3,000, 출력 Q × 500토큰입니다. 예를 들어 10명이 각각 5회 질문하면 50건입니다.
  • 총 AI 비용은 실제 호출의 입력 토큰 사용료와 출력 토큰 사용료를 합산합니다. 24시간 상시 사용이나 매달 매일 사용을 전제하지 않습니다.
  • 아직 정하지 않은 항목: Bedrock 접근 가능 여부, 서울 리전 모델 지원·모델 단가, 점검·데모 일수와 실제 가동 시간·질문 수.

비용 추정 금액표

2026-10-14 검토 초안: 실제 청구액·확정 예산이 아닙니다. 가정 기반 합계 약 $316.33, 예비비 20% 포함 약 $379.60(세전)입니다.

1. 계산 범위와 가정

  • 서울(ap-northeast-2)을 계산용 리전으로 가정한다. 팀 리전 확정은 아니다. USD, 온디맨드, 할인·크레딧·프리티어·세금 미반영이다.
  • 범위는 26주차(10/1211/15, 마지막 주말 포함 정리 기간)다. 기간 종료 후 모든 과금 자원을 정리한다는 가정이며 실제 수업 마지막 날은 11/13이다.
  • 사용자 요청대로 NAT 2개, RDS Primary+Standby, Redis Primary+Replica를 유지한다.
  • 2주차 NAT 실습 4시간, 3주차 내부 통신 실습 4시간을 가정한다. 3주차 테스트 EC2는 t3.medium 1대×4시간이다.
  • 4주차 EC2+kubeadm은 t3.medium 제어 노드 1대와 t3.large 작업 노드 2대, 하루 4시간×5일=20시간으로 계산한다.
  • 5~6주차 EKS 작업 노드는 t3.large 2대, 하루 4시간×10일=40시간이다. EKS 제어 영역은 표준 지원 버전 1개를 14일=336시간 유지한다. Auto Mode는 사용하지 않는 가정이다.
  • NAT 2개는 총 68시간(4+4+20+40), ALB 1개는 60시간(20+40)만 존재하도록 생성·삭제한다는 가정이다. EC2 종료만으로 NAT·ALB 비용이 멈추는 것은 아니다. 재생성·시작 준비 시간이 길어지면 추가된다.
  • 데이터 보존과 재생성 절차가 아직 확정되지 않았으므로 RDS·Redis는 3~6주차 28일=672시간 유지하는 보수적 기준으로 계산한다. 이는 항상 켜두라는 지시가 아니다. 실제 종료·복원 절차 확정 후 시간을 줄여 재산정한다.
  • RDS MySQL db.t3.medium Multi-AZ 배포 1개, gp3 논리 용량 20GB; Redis OSS cache.t3.small 2개를 가정한다. 지원 중인 엔진 버전을 사용하고 연장 지원료는 제외한다. 사양은 견적용이며 성능 검증 전이다.
  • EBS gp3는 3주차 테스트용 30GB×7일, 4주차 3대×30GB×7일, 5~6주차 2대×30GB×14일을 유지한다. 월 단가는 730시간으로 나눠 근사한다. 실제 월 길이·시간별 사용량에 따라 소액 차이가 발생할 수 있다.
  • ALB 평균 1 LCU, NAT 처리량 합계 20GB를 가정한다. 공인 IPv4는 NAT용 2개×68시간, ALB용 2개×60시간이다. 추가 IP가 할당되면 증액한다. 앱·DB는 공인 IP 없이 구성한다.

2. 예상 금액

항목 적용 단가·계산 예상 USD
EC2 t3.medium $0.052/시간×24 + t3.large $0.104/시간×2대×60시간 13.73
EKS 제어 영역 표준 지원 $0.10/시간×336시간 33.60
EBS gp3 $0.0912/GB·월×(30×168+90×168+60×336)/730 5.04
NAT 게이트웨이 2개 $0.059/개·시간×2×68 8.02
NAT 데이터 처리 $0.059/GB×20GB 1.18
공인 IPv4 $0.005/IP·시간×(2×68+2×60) 1.28
ALB 1개+평균 1 LCU ($0.0225/시간+$0.008/LCU·시간)×60 1.83
RDS MySQL Multi-AZ 이중화 포함 단가 $0.208/시간×672. 여기에 다시 2를 곱하지 않음 139.78
RDS gp3 Multi-AZ 저장소 이중화 포함 단가 $0.262/GB·월×20GB×672/730 4.82
Redis OSS 노드 2개 cache.t3.small $0.049/노드·시간×2×672 65.86
Route 53 호스팅 영역 1개×$0.50/월×10월·11월 1.00
ACM 인증서 2개 CloudFront·ALB에 연결하는 비내보내기 공개 인증서 가정 0.00
Bedrock 실제 AI Nova Lite 계산용 가정, 아래 12시간·질문 150건 예시 0.20
도메인 신규 구입 예산 공식 단가 아님: 미선정 도메인의 임시 예산. 이미 보유한 도메인 사용 시 차감 20.00
화면·로그·추가 백업·전송 등 공식 단가 합산 아님: S3·CloudFront·로그·이미지 저장·추가 백업·기타 전송·시험용 자원 등의 임시 여유분 20.00
예상 합계 반올림 전 값으로 합산 316.33
20% 예비비 포함 316.3313×1.2. 소수점 표기 합계와 미세한 차이가 있을 수 있음 379.60

예산 계획용으로 **약 $380, 여유 있게 $400(세전)**를 제안한다. 상한 보장이나 팀 예산 확정이 아니다. 원화는 실제 결제 환율·세금에 따라 달라지므로 확정 환산액을 적지 않는다. 도메인과 기타 항목의 $40는 예약금이나 실제 AWS 청구 금액이 아닌 편의상 잡은 예산이다.

3. 용민님 AI 운영 기준 반영

  • 분야 요약: 30분마다 6분야, 호출당 입력 8,000·출력 1,500토큰. 저장된 요약 조회는 추가 AI 호출로 계산하지 않는다.
  • 질문: 사용자당 하루 최대 10회, 질문당 1회 호출, 입력 3,000·출력 500토큰.
  • 평소 개발·테스트·k6는 mock이며 실제 AI 호출료는 0이다. 실제 AI는 4주차 점검과 6주차 리허설·발표 때만 사용하는 계획이다.
  • 계산용 예시: 4주차 점검 1회+6주차 리허설·발표 2회, 각 4시간으로 총 12시간. 각 회차 10명이 5번씩 질문해 총 150건. 횟수·시간·인원은 합의된 일정이 아니다.
  • 모델은 Amazon Nova Lite v1을 계산용으로만 가정한다. 팀 모델 결정이나 실제 호출 가능 확인을 대신하지 않는다.
  • 서울 가격 카탈로그의 온디맨드 단가는 입력 $0.071/100만 토큰, 출력 $0.284/100만 토큰이다. Batch 단가나 다른 리전의 $0.06/$0.24를 섞지 않았다.
  • 공식 모델 문서는 서울에서 In-Region은 미지원, Geo Cross-Region은 지원으로 안내한다. 서울 내에서만 추론한다는 뜻이 아니다. 계정의 추론 프로필·대상 리전 권한과 정책, 실제 적용 요금을 확인해야 한다.
구분 호출 수 입력 토큰 출력 토큰 예상 USD
요약 12시간 12×2×6=144 1,152,000 216,000 0.143136
질문 150건 150 450,000 75,000 0.053250
합계 294 1,602,000 291,000 0.196386 ≈ 0.20

계산식: 입력 1.602×$0.071+출력 0.291×$0.284. 배치라는 앱 실행 방식만으로 Bedrock Batch 할인 요금을 적용하지 않는다. 시작 직후 갱신·재시도·실제 프롬프트 추가 토큰은 별도이며, 모델이 변경되면 이 금액도 바뀐다. AI가 저렴하게 계산되는 이유는 적은 호출 시간과 가정한 모델 단가 때문이다.

4. 영찬님 구성 반영

  • app.{도메인} → CloudFront → 비공개 S3, api.{도메인} → ALB → 앱. API를 CloudFront 경유로 중복 계산하지 않는다.
  • 같은 상위 도메인 하나를 사용한다. app·api를 별도 도메인 두 개 구입으로 계산하지 않는다.
  • Route 53 호스팅 영역은 하나로 가정하고, ALB·CloudFront를 가리키는 적격 Alias A/AAAA 질의는 무료 조건을 적용한다. 다른 질의·추가 영역은 별도다.
  • 인증서는 CloudFront용 us-east-1, ALB용 서울에 각각 발급하는 계획이다. 두 개 모두 AWS 서비스에 연결하는 ACM 비내보내기 공개 인증서로 가정해 $0으로 계산한다. 내보내기 인증서·Private CA는 이 견적에 포함하지 않는다.
  • CORS credentials, 쿠키 포함 요청, api.js 환경별 주소, 화면 전용 SPA 처리는 기존 설계를 유지한다. 별도 유료 서비스 항목으로 추가하지 않는다.

5. 운영 방식에 따른 변동과 재확인 항목

  • DB·Redis 상시 유지가 이 견적의 가장 큰 부분이다. 24시간 유지일을 하루 줄이면 노드 실행료 기준 RDS $4.992+Redis $2.352=약 $7.34/일 감소할 수 있다. 저장·백업·재생성 비용까지 사라진다는 뜻은 아니다.
  • NAT·ALB를 4~6주차 내내 504시간 유지하면 현재 실습시간 가정보다 약 $74.52 추가될 수 있다(NAT·ALB 시간료와 IPv4 기준, 추가 LCU·데이터 처리 제외). 따라서 퇴실 뒤 실제 삭제·IP 해제 여부가 중요하다.
  • 실습 종료만으로 과금이 중지되지 않는다. EKS·Redis·NAT·ALB는 EC2처럼 일괄 정지된다고 가정하지 않는다. 데이터 보존·백업 검증 후 정리 절차를 확정한다.
  • 추가 스냅샷·복원 DB, CloudWatch 대량 로그, 이미지 저장소, 인터넷·AZ 간 전송, CPU 크레딧 초과, 부하 테스트로 인한 ALB 용량 증가, 준비·장애 복구 시간은 실제 사용에 따라 증액된다. $20 기타 예산이 이를 모두 보장하지 않는다.
  • 이 견적은 계정 확인 전 작성한 설계 추정치다. 리전·사양·모델·기간·기존 도메인·프리티어·크레딧과 예상 사용량을 확정하면 다시 계산한다. 어떤 자원도 이번 작업으로 생성·구입하지 않는다.

6. 공식 출처

서울 리전 단가는 AWS 공개 Price List의 OnDemand 항목에서 조회했다. current 링크는 갱신되므로 조회 당시 적용 단가는 위 표에 고정 기록했다.

월 730시간 비교 견적

서울 리전을 계산에만 사용합니다. Linux 온디맨드·할인/크레딧/세금 제외. 사양은 이전 견적과 비교하기 위한 가정이며 계정에서 MySQL 8.4 및 선택 사양의 생성 가능 여부는 미확인입니다.

2026-10-19 AWS 공식 Price List를 다시 읽었습니다. EC2·RDS·Redis·ALB·NAT 단가는 기존 견적과 같았습니다. Redis는 표준 지원 노드 단가이며 연장 지원 항목을 합산하지 않았습니다. NAT는 Regional 상품이 아닌 AZ별 NAT 상품을 사용했습니다.

항목 수량·단가 월 USD
EC2 제어 평면 t3.medium 1 × $0.052 × 730 37.96
EC2 워커 t3.large 2 × $0.104 × 730 151.84
EBS gp3 30GB × 3대 × $0.0912 8.21
RDS MySQL Multi-AZ db.t3.medium $0.208 × 730 (Primary/Standby 포함) 151.84
RDS gp3 Multi-AZ 20GB × $0.262 (이중화 포함 단가) 5.24
Redis Primary/Replica cache.t3.small 2 × $0.049 × 730 71.54
NAT 2개 2 × $0.059 × 730 86.14
NAT 처리량 가정 합계 20GB × $0.059 1.18
ALB + 평균 1 LCU ($0.0225 + $0.008) × 730 22.27
공인 IPv4 NAT 2 + ALB 최소 가정 2, $0.005 × 4 × 730 14.60
위 항목 소계 반올림 전 합산 550.81
소계 + 20% 프로젝트 전체 예산 확정 아님 660.98

이 표는 M4 EC2 구성을 한 달 계속 유지하는 비교용입니다. EKS 제어 영역, S3·CloudFront, Route 53·도메인, AI, 로그·추가 백업, 인터넷/AZ 간 전송, CPU 크레딧 초과, 추가 IPv4·LCU는 별도입니다. AWS Pricing Calculator 저장 견적 링크는 아직 만들지 않았습니다. 실제 계정과 엔진·사양 선택 후 Calculator에서 보완해야 합니다.

기존 $316.33(여유 포함 $379.60)은 2~6주차 실습시간·데이터 유지기간 가정의 프로젝트 견적입니다. 이 월 소계와 기간·포함 항목이 다르므로 직접 절감액을 비교하지 않습니다.

실습 종료 후 비용 관리

자원 종료 방법 남는 비용·주의
EC2 중지 또는 불필요 인스턴스 종료 EBS·스냅샷·보유 공인 IP 등 별도
RDS 지원 구성은 임시 중지 가능 스토리지·백업 요금 유지. 연속 7일 후 자동 재시작
Redis 캐시 보존 정책·최종 백업 확인 후 삭제 EC2처럼 중지하는 서비스가 아님. 보존 스냅샷 별도
NAT 삭제 후 사용하지 않는 EIP 해제 EC2 중지로 NAT·공인 IP 요금이 멈추지 않음
ALB 재생성 절차 확보 후 삭제 EC2 중지로 ALB 요금이 멈추지 않음
EKS (M5) 재생성 가능한 경우 클러스터 삭제 검토 노드만 중지해도 제어 영역 비용 발생

데이터·상태 파일·백업은 자동 삭제 목록에 넣지 않습니다. 이 문서는 삭제 실행 지시가 아닙니다. 팀 공용 자원과 보존 대상을 확인한 뒤 종료하고 결과를 기록합니다.

단계별 환경

단계 환경 배포 대상 배포 방식(계획)
1 온프레미스 VM, kubeadm 멀티노드 develop GitHub Actions → 테스트 → 이미지 빌드 → GHCR push(커밋 SHA 태그) → 클러스터 안 self-hosted runner가 개발 클러스터에 적용
2 AWS 3Tier, EC2 + kubeadm main GitHub Actions → 이미지 빌드 → EC2 클러스터
3 AWS EKS, Terraform main Terraform으로 환경 구성 + GitHub Actions로 앱 배포

현재 클라우드 설계 목표는 EKS입니다. 실제 적용 방식과 각 단계 연결은 팀 검토 후 확정합니다.

네트워크 구조

VPC 주소 제안: 10.20.0.0/16. 기존 팀 네트워크와 중복되면 변경합니다. 실제 리전과 AZ 이름은 추후 입력합니다.

구역 AZ A AZ B 배치 대상
퍼블릭 10.20.0.0/24 10.20.1.0/24 ALB의 AZ별 연결, NAT-A / NAT-B
프라이빗 앱 10.20.10.0/24 10.20.11.0/24 EC2 / EKS 작업 노드
프라이빗 데이터 10.20.20.0/24 10.20.21.0/24 RDS Primary·Standby, Redis Primary·Replica

라우팅

퍼블릭 A/B는 rt-public, 앱 A/B는 각각 rt-app-a·rt-app-b, 데이터 A/B는 rt-data에 연결하는 설계입니다. 모든 표에 VPC local 경로를 유지하며 앱·DB 서브넷의 공인 IPv4 자동 할당은 비활성화합니다.

  • 퍼블릭 A/B: 0.0.0.0/0 → IGW.
  • 앱 A: 0.0.0.0/0 → NAT-A, 앱 B: 0.0.0.0/0 → NAT-B. 앱 라우팅 표를 AZ별로 분리합니다.
  • 데이터 A/B: 인터넷 기본 경로 없음. 내부 통신은 VPC local 경로를 사용합니다.
  • NAT는 각 AZ의 앱이 자기 AZ의 NAT를 사용하도록 합니다. 장애 시 다른 NAT로 경로가 자동 변경되는 설계는 아닙니다.

접근 제어

IPv4·동일 VPC 기준입니다. 아래 SG 이름은 설계용 이름이며 실제 SG ID가 아닙니다. SG는 허용 규칙을 합산하므로 다른 SG를 함께 연결해 우회 허용하지 않도록 확인합니다.

SG 방향 상대 프로토콜·포트 목적
sg-alb 인바운드 0.0.0.0/0 TCP 443 API HTTPS 진입
sg-alb 인바운드 0.0.0.0/0 TCP 80 HTTPS 리디렉션 전용 리스너
sg-alb 아웃바운드 sg-app TCP P_TARGET, P_HEALTH 대상 서비스와 헬스체크. 두 포트가 같으면 규칙 하나
sg-app 인바운드 sg-alb TCP P_TARGET, P_HEALTH 사용자 요청·헬스체크는 ALB에서만 허용
sg-app 아웃바운드 sg-db TCP 3306 API·워커·배치의 MySQL 연결
sg-app 아웃바운드 sg-redis TCP 6379 Redis TLS 연결 계획. 실제 엔진 설정 확인
sg-app 아웃바운드 0.0.0.0/0 TCP 443 해당 AZ NAT를 통한 뉴스·AI API 및 필요한 HTTPS 서비스 접근
sg-db 인바운드 sg-app TCP 3306 앱 계층만 DB 접속
sg-redis 인바운드 sg-app TCP 6379 앱 계층만 Redis 접속
sg-db / sg-redis 아웃바운드 사용자 정의 신규 연결 없음 기본 전체 허용 제거를 계획 허용된 연결의 응답은 상태 추적으로 처리. 관리형 서비스 실제 요구사항은 구축 시 확인

P_TARGET은 ALB가 실제 연결하는 대상 포트, P_HEALTH는 대상 그룹 헬스체크 포트입니다. 아직 확정되지 않은 숫자를 실제 포트처럼 게시하지 않습니다. 백엔드 실행 포트와 ALB 대상 타입을 확인한 뒤 적용합니다.

2026-10-21 저장소 대조: backend와 infra의 앱 포트는 8080이며 readiness는 /actuator/health/readiness, liveness는 /actuator/health/liveness입니다. 온프렘 Traefik NodePort는 HTTP 30080·HTTPS 30443입니다. 이는 AWS용 대상·헬스체크 포트를 확정한 값이 아니므로 Terraform에서는 alb_target_ports 필수 입력으로 둡니다. 대상 경로·호스트 라우팅은 M4 ALB 구성에서 확인합니다.

현재 backend Category.java에 정의된 RSS 8개는 모두 https://rss.etnews.com/ 주소입니다. 외부 443 → 같은 AZ NAT → IGW 경로를 코드와 대조했습니다. 실제 VPC의 DNS·RSS 접속은 계정 수령 후 검증합니다. Terraform 모의 테스트 통과와 AWS 실통신 성공은 구분합니다.

  • 4주차 kubeadm의 instance 대상이면 필요한 NodePort/Ingress 대상 포트만 허용합니다. 컨테이너 포트와 같다고 가정하거나 NodePort 전체 범위를 열지 않습니다.
  • EKS ip 대상이면 실제 파드 ENI에 적용되는 SG와 대상 포트를 확인합니다. 별도 파드 SG를 쓰는지에 따라 sg-app 참조 대상이 달라집니다.
  • 클러스터 제어 영역·노드·CNI·DNS·관리 접속 규칙은 위 사용자 트래픽 표와 별도로 확정합니다. 이 표만으로 Kubernetes 전체 통신 구성이 완료되지는 않습니다.
  • 기본 전체 아웃바운드 규칙이 남아 있으면 위 제한이 무의미하므로 실제 구성 시 확인합니다. 기본 VPC DNS와 사용자 지정 DNS는 구분하며, 사용자 지정 DNS 사용 시 해당 서버로 UDP/TCP 53을 별도 설계합니다.
  • SG만으로 HTTPS 목적지를 특정 뉴스·AI 도메인으로 제한할 수는 없습니다. 현재 443 아웃바운드는 모든 IPv4 목적지에 대한 허용입니다.
  • 앱·DB·Redis의 인터넷 직접 인바운드는 허용하지 않습니다. SSH 22와 Kubernetes API 6443을 인터넷 전체에 열지 않습니다. 관리 경로는 계정 권한 확인 후 별도 확정합니다.
  • NAT·S3·CloudFront에 이 SG 표를 그대로 적용하지 않습니다. 화면은 CloudFront→비공개 S3, API는 api 도메인→ALB라는 기존 구성을 유지합니다.

구축 후에는 ALB 정상 대상, 앱→DB/Redis 연결 성공, 비허용 출발지의 접속 실패를 실제로 검증합니다.

온프레미스 (develop)

항목 값
하이퍼바이저 VirtualBox
어댑터 1 NAT. VM의 인터넷 접속(패키지·이미지 다운로드)
어댑터 2 호스트 전용 192.168.56.0/24, DHCP 비활성, 노드 고정 IP
노드 IP k8s-cp 192.168.56.10, k8s-worker1 .11, k8s-worker2 .12
파드 대역 10.244.0.0/16
서비스 대역 10.96.0.0/12 (kubeadm 기본값)
CNI Calico
외부 노출 ingress-nginx(NodePort). / → 프론트, /api/* → API
팀원 접속 미정 (VPN 검토)
  • 노드 간 통신은 호스트 전용 네트워크를 사용합니다. 공유기와 무관해 장소가 바뀌어도 노드 IP가 유지됩니다.
  • VirtualBox NAT는 모든 VM에 같은 IP(10.0.2.15)를 주므로, kubelet에 --node-ip로 호스트 전용 IP를 지정해 노드 주소가 겹치지 않게 합니다.
  • 파드 대역은 노드 대역(192.168.56.x)과 겹치지 않도록 10.244.0.0/16으로 지정합니다. 겹치면 라우팅이 꼬입니다.
  • 온프레미스 대역은 AWS VPC(10.20.0.0/16)와도 겹치지 않습니다. 두 환경을 VPN으로 직접 연결하지 않으며, 온프레미스에서 AWS로는 S3 백업 업로드만 나갑니다.
  • 화면과 API가 같은 출처(Nginx가 /api/*를 백엔드로 프록시)이므로 온프레미스에서는 CORS가 필요하지 않습니다.
  • /actuator/*는 Ingress에 연결하지 않고 클러스터 내부에서만 접근합니다. 메트릭·커밋 SHA 같은 내부 정보가 외부에 노출되지 않게 하기 위해서입니다.

컴퓨트

  • 4주차: EC2 + kubeadm, 제어 노드 1대와 A/B 작업 노드 각 1대를 초기안으로 둡니다. 제어 노드 1대는 단일 장애 지점이며 학습 단계의 한계입니다.
  • 5주차: EKS 관리형 제어 영역으로 전환하고 작업 노드를 A/B에 분산합니다. EKS 제어 영역은 우리 앱 서브넷의 EC2가 아닙니다.
  • API·워커 복제본이 두 AZ에 분산되도록 배치 규칙을 적용하고, 한 AZ 장애 시 잔여 용량을 검증합니다.
  • API는 HPA, 워커는 큐 길이 기반 KEDA 확장을 계획합니다. 노드 증설은 별도 설정합니다.
  • 갱신 배치는 30분 주기 CronJob으로 실행하며 중복 실행을 제어합니다.
  • 서버 크기·앱 포트·헬스체크 경로·메모리는 백엔드 실행 요건에 맞춰 확정합니다.

온프레미스 (develop)

항목 값
호스트 노트북 1대 (AMD Ryzen 5, 6코어 12스레드, 32GB, Windows)
하이퍼바이저 VirtualBox (Hyper-V 비활성 상태에서 직접 실행)
OS Ubuntu Server 24.04 LTS (amd64)
컨테이너 런타임 containerd 2.4 (SystemdCgroup 사용)
Kubernetes v1.35 (kubeadm·kubelet·kubectl 버전 고정)
노드 역할 vCPU RAM 디스크 IP
k8s-cp control plane, self-hosted runner 2 4GB 40GB 192.168.56.10
k8s-worker1 worker 2 6GB 40GB 192.168.56.11
k8s-worker2 worker 2 6GB 40GB 192.168.56.12
워크로드 종류 비고
API Deployment readiness는 DB 연결 기준 (Redis 제외, API 명세 기준)
워커 Deployment 최소 1개 유지. 0개로 줄이면 기동 시간 때문에 질문 재투입(30초)·실패 처리(60초) 기준에 걸릴 수 있음
요약 갱신 배치 CronJob concurrencyPolicy: Forbid로 중복 실행 방지
프론트 Deployment (Nginx) 정적 파일 + /api/* 프록시
  • 호스트 CPU가 x86(amd64)이라 AWS EC2와 같은 이미지를 그대로 사용합니다.
  • 앱·DB·모니터링은 워커에 올라가므로 워커에 RAM을 더 배정합니다. 디스크는 사용한 만큼만 커지는 가변 크기입니다.
  • swap은 비활성화합니다. kubelet이 메모리를 정확히 계산해 파드를 배치하기 위해서입니다.
  • 온프레미스는 5주차에 KEDA를 설치하기 전까지 워커 수를 고정으로 운영합니다.

데이터 계층

구성 AZ A 초기 배치 AZ B 초기 배치 장애 대응
RDS MySQL Multi-AZ DB instance Primary Standby 동기 복제, 대기 DB 자동 승격
ElastiCache Redis OSS 복제 그룹 Primary Replica 비동기 복제, Multi-AZ·Automatic Failover 활성화
  • RDS는 독립 DB 두 개가 아닌 Multi-AZ 배포 1개입니다. Standby는 평소 읽기 요청을 처리하지 않습니다. 3개 AZ를 사용하는 Multi-AZ DB cluster와 구분합니다.
  • Redis는 클러스터 모드 비활성, 샤드 1개, 주 노드 1개 + 복제 노드 1개를 기준으로 설계합니다.
  • RDS는 회원·질문·결과·작업 상태를, Redis는 캐시·작업 대기열을 담당합니다. 스키마는 백엔드와 ERD 문서에서 확정합니다.
  • A/B 주·대기 역할은 초기 예시이며 장애 전환 후 바뀔 수 있습니다. 앱은 고정 IP 대신 서비스 엔드포인트와 재연결 로직을 사용합니다.
  • Redis 비동기 복제는 최근 쓰기 일부 유실 가능성이 있습니다. DB 작업 상태, 재처리, 중복 처리 방지를 백엔드와 설계합니다.
  • 이중화는 백업을 대체하지 않습니다. 스냅샷 복원과 데이터 검증은 별도로 수행합니다.

온프레미스 (develop)

구성 방식 비고
MySQL StatefulSet + PVC kubeadm에는 기본 스토리지가 없어 local-path-provisioner로 PVC를 제공합니다
Redis Deployment 단일 인스턴스. 캐시와 작업 대기열
백업 etcd 스냅샷·MySQL 덤프 하루 1회, 7일 보관 5주차부터 S3로 전송합니다
  • 온프레미스 데이터는 개발·검증용이며 이중화하지 않습니다. 운영 데이터는 AWS에만 둡니다.
  • Redis 단일 인스턴스가 중단되면 대기열 항목이 사라질 수 있지만, 질문 상태의 기준은 DB이고 30초 넘은 PENDING 질문은 다시 대기열에 넣으므로 처리가 이어집니다 (API 명세 기준).

인증

역할별 IAM 최소 권한

아래는 역할별 권한 경계이며 실제 IAM 정책 적용 완료를 의미하지 않는다. 구체적인 작업 이름과 리소스 ARN은 계정·배포 방식 확정 후 작성한다.

역할 필요한 범위 제한 기준
클라우드 인프라 담당 프로젝트 네트워크·컴퓨트·데이터 자원의 생성·수정·조회 서비스별 지원 범위 내에서 프로젝트 리소스·태그·리전으로 제한. 모든 작업이 태그 조건을 지원한다고 가정하지 않음
백엔드 배포 지정 이미지 저장소와 앱 배포 대상 인프라·사용자 관리 권한과 분리. IAM 인증과 Kubernetes 배포 권한을 별도로 제한
프론트 배포 지정 S3 배포 경로 업로드, 지정 CloudFront 배포 무효화 다른 버킷·배포 접근 제외
앱 실행 선택한 AI 서비스 호출과 필요한 비밀값 읽기 등 모델·비밀값 등 필요한 리소스로 제한. 인프라 관리 권한 제외
조회·비용 확인 필요한 모니터링·비용 조회 변경 권한과 구분. 비용 정보 접근은 팀 계정 정책에 맞춰 부여

GitHub Actions OIDC는 해당 저장소·브랜치 또는 배포 환경으로 신뢰 조건을 제한한다. 사람 계정은 MFA를 적용한다. 정적 비밀값을 저장소에 올리지 않는다.

AWS·배포 권한 설계

  • 팀원별 로그인과 MFA, 업무에 필요한 최소 권한을 사용합니다.
  • 인프라 관리, 앱 배포, 프론트 배포, 앱 실행 권한을 분리합니다.
  • GitHub Actions는 OIDC 기반 단기 권한을 사용하며 신뢰 조건을 해당 저장소와 브랜치 또는 승인된 배포 환경으로 제한합니다.
  • API 키·DB 암호는 Git에 저장하지 않고 비밀값 저장소로 관리합니다.
  • 비공개 클러스터까지 접근 가능한 배포 실행 위치를 마련합니다. OIDC 인증만으로 내부 네트워크 접근이 가능해지는 것은 아닙니다.

온프레미스 (develop)

  • 비밀 값: AI·뉴스 API 키와 DB 비밀번호는 Kubernetes Secret으로 주입합니다.
  • 로그인 쿠키: 온프레미스는 HTTP로 서비스하므로 COOKIE_SECURE=false를 ConfigMap으로 주입합니다. 브라우저는 localhost 외의 HTTP 주소(VM IP)에서 Secure 쿠키를 저장하지 않기 때문입니다.
  • 배포 권한: self-hosted runner는 관리자 권한이 아닌 배포 전용 ServiceAccount(RBAC로 앱 네임스페이스만 허용)로 클러스터에 접근합니다.
  • 이미지 pull: GHCR 이미지가 비공개면 클러스터에 imagePullSecret을 등록합니다.
  • S3 백업: 온프레미스는 IAM 역할을 쓸 수 없으므로, 백업 버킷 업로드만 허용한 전용 IAM 사용자를 클라우드 담당과 설계합니다.

사용자 로그인·JWT 등 앱 인증 상세는 백엔드 담당 작성 예정입니다.

프론트엔드

AWS 도메인·HTTPS 구성

2026-10-12 프론트엔드 담당 제안을 반영합니다. 실제 도메인 이름은 클라우드 담당이 확정 후 입력합니다.

  • 화면: https://app.{도메인} → CloudFront → 비공개 S3.
  • API: https://api.{도메인} → ALB(HTTPS) → 앱 서버.
  • 두 주소는 같은 상위 도메인을 사용하고 Route 53에서 각각 CloudFront·ALB로 연결합니다. HTTPS를 공통으로 사용해 로그인 쿠키의 SameSite=Lax 조건에 맞는 같은 사이트 구성을 유지합니다.
  • 화면과 API는 같은 사이트이지만 서로 다른 출처이므로 CORS가 필요합니다. AWS API는 CloudFront의 /api/* 프록시를 거치지 않고 API 도메인으로 직접 호출합니다.

CORS·환경별 API 주소

  • 백엔드는 https://app.{도메인} 출처만 허용하고 credentials를 허용합니다. 쿠키 인증 요청에 와일드카드 출처(*)를 사용하지 않습니다.
  • 프론트는 쿠키 포함 요청(credentials: include 또는 Axios withCredentials: true)을 사용합니다.
  • 화면은 api.js에서 환경별 API 주소를 사용합니다: 온프레미스 /api, AWS https://api.{도메인}. /api 경로가 중복되거나 빠지지 않도록 실제 엔드포인트 조합은 API 명세에 맞춰 연결합니다.

인증서와 담당

  • app.{도메인}용 CloudFront 인증서는 ACM의 us-east-1에서 발급합니다.
  • api.{도메인}용 ALB 인증서는 ALB를 배치하는 리전에서 발급합니다. ALB가 서울이면 서울 리전 인증서를 사용합니다.
  • 클라우드 담당: 도메인 이름 확정, Route 53 연결, 인증서 발급·검증·연결.
  • 프론트 담당: api.js 환경별 주소 분리 및 쿠키 포함 요청 적용.
  • 백엔드 담당: CORS·로그인 쿠키 설정. 운영 쿠키의 Secure·HttpOnly·SameSite=Lax와 실제 로그인 동작을 검증합니다.

SPA 경로 처리

  • CloudFront는 화면 파일만 제공하며 403/404를 /index.html로 반환하는 SPA 설정은 화면 배포에만 적용합니다.
  • API 오류 응답은 HTML로 치환하지 않습니다. 정적 파일 누락 오류까지 숨겨지지 않는지도 배포 시 확인합니다.
  • 온프레미스: Nginx 컨테이너를 Ingress / 경로로 노출하고 /api/*는 백엔드로 프록시합니다. SPA 경로는 /api/*를 제외하고 index.html로 연결합니다.

CI/CD

운영 배포 계획: main 변경 → 테스트 → 버전 고정 이미지 빌드·저장 → 운영 앱 배포 → 헬스체크. 실패 시 직전 정상 이미지로 복귀합니다. 개발·운영 분기와 이미지 저장소, 실행기 위치, 승인 규칙은 관련 담당과 확정 예정입니다.

구현 절차는 별도 배포 가이드에 기록합니다. 현재 자동 배포가 구축된 상태는 아닙니다.

온프레미스 (develop)

develop 변경 → 테스트 → 이미지 빌드 → GHCR에 커밋 SHA 태그로 push → control plane VM의 self-hosted runner가 클러스터에 적용 → kubectl rollout status로 확인, 실패 시 팀 채널 알림.

  • 온프레미스 VM은 외부에서 접근할 수 없으므로, 클러스터 안의 runner가 GitHub에서 작업을 받아오는 방식을 사용합니다.
  • 브랜치·승인·롤백 정책은 배포 가이드를 따릅니다.

리소스 태그

초기 태그 제안은 Project=likelion-team01, Owner=chaneee93, Environment=practice, ManagedBy=console입니다. Owner는 실제 담당자, ManagedBy는 실제 관리 방식에 맞춥니다. 팀 공통 값은 적용 전에 확정합니다. 비용 분류에 사용할 태그는 비용 할당 태그 활성화 여부도 확인하며, 태그만으로 접근 권한이 통제되는 것은 아닙니다.

IaC (Terraform)

아래는 5주차 코드화 대상이며 실제 모듈 구현 전입니다.

모듈(제안) 역할
network VPC, 서브넷 6개, IGW, AZ별 NAT 2개, 라우팅
compute EKS, 관리형 작업 노드 그룹, 관련 보안 그룹
data RDS Multi-AZ, Redis 복제 그룹, 데이터 접근 규칙
identity OIDC, 배포·앱 실행 역할과 최소 권한
frontend S3·CloudFront, 프론트 담당과 관리 범위 협의

실습 시간에 서비스 운영을 계획합니다. 종료·재생성 대상과 영구 데이터·백업·Terraform 상태 보관 대상을 분리하고, 실제 종료 절차는 구축 후 검증합니다.

  • 온프레미스 VM은 Terraform 대상이 아니며, 설치 절차를 문서와 스크립트로 관리합니다. 앱 배포는 5주차부터 온프레미스와 EKS가 같은 Helm 차트를 values 파일만 바꿔 사용합니다.

모니터링

클라우드 측 관찰 대상은 ALB 정상 대상·응답 오류, 노드·파드 상태, DB 연결·장애 전환, Redis 복제·큐 길이, API·워커 처리 시간입니다. 도구·대시보드·알림 구성은 온프레미스 및 백엔드 담당과 협의 예정입니다.

온프레미스 (develop)

  • 4주차부터 kube-prometheus-stack(Prometheus + Grafana)을 설치합니다.
  • 관찰 대상: 노드·파드 자원, 앱 메트릭(/actuator/prometheus, 클러스터 내부 수집), 응답 시간·5xx 에러율, 캐시 적중률, 대기열 길이, 백업 성공 여부.
  • 클라우드와 같은 대시보드를 쓸 수 있도록 지표 이름과 패널 구성을 공유하는 방향으로 협의합니다.

실측 검증 결과 요약

아직 구축 전이므로 실측값이 없습니다. 4주차 기준값 및 6주차 개선 결과를 측정 후 기입합니다.

시나리오 부하 실패율 p95 응답시간
측정 후 작성 미측정 미측정 미측정

예정 검증: A/B 앱 분산, AZ 한쪽 앱 중단 시 ALB·잔여 앱의 외부 통신, RDS·Redis 장애 전환 후 재연결, 백업 복원, HPA·KEDA 확장. 상세 절차는 장애 시나리오·성능 테스트 문서에서 관리합니다.

온프레미스 예정 검증: 워커 노드 다운 시 파드 재배치, etcd 스냅샷 복구, MySQL 백업 복원, 온프레미스와 클라우드 복구 시간 비교.

알려진 한계

  • 팀 검토 전 설계안이며 실제 계정·리전·버전·서버 크기·연결 상세는 미정입니다.
  • 4주차 kubeadm 제어 노드 1대는 단일 장애 지점입니다. NAT·데이터 이중화만으로 클러스터 전체 고가용성이 완성되지는 않습니다.
  • AZ 장애 시 남은 앱 용량과 재연결 동작을 검증해야 합니다. 장애 전환 중 일시 중단 가능성이 있습니다.
  • Redis 복제는 비동기이므로 작업 유실·중복 처리 방지 설계가 별도로 필요합니다.
  • 이 문서는 클라우드 설계 중심이며 온프레미스 상세·앱 인증·화면 설계는 각 담당이 보완합니다.
  • 온프레미스 control plane도 1대라 단일 장애 지점입니다. control plane 장애 시 클러스터 관리가 멈추지만 실행 중인 파드는 유지됩니다.
  • 온프레미스는 노트북 1대에서 실행되므로, 노트북이 꺼지거나 절전에 들어가면 개발 환경과 self-hosted runner가 함께 멈춥니다. 호스트는 전원 연결 시 절전을 해제해 운영합니다.
  • 온프레미스에는 클라우드 로드밸런서가 없어 Ingress를 NodePort로 노출합니다.
  • 온프레미스는 HTTP로 서비스하므로 운영과 쿠키 보안 설정(COOKIE_SECURE)이 다릅니다.

참고 자료

계정 설정·네트워크 실행 절차 및 진행 상태는 계정 보안·예산 이슈 #26과 네트워크 구성 이슈 #27에서 관리합니다.

Clone this wiki locally