[AWS] AWS 아키텍처 #15

­박찬영·2025년 2월 23일

AWS

목록 보기
15/15
post-thumbnail

📌 AWS 서비스 정리하기


  • 클라우드 컴퓨팅(Cloud Computing) : 인터넷을 통해 IT 리소스와 애플리케이션을 원할 때 사용하고, 사용한 만큼 요금을 지불하는 서비스

  • EC2(Elastic Compute Cloud) : 컴퓨팅 자원(Virtual Machine)을 클라우드로 제공하는 가상 서버 서비스

    • Elastic IP(Elastic IP Address) : 클라우드 컴퓨팅을 위한 정적 IPv4 주소, EC2 인스턴스에 연결 가능 (클라이언트에 접속하는 IP 주소의 변경 없이 서버의 장애 극복)

    • Security Group(보안 그룹) : 인스턴스에 대한 트래픽을 제어하는 가상의 방화벽 역할

  • ELB(Elastic Load Balancing) : Load Balancing을 위해 리전에 존재하는 서비스, 부하를 대상 그룹(Target Group)에 속한 EC2 인스턴스에게 분산

    • Load Balancing : 부하(트래픽)를 여러 대의 서버로 분산시켜 처리하는 것 (성능과 안정성 향상, 서버의 장애 예방에 기여)

    • 리스너(Listener) : 프로토콜과 포트를 기반으로 외부의 요청을 적절한 타겟으로 전달

  • Auto Scaling : 트래픽에 따라 자동으로 서버(EC2 인스턴스)의 개수를 조절해주는 기능 (서비스의 안정적 제공과 효율적인 서버 운영)

    • Auto Scaling이 생성하는 EC2 인스턴스의 사전 정보는 시작 템플릿으로 설정 (AMI 사용 가능)

    • AMI(Amazon Machine Image) : 인스턴스를 실행하기 위한 정보를 모은 단위로, OS가 설치된 형태의 이미지(템플릿) 파일 (AMI로 EC2 인스턴스를 생성하고 실행 가능)

    • Auto Scaling Group(ASG) : 가용 영역을 ELB의 대상 그룹(Target group)과 동일하게 설정, ELB는 Auto Scaling으로 생성된 EC2 인스턴스에 부하를 분산

  • Lambda : 서버리스 컴퓨팅 서비스, 특정한 주기 혹은 트리거에 의해 간단한 코드를 실행할 때 사용

    • Lambda 트리거 : 람다 함수를 실행할 수 있는 이벤트로 (S3, API Gateway, DynamoDB 등)

  • EBS(Elastic Block Store) : EC2에 연결(attach)하여 쓸 수 있는 블록 스토리지

    • 볼륨(Volume) : EBS의 가장 기본적인 형태 (단, 한 개의 EBS에 여러 개의 EC2 인스턴스 연결 불가)

    • 스냅샷(Snapshot) : 볼륨의 특정 시점을 그대로 복사하여 저장한 파일, 스냅샷을 이용해 볼륨을 생성하거나(특정 시점의 데이터 복구) AMI를 생성

  • S3(Simple Storage Service) : 객체 기반의 파일 저장 스토리지 (데이터의 일부분만 수정이 불가능한 대신 확장성이 높고 안전하게 파일을 저장 가능)

    • Bucket(버킷)을 생성하고 파일을 업로드한 다음 Object(객체)의 권한을 설정하여 HTTP로 파일을 다운로드 가능

    • URL을 통해 파일을 공유하고 정적 웹사이트를 호스팅 가능, 데이터 백업에도 적합

  • RDS(Relational Database Service) : 관계형 데이터베이스 서비스, 데이터베이스를 여러 대 복제하는 Replication을 기반으로 함

    • Master DB(Primary DB) & Standby DB (장애가 발생하면 Standby DB로 읽기와 쓰기 작업을 진행하는 Failover를 수행) & Read Replica (읽기 전용으로 만들어진 복제본)

    • 다중 AZ(Multi-AZ) : 단일 지역의 2개 이상의 가용 영역에 걸쳐 데이터베이스를 구축하는 것

    • Master DB 인스턴스를 만들고 다중 AZ 배포로 변환하여 Standby DB를 만든 다음, 다른 리전에 Read Replica를 생성

    • EC2 인스턴스가 RDS를 사용하게 하려면 EC2 인스턴스의 설정 파일과 RDS의 보안 규칙을 변경 (Auto Scaling이 설정되어 있다면 AMI, 시작 템플릿도 변경)

  • DynamoDB : 완전 관리형 클라우드 NoSQL 데이터베이스 (스키마가 없는 데이터 모델에 최적화)

    • 기본 키(Primary Key) : 단순 기본 키(파티션 키)와 복합 기본 키(파티션 키 + 정렬 키)

    • 파티션 키(Partition Key) : 데이터가 저장되는 파티션을 결정

    • 정렬 키(Sort Key) : 동일한 파티션 내의 항목을 정렬

    • 보조 인덱스 : 글로벌 보조 인덱스(Global Secondary Index)(전체 테이블), 로컬 보조 인덱스(Local Secondary Index)(파티션 내)

    • 데이터 조회 : 키 기반으로 Query 혹은 전체 데이터를 가져와 필터링하는 Scan


  • CloudFront : CDN 역할의 서비스로, 캐싱을 통해 콘텐츠를 빠르게 전송할 수 있게 함

    • 기본 단위는 배포(Distribution)

    • CloudFront로 S3 Origin에서 원본 파일을 가져오려면 S3 버킷 정책을 수정

  • Route 53 : DNS 시스템, 도메인 이름을 IP 주소로 바꿔줌

    • 레코드의 컨테이너인 호스팅 영역(Hosted Zone)을 먼저 만들어준 다음 레코드를 생성
  • CloudWatch : 클라우드 모니터링 서비스

    • 로그 데이터 및 지표를 모니터링

    • 경보 기능으로 조건에 따라 알람을 전달

  • IAM (Identity and Access Management) : AWS 리소스에 대한 권한을 관리하는 서비스

    • IAM 사용자를 추가하여 권한(Role)을 제한적으로 부여 가능

    • IAM 그룹을 생성하여 그룹에 속한 사용자에게 특정 권한을 부여 가능

  • AWS SDK(Software Development Kit) : 애플리케이션에 AWS를 연동하기 위한 개발 도구의 집합

  • AWS CLI(Command Line Interface) : 명령행 도구

    • Shared Credentials(공유 자격 증명)을 설정하여 SDK, CLI를 통해 AWS 서비스 사용 가능


