본문 바로가기
Cloud/AWS

Storage Service

by 황밤 2023. 10. 25.
728x90
반응형

1. AWS 백업

 

1.1) 백업의 형태

  • 온프레미스 환경의 데이터를 AWS 백업
  • AWS에 구축한 시스템을 백업

1.2) 백업의 개요

  • 사내 시스템은 온프레미스 환경에 위치하고 기업의 사이트는 AWS 환경에 위치
  • 용량이 큰 이미지 파일, 데이터 베이스, 각 서버의 로그 파일, 파일 서버에 있는 파일이 백업 대상
  • 로그 파일과 데이터베이스는 장기간 보관
  • 비용을 절감하면서도 운영에 손이 많이 가지 않는 방식으로 진행

1.3) 인프라 설계

  • 스토리지 게이트웨이를 이용한 자동 백업 : 온 프레미스 환경에 스토리지 게이트웨이를 사용하여 백업용 스토리지를 만들어 S3에 자동 백업
  • S3 와 글레이셔를 이용한 수명 주기 관리 : 로그 파일을 보관할 때 일반적으로는 S3의 기능으로 백업을 하고 온라인 보관 기간을 넘은 파일은 글레이셔에 아카이브
  • 용량의 대부분을 차지하는 이미지 파일과 데이터베이스는 S3에 백업 : 스크립트를 이용해서 백업

2. On-Premise 환경의 데이터 백업

2.1) 일반적인 방법

  • 오브젝트 스토리지 서비스인 S3 를 명령행 인터페이스를 통해 이용하는 패턴
    관리형 콘솔을 이용하지 않음
  • 가상 서버인 EC2 와 가상 스토리지 인 EBS 로 구축한 백업용 서버에 데이터를 동기화시키는 방법
    S3 보다 비용이 증가하나, 백업을 유연하게 할 수 있음
    EC2에 에플리케이션을 만들어서 실행시키면 온라인 백업을 자유롭게 할 수 있음.
  • AWS 스토리지 게이트웨이 이용
    온프레미스 환경과 AWS를 전용 소프트웨어를 이용해서 직접 연결시키는 방법
    가장 쉬운 방법이지만 비용이 가장 많이 소모
  • 최근에는 높은 추상화(개발자는 알고리즘 개발에만 신경쓰고 나머지 작업은 이미 구성된 소프트웨어가 있으면 그것을 이용)를 이용하는 방식을 권장

2.2) S3 로 파일 백업

  • AWS CLI를 이용해서 백업 : 30여가지가 넘는 리눅스 명령어
  • 언어별 API를 이용해서 백업
  • cron 이나 작업 스케쥴러를 제공
  • S3 는 인바운드 전송은 무료이고 온프레미스에 대한 전송이 유료
  • 라이프 사이클 설정 가능 - 일정 기간이 지나면 삭제하도록 할 수 있음
  • 서버 사이드 암호화를 제공
    파일이 업로드 될 때는 평문으로 업로드 되지만 저장이 될 때 암호화를 적용하고 꺼낼 때 복호화를 수행
    전송 도중 암호화를 하고자 하는 경우 암호화 소프트웨어나 암호화 알고리즘을 적용해야 함

2.3) EC2 로 파일 백업

  • EBS 스토리지 이용
  • 별도의 애플리케이션을 제작해서 활용하는 것이 가능

2.4) AWS 스토리지 게이트웨이 이용

  • AWS 가 제공하는 소프트웨어를 이용

2.5) 3rd Party 제품 사용

  • MSP 나 DSP의 제품을 이용
  • CSP 는 인프라를 제공하는 기업 (Amazon, MS, Google)

3. 백업 파일 보관

  • AWS에서는 아카이브용 스토리지 서비스인 아마존 글레이셔라는 서비스를 제공
  • 자주 사용하지 않고 오랫동안 보관해야 하는 데이터를 보관하는데 적합
  • 비용은 S3에 비해 1/5 ~ 1/10 정도이며 엑세스 하는데 3~ 5 시간이 소요 ( 압축 해제 필요 )
  • S3 에 정책 설정을 하면 일정 기간 지날시 글레이셔로 이동하도록 지정 가능

4. AWS 와 온프레미스 환경에 전용선 연결 가능

  • 인터넷 VPN을 이용

5. 파일 서버로 AWS 를 이용

  • 파일을 공유하거나 콘텐츠 관리 기능이 요구되는 경우 사용
  • 직접 파일 서버를 구축하고자 하면 비용이 발생
  • 관리형 파일 서버를 이용하고자 하는 경우에는 EFS 라는 서비스를 이용하는 것을 권장
    S3 는 HTTP나 HTTPS 서비스를 이용해서 접근
    NFS를 이용하는 파일 관리 보다는 S3는 느림
  • 워크 독스를 이용한 파일 공유도 가능

6. S3

6.1) 개요

  • Simple Storage Service 는 인터넷 스토리지 서비스
  • 용량에 관계없이 파일을 저장할 수 있고 웹에서 파일에 접근할 수 있으며 안정성이 뛰어나 가용성이 높고 무제한 확장이 가능
  • 정적 웹 호스틍(html, css, js 로만 구성된 웹 애플리케이션) 가능

    S3 자체가 수천 대 이상의 성능이 좋은 웹 서버로 구성되 있어서 자동 횡적 확장(Auto Scailing) 이나 부하 분산(Load Balancing)을 신경 쓰지 않아도 됨

    Docker로 만들 떄 nginx 를 앞에 달아서 Load Balancing을 하거나 Kubenetes의 replicaset을 이용해서 자동 횡적 확장을 할 필요가 없음.

  • 동적 웹 처리 부분과 정적 웹 서비스 부분이 있다면 이를 분리해서 구현을 하고 동적 웹 처리 부분은 컨테이너나 EC2를 이용해서 배포를 하고 정적 웹 서비스 부분은 S3를 이용하는 것이 가능

 

6.2) 개념

  • 객체
    • S3에 저장되는 단위
    • 파일과 메타 데이터로 구성
    • Key 가 객체의 이름이고 Value 가 실제 데이터
  • bucket
    • S3 에서 만들 수 있는 최상위 디렉토리
    • 리전 별로 생성되며 계정 별로 100개 까지 생성 가능
    • 버킷 안에 객체가 저장되고 디렉토리 생성 가능(객체의 이름은 디렉토리 이름을 포함)
    • 저장 가능한 객체의 개수와 저장 가능한 용량은 무제한
    • URL로 접근이 가능
  • 내구성 : 데이터가 유실되지 않는 성질 - 1년 99.999999999% 의 내구성
  • 가용성 : 언제나 정상적으로 사용 가능한 상태 - 1년 기준 99.99%

 

  • S3 서비스는 내구성을 기준으로 2가지 Storage 제공
    • 복제본의 개수를 다르게 해서 내구성을 유지
  • 요금 개념은 저장 용량과 데이터 다운로드 량과 HTTP 요청 개수로 책정

 


7. 버킷 생성

 

7.1) 버킷을 외부 애플리케이션에서 사용하고자 하면 사용자를 등록해야 합니다.

  • IAM 사용자를 등록해서 키를 받아야 함.
- AWS 서비스에서 IAM 으로 이동해서 사용자 이름 과 권한을 생성
- 키 발급 받기  IAM 콘솔을 열어서 사용자를 클릭하고 Access Key 만들기를 누르고 외부에서 실행되는 애플리케이션을 선택하고 만들기

7.2) 버킷을 생성

  • S3 버킷에 접속
  • 버킷 만들기를 누르고 버킷 이름을 작성하고 퍼블릭 접근 차단을 해제
  • 버킷 이름과 리전 그리고 이전에 생성한 Access key를 이용해서 접속 가능

7.3) 권한을 설정

  • 버킷 자체에 대한 권한 설정
    • 버킷 정책에 추가 : 목록 가져오기와 가져오기, 업로드 및 삭제 권한 부여
    • 버킷 이름과 권한만 수정해서 작성하면 됩니다.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicListGet",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:List*",
                "s3:Get*",
                "s3:Put*",
                "s3:Delete*"
            ],
            "Resource": [
                "arn:aws:s3:::adamsoft",
                "arn:aws:s3:::adamsoft/*"
            ]
        }
    ]
}

 

  • CORS 권한 설정 - 웹 브라우저에서 구동되는 프로그램은 자신의 로컬 서버 이외의 요청이 안되는데, 이를 허용해주는 설정
    • react 에서 작업을 하고자해서 localhost:3000 을 허용했는데, 실제 배포가 이루어지면 배포된 도메인으로 수정을 해주어야 합니다.
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "http://localhost:3000"
        ],
        "ExposeHeaders": []
    }
]