📌 AWS 미니 프로젝트



Step 1. EC2 인스턴스 생성하기

  • Ubuntu 인스턴스 생성SSH 접속

  • Node.js 설치설치 방법

    • sudo apt-get install -y curl

    • curl -fsSL https://deb.nodesource.com/setup_23.x -o nodesource_setup.sh

    • sudo -E bash nodesource_setup.sh

    • sudo apt-get install -y nodejs

    • node -v

  • Express 설치 (Node.js 웹 애플리케이션 프레임워크)

    • sudo mkdir project

    • sudo chown ubuntu:ubuntu project/ (폴더의 소유자 변경)

    • cd projectnpm init -y

    • npm install express

  • Vim 환경 설정

    • vim ~/.vimrc

      set autoindent
       set ts=4
       set shiftwidth=4
       set nu


Step 2. 보안 그룹 설정하기

  • project/index.js 작성

    const express = require('express');
     const PORT = 3000;
    
     const app = express();
    
     app.get('/', (req, res) => {
       res.send("Hello, World!");
     });
    
     app.listen(PORT, () => {
       console.log(`Listening on port ${PORT}...`);
     });
  • node index.js 실행 후 <퍼블릭 IPv4 주소>:3000으로 접속



Step 3. 이미지 파일 업로드 API 만들기

  • 기존 폴더 삭제

    • cd ~rm -r project
  • 프로젝트 기본 구조 만들기

  • 프로젝트 폴더 소유자 변경

    • sudo chown -R ubuntu:ubuntu project/
  • 패키지 설치

    • cd projectnpm install
  • 서버 시작

    • npm start


  • multer 설치 및 사용하기 (API 작성)

    • npm install multer

    • 파일 복사 cd routescp users.js images.js

    • vim images.js로 파일 수정

    
    const express = require('express');
    const fs = require('fs');
    const path = require('path');
    const multer = require('multer');
    
    const router = express.Router();
    
    const upload = multer({
      dest: path.join(__dirname, '..', 'uploads')
    });
    
    router.get('/', (req, res, next) => {
      res.send('respond with a resource');
    });
    
    router.post('/', upload.single('new-image'), (req, res, next) => {
      console.dir(req.file);
      res.send();
    });
    
    module.exports = router;

  • Router 등록

    • cd ..vim app.js로 파일 수정


  • HTML 파일 수정하기

    • cd viewsvim index.ejs로 파일 수정

    • Bootstrap

    • jQuery

      • <script src="https://blueimp.github.io/jQuery-File-Upload/js/jquery.fileupload.js" crossorigin="anonymous"></script> 추가

      • input 태그에 name="new-image" 속성 추가

    • ④ 최하단에 jQuery 코드 추가

    <script>
       $(function () {
         $('#file-upload').fileupload({
           url: '/images',
           dataType: 'json',
           progressall: function (e, data) {
             var progress = parseInt(
               (data.loaded / data.total) * 100,
               10
             );
             $('#progress .progress-bar').css(
               'width',
               progress + '%'
             );
           },
         });
       });
     </script>
    • 완성 코드 참고

    • npm start으로 서버를 실행하고 이미지를 업로드하면 로그 확인 가능