7.4) 정적 웹 호스팅을 하고자 하는 경우

  • 정적 웹 호스팅 설정을 열어주어야 합니다.

 


8. Django 에서 S3에 파일 업로드 및 다운로드

 

8.1) 로컬에 파일을 업로드

  • python 가상환경 생성
python -m venv myvenv

window
cd myvenv
cd Scripts
activate

-mac
source venv/bin/activate
  • 필요한 패키지 설치
    • django, mysqlclient, Pillow(이미지 파일을 데이터베이스에 활용하고자 할 때 설치), django-bootstrap4
  • django 프로젝트 생성
django-admin startproject {프로젝트이름} .
  • django 애플리케이션 생성
cd myproject
python manage.py startapp fileupload

 

  • settings.py 파일을 수정
    • 실행될 서버의 IP : ALLOWED_HOSTS = ["0.0.0.0""127.0.0.1"]
    • 앱 등록

 

  • INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        "fileupload",
        "bootstrap4",
    ]​
  • 데이터베이스 설정
  • DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'itbam',
            'USER' : 'itbam',
            "PASSWORD" : "tj1",
            "HOST" : "aram",
            "PORT" : "3306"
    
        }

 

  • 화면을 만들기 위해서 보여지는 템플릿 엔진 파일이 위치할 디렉토리를 생성 - 애플리케이션 안에 templates 디렉토리
  • 업로드된 파일이 저장될 디렉토리를 생성 - 최상위 디렉토리에 생성하는데 이름은 media
  • 모델 설정 : 엔티티 설정
from django.db import models

# Create your models here.

class FileUpload(models.Model):
    title = models.TextField(max_length=40, null=True)
    imgfile = models.ImageField(null=True, upload_to="", blank=True)
    content = models.TextField()

    def __str__(self):
        return self.title
  • 마이그레이션 : Model 클래스의 변경 내용을 데이터베이스에 반영
python manage.py makemigrations

python manage.py migrate

 

데이터를 표현하는 클래스 - Domain Class
- Entity : 데이터베이스의 테이블과 직접 연결되는 클래스로 이 클래스는 Service 계층과 Repository 에서만 사용해야 합니다.

- DTO : Data Transfer Object 의 약자로 계층 간의 데이터 이동에 사용합니다.
여러 계층에서 동일한 모양의 데이터를 사용할 때는 DTO를 만들어야 합니다.

- VO : Value Object 의 약자로 여러 개의 데이터를 묶기 위한 목적으로 현재 계층에서만 사용하는 객체

데이터베이스 연동 방식
=> 데이터베이스 드라이버를 직접 조작하는 방식 : 직접 코딩

=> SQL Mapper 방식의 프레임워크를 이용하는 방식 : SQL 과 소스 코드의 분리

=> ORM(Object Relation Mapping) : 데이터베이스의 하나의 행을 인스턴스로 표현해서 인스턴스를 조작하면 데이터베이스에 반영이 되는 방식
Class 가 Table(Schema)이 되고 Instance 가 Row(Tuple) 가 되는 방식입니다.
대다수의 ORM은 속도 때문에 연결된 구조를 갖는 경우가 많습니다.
Class 를 Entity Class 라고 하며 이 클래스의 객체들은 프레임워크가 관리(IoC - Inversion of Control : 제어의 역전)

기본적으로 프레임워크를 사용하는 방법은 프레임워크가 클래스를 제공하고 개발자가 인스턴스를 만들어서 사용한 후 관리하는 방식인데 클래스를 개발자가 만들고 그 클래스의 인스턴스를 프레임워크가 관리하는 형태를 제어가 역전되었다고 해서 IoC 라고 합니다.

 

from django.forms import ModelForm
from .models import FileUpload

class FileUploadForm(ModelFrom) :
    class Meta :
        model = FileUpload
        fields = ['title', 'imgfile', 'content']
  • 요청을 처리(Service 계층)할 함수를 소유하는 views.py 파일을 수정
def fileUpload(request):
    if request.method == 'POST':
        title = request.POST['title']
        content = request.POST['content']
        img = request.FILES["imgfile"]
        fileupload = FileUpload(
            title=title,
            content=content,
            imgfile=img,
        )
        fileupload.save()
        return redirect('fileupload')
    else:
        fileuploadForm = FileUploadForm
        context = {
            'fileuploadForm': fileuploadForm,
        }
        return render(request, 'fileupload.html', context)
  • 화면 출력에 공통으로 사용할 base.html 파일을 templates 디렉토리에 생성
  • 실제 업로드 화면으로 사용할 fileupload.html 파일을 templates 디렉토리에 생성
{% load static %}
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
</head>
</html>

 

{% extends 'base.html' %}
{% load static %}
{% load bootstrap4 %}
{% block content %}
<div class="container">
    <form method="POST" action="{% url 'fileupload' %}" enctype="multipart/form-data">
        {% csrf_token %}
        {% bootstrap_form fileuploadForm %}
        <input type="submit" class="btn btn-primary col-12" value="제출">
    </form>
</div>
{% endblock%}
StyleSheet 나 JavaScript 의 경우 위 변조를 확인하는 방법을 integrity를 사용

클라이언트에서 파일을 전송하고자 할 때 form 을 사용하는 경우는 enctype을 반드시 multipart/form-data 로 설정해야 합니다.

클라이언트에서 서버로 폼을 전송할 때 되도록이면 csrf_token을 설정해야 합니다.
이 폼을 전송받은 클라이언트를 증명하기 위한 token 값
이 값이 사용되지 않으면 다른 곳에서 url을 복사하거나 자바스크립트를 이용해서 임의로 데이터를 전송하는 것이 가능

{% bootstrap_form fileuploadForm %}
장고나 스프링 같은 프레임워크 들은 폼을 자동 생성하는 기능이 있어서 모델을 기반으로 폼을 만들어두고 html에서 불러다 사용할 수 있습니다.
id, name 그리고 유효성 검사 기능이 자동으로 설정됩니다.
클라이언트에서 name을 이용해서 서버에게 전송하는데 이름을 직접 설정하면 실수를 많이 하기 때문

static : 정적 파일 중 화면 출력과 관련된 파일 - html, css, javascript 등

media : 정적 파일 중에서 리소스에 해당하는 파일 - 이미지 파일 등

s3 에 저장하는 내용이 업데이트 인지 아니면 새로 추가하는 것인지 ?

모델을 만드는 서비스 - 모델을 생성 - 모델을 저장 -> 다른 곳에서 가져가서 서비스

덮어씌우지 않도록 할려면 중복될 가능성이 없는 문자열을 파일 이름으로 부여
한가지 방법은 uuid 를 사용하는 방법
타임스탬프를 이용 : 로드 밸런싱이 된 경우는 주의
id 별로 디렉토리를 별도로 생성해서 timestamp 이용

 

  • urls.py 파일에 url 과 views 의 메서드를 연결 - Controller의 역할
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

# fileupload/urls.py
from django.urls import path
from fileupload import views

urlpatterns = [
	path('fileupload/', views.fileUpload, name="fileupload"),
]
  • 로컬에서 파일을 업로드 하기 위한 작업
import os
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

 

 

  • 애플리케이션을 실행하고 fileupload 에 접속해서 파일을 선택해서 업로드 한 후 media 디렉토리 확인
python manage.py runserver [0.0.0.0:포트번호] - 배포할 때는 이 명령

데이터 베이스도 확인 - 동일한 이름의 파일을 업로드 했을 때 내용 확인 - django는 동일한 이름의 파일을 업로드 하면, 2번째 파일의 이름을 수정함.

 

 

 

8.2) S3에 업로드하고 다운로드

  • 로컬 컴퓨터에 파일을 저장했을 때 문제점