Step 4. S3 버킷 연결하기 (AWS SDK for JavaScript)

  • S3 버킷 생성하기


  • 공유 자격 증명 설정하기


  • AWS SDK for JavaScript 설치하기

    • npm install @aws-sdk/client-s3
  • S3 연결하기

    • routes 폴더에서 vim images.js 실행, 아래와 같이 코드 수정
    
    const express = require('express');
    const fs = require('fs');
    const path = require('path');
    const multer = require('multer');
    
    const router = express.Router();
    
    const upload = multer({
      dest: path.join(__dirname, '..', 'uploads')
    });
    
    const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
    const s3Client = new S3Client({ region: 'ap-northeast-2' });
    
    router.get('/', (req, res, next) => {
      res.send('respond with a resource');
    });
    
    router.post('/', upload.single('new-image'), (req, res, next) => {
      console.dir(req.file);
      fs.readFile(req.file.path, (err, data) => {
        s3Client.send(
          new PutObjectCommand({
            Bucket: '버킷 이름',
            Key: req.file.filename,
            Body: data,
            ContentType: req.file.mimetype,
          })
        )
        .then((data) => {
          console.log(data);
          res.send(data);
        })
        .catch((error) => {
          console.log(error);
        });
      });
    });
    
    module.exports = router;
    • 서버 시작 npm start 후 이미지를 업로드하면 S3 버킷에 업로드됨