로컬 컴퓨터 안의 프로젝트 디렉토리에만 저장할 수 있습니다.
파일을 저장할 때는 절대 경로가 필요한데 현재 컴퓨터의 절대 경로를 설정하면 이 코드를 다른 곳에서 실행할 때 경로를 수정해야 합니다.
TOMCAT 과 같은 WAS 를 이용할 때는 IDE를 이용해서 테스트 할 때와 배포한 후 실행될 때 경로가 다릅니다
확장이 어렵습니다.
이런 문제를 해결하기 위해서 대부분의 경우 파일 서버를 별도로 생성해서 저장
전에는 파일 서버를 별도로 두었지만 최근에는 클라우드 파일 서버를 주로 이용
클라우드 파일 서버로 사용하기 쉬운 서비스가 S3와 Google Firebase 의 File Storage 가 있습니다.

 

  • S3 사용하기 전 준비
    • IAM 사용자의 access key 와 secret access key : 외부 애플리케이션을 이용해서 AWS 를 사용할 때는 계정과 권한이 있어야 하는데 이에 대한 내용이 key로 발급됩니다.
    • AWS 서비스 안에서도 계정이 필요한 경우가 있습니다.
    • S3에 접근 권한 정책이 public 으로 접근이 가능해야 하고 할 수 있는 작업이 설정되어 있어야 합니다.
    • 웹 애플리케이션이 ajax 나 fetch api 와 같은 브라우저 요청일 때는 cors 설정도 확인
  • 필요한 정보
    • access key:  AKIA
    • secret key: CpX3Blcdo7Zo5
    • bucket name : itbambucket
    • region : ap-northeast-2
  • 패키지 설치
pip install boto3

pip install django-storages # 장고 애플리케이션이 파일 저장소를 외부와 연결하고자 할 때 사용
#django-storages 를 이용하지 않고 boto3 만 이용해서 구현하는 경우도 있는데 이렇게 하면 업로드하는 로직을 직접 작성해야 합니다.

 

  • settings.py 파일에 AWS 장고 스토리지 설정
# AWS Setting
AWS_REGION = 'ap-northeast-2' #AWS서버의 지역
AWS_STORAGE_BUCKET_NAME = 'itbambucket' #생성한 버킷 이름
AWS_ACCESS_KEY_ID = 'AKIAVUV3427FAJA2PBGB' #액서스 키 ID
AWS_SECRET_ACCESS_KEY = 'CpX3Blcdo7Zo5yMRLR6e0MMOdgCOVBZBvdttp6bZ' #액서스 키 PW
#버킷이름.s3.AWS서버지역.amazonaws.com 형식
AWS_S3_CUSTOM_DOMAIN = '%s.s3.%s.amazonaws.com' % (AWS_STORAGE_BUCKET_NAME, AWS_REGION)
# Static Setting 실제 static이 저장될 경로
STATIC_URL = "https://%s/static/" % AWS_S3_CUSTOM_DOMAIN
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
  • 연결확인
    • python manage.py collectstatic
  • 서비스를 다시 시작해서 파일을 업로드하면 로컬 컴퓨터에 저장되지 않고 AWS S3 버킷에저장
  • 현재 서비스의 문제점
    • 동일한 파일 이름을 업로드하게 되면 이전 파일이 삭제되고 업로드가 됩니다. 

 

파일 업로드 할 때 데이터베이스 사용
  - S3 는 동일한 이름의 파일이 업로드되면 이전 파일을 삭제하고 새로 업로드

이전 파일이 없어지지 않도록 하려면 새로 업로드되는 파일이 새로운 이름을 갖거나, 이름이 중복될 수 없도록 업로드하는 쪽에서 처리
업로드하는 쪽에서 처리를 해버리면, 처음 이름이 변경이 되므로 기억할 수가 없음.
데이터베이스에 변경된 이름을 기억을 시켜 가져올 수 있도록 해야 합니다.
이렇게 하지 않으면 매번 S3 에 접속해서 모든 파일의 이름을 가져와야 합니다.

파일 업로드를 서버에서 처리 하느냐 클라이언트에서 처리하느냐
- 서버가 파일을 업로드하는 경우 클라이언트가 서버에게 파일을 전송하고 서버가 다시 저장소에 전송하는 구조가 됩니다.
클라이언트가 파일을 저장소에 전송하고 이름만 전송하는 것보다 트래픽이 늘어납니다.

 

 

 

반응형
LIST

'Cloud > AWS' 카테고리의 다른 글

AWS (10/27)  (0) 2023.10.27