Step 5. CloudFront로 S3 파일 보여주기

  • CloudFront 배포 생성 및 정책 편집

    • 도메인 복사해두기


  • API 코드 수정

    • routes 폴더에서 vim images.js 실행, 아래와 같이 코드 수정 (객체 최대 50개 읽어옴)
    
    const express = require('express');
    const fs = require('fs');
    const path = require('path');
    const multer = require('multer');
    
    const router = express.Router();
    
    const upload = multer({
      dest: path.join(__dirname, '..', 'uploads')
    });
    
    const { S3Client, PutObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
    const s3Client = new S3Client({ region: 'ap-northeast-2' });
    
    router.get('/', (req, res, next) => {
      s3Client.send(
        new ListObjectsV2Command({
          Bucket: '버킷 이름',
          MaxKeys: 50,
        })
      )
      .then((data) => {
        res.send(data.Contents);
      })
      .catch((error) => {
        console.log(error);
      });
    });
    
    router.post('/', upload.single('new-image'), (req, res, next) => {
      console.dir(req.file);
      fs.readFile(req.file.path, (err, data) => {
        s3Client.send(
          new PutObjectCommand({
            Bucket: '버킷 이름',
            Key: req.file.filename,
            Body: data,
            ContentType: req.file.mimetype,
          })
        )
        .then((data) => {
          console.log(data);
          res.send(data);
        })
        .catch((error) => {
          console.log(error);
        });
      });
    });
    
    module.exports = router;
    • 서버 시작 npm start<퍼블릭 IPv4 주소>:3000/images로 접속


  • HTML 파일 수정

    • views 폴더에서 vim index.ejs 실행

    • <div id="image-list"></div> 추가

    • 최하단에 jQuery 코드 추가

    <script>
       $.getJSON('/images', function (data) {
         $.each(data, function (i, e) {
           const img = $('<img>');
           img.attr(
             'src',
             '<CloudFront 배포 도메인 이름>/' + e.Key
           )
           .attr({ width: '200px', height: '200px' })
           .addClass('img-thumbnail');
           
           $('#image-list').append(img);
         });
       });
     </script>
    • 서버 시작 npm start<퍼블릭 IPv4 주소>:3000로 접속



Step 6. ELB Load Balancer 설정하기

  • pm2 설치 (Node.js용 프로세스 매니저)

    • sudo npm install pm2 -g

    • 프로젝트 폴더에서 pm2 start ./bin/www

    • 애플리케이션 상태 확인 pm2 show www

    • 서버 부팅 시 자동 시작 설정 : pm2 startup 명령어를 실행하면 나오는 명령어를 복사하여 실행

    • 프로세스 목록 저장 pm2 save

    • dump 파일 내용 확인 cat ~/.pm2/dump.pm2

      • "pm_exec_path"에 실행 경로가 들어가있음
    • EC2 인스턴스 재부팅 후 애플리케이션이 잘 구동되는지 확인

  • ELB Load Balancer 설정하기

    • ELB Load Balancer 생성

      • Application Load Balancer 선택

      • EC2 인스턴스가 존재하는 가용 영역 포함

      • 대상 그룹에 인스턴스 등록 (포트 번호 3000번으로 설정)

      • ELB 생성 후 3000번 포트 리스너 추가

    • DNS 이름의 3000번 포트로 접속



Step 7. Auto Scaling 설정하기

  • AMI 생성하기

  • Auto Scaling Group 생성하기

    • 시작 템플릿 생성 필요

      • ELB의 대상 그룹(Target Group)과 동일하게 가용 영역을 설정

      • S3에 접근할 수 있도록 IAM 권한 설정

  • DNS 이름의 3000번 포트로 접속하면 최종적으로 잘 실행됨


🔧 Trouble Shooting

  • Problem : Auto Scaling 이후, DNS 이름의 3000번 포트로 접속했을 때 이미지가 나오기도 나오지 않기도 하는 문제점 발생

  • Examination : 생성된 EC2 인스턴스에서 이미지를 GET, POST하는 요청만이 되지 않는 상황이므로 S3 권한과 관련된 문제

    • 두 개의 EC2 인스턴스에서 pm2 monit 명령어로 로그를 관찰한 결과 credentials에 대한 문제임을 확인

  • Solution : 시작 템플릿에 IAM 권한(S3 접근 권한)이 포함되지 않은 것으로, AMI를 생성할 때 IAM 권한이 포함되도록 해야 했음




참고 자료
소플의 처음 만난 AWS

profile
Develop하는 개발자

0개의 댓글