CLOUD

클라우드란?

  • 인터넷(네트워크)으로 접근 가능한 가상화된 서버, 프로그램, 데이터베이스를 제공하는 IT 환경
  • 클라우드를 사용하면 필요한 컴퓨팅 자원을 쉽게 가져와서 쓸 수 있다.

클라우드 컴퓨팅

  • 클라우드를 이용하여 컴퓨팅 자원을 사용하는 기술적인 방법
  • 서버, 스토리지, 네트워크 등의 자원을 가상화하여 제공
  •  장점
    1. 탄력성 & 확장성 : 필요에 따라 이를 확장하거나 축소할 수 있다.
      ( 트래픽이 몰리는 경우 유동적으로 사양을 늘릴 수 있다. )
    2. 비용 : 사용자가 사용한 만큼 비용을 지불한다. ( 낭비되는 리소스가 적음 ) 
    3. 안정성 : 다운타임/유지보수시간을 최소화하고 서비스를 정상적으로 유지시킬 수 있다.
    4. 내구도 : 여러 개의 클라우드를 사용하면 오류 및 사고발생 시점에 데이터를 안전하게 저장할 수 있다.

클라우드 컴퓨팅 종류

 

1. 퍼블릭 클라우드(Public Cloud)

  • 인터넷을 통해 누구나 접근할 수 있는 클라우드 서비스
  • 사용자는 클라우드 공급자가 제공하는 인프라를 공유한다.

2. 프라이빗 클라우드(Private Cloud)

  • 제한된 네트워크 상에서 특정 사용자만을 대상으로 하는 클라우드 서비스

3. 하이브리드 클라우드(Hybrid Cloud)

  • 퍼블릭 클라우드와 프라이빗 클라우드를 결합한 형태의 서비스
  • 온프레미스(물리 컴퓨터) + 클라우드(가상 컴퓨터) 로도 쓰인다고 합니다.

 

클라우드 서비스

  • 클라우드 컴퓨팅을 기반으로 제공하는 서비스 모델
  • 컴퓨팅, 데이터베이스, 스토리지, 네트워크, 보안 등 클라우드 기반으로 다양한 분야를 제공할 수 있다.

클라우드 서비스의 종류

 

1. IaaS(Infrastructure as a Service, 인프라 기반 서비스)

  • 기본적인 컴퓨팅 인프라를 제공하는 서비스
  • 가상화된 기본 자원(서버, 스토리지, 네트워크 등) 제공
  • AWS의 EC2
  • 장점 
    • 비용을 효과적으로 관리할 수 있다.
      => IT 인프라 직접 구축할 필요가 없고, 요구에 따라 자원 사용량을 조정, 사용한 만큼 비용 지불
    •  인프라 확장이 빠르고 용이하다.
  • 단점
    • 복잡하다
    • 퍼블릭 클라우드의 경우 보안 문제가 발생할 수 있음 

2. PaaS(Platform as a Service, 플랫폼 기반 서비스)

  • IaaS에서 제공하는 인프라 위에 개발, 배포, 운영을 지원하는 플랫폼을 제공 ( 더 추상화 )
  • 애플리케이션 개발 및 배포에 필요한 플랫폼(미들웨어, 데이터베이스 관리 시스템, 개발 도구, 라이브러리 등) 제공
  • 애플리케이션을 개발해서 업로드 하면 신속하게 배포, 운영 가능
  • AWS의 Elastic BeanStalk
  • 장점
    • 개발 생산성을 높일 수 있다.
  • 단점
    • 제한된 제어 수준을 제공한다. ( 인프라에 대한 정보 제어가 어렵다 )
    • 제한된 커스터마이징을 제공한다. ( 제공 업체가 제한된 범위의 서비스를 제공하므로 )

3. SaaS(Software as a Service)

  • 소프트웨어 서비스 제공 모델
  • 인터넷을 통해 소프트웨어 애플리케이션에 접근할 수 있다.
  • Notion, Netflix, Gmail
  • 장점
    • 편리하고 쉽게 접근이 가능하다. ( 인터넷만 있으면 애플리케이션 접근 가능 )
    • 자동 업데이트 ( 소프트웨어 업데이트 알아서 해줌 )
  • 단점
    • 성능 문제가 발생할 수 있다. ( 네트워크 환경에 따라 성능이 결정됨 )
    • 접근성 ( 인터넷 연결이 불량하거나 액세스할 수 없는 경우 애플리케이션에 접근할 수 없다. )

 

MSA(Microservices Architecture)

  • 애플리케이션을 여러 개의 작은 서비스로 나누어 구성하는 아키텍처
  • 각 서비스의 개발 및 배포 등 프로세스는 독립적이며, 서비스끼리 REST API, message stream등으로 통신하는 구조
  • 장점
    • 배포 
      - 서비스별 개별 배포가 가능하다. 
      - 특정 서비스의 요구사항만을 반영하여, 빠르게 배포할 수 있다.
    • 확장
      - 서비스의 대한 확장성(sacle-out)이 유리하다.
      - 클라우드 기반 서비스 사용에 적합하다.
    • 장애
      - 일부 장애가 전체 서비스로 확장될 가능성이 적다.
    • 새로운 기술 적용이 유연하다
    • 서비스 구조 파악 및 분석이 모놀리식 구조에 비해 쉽다.
  • 단점
    • 설계가 어렵다
      - 통신 장애, 통신 방법, transaction 유지 등을 설계하기 어렵다.
    • 성능
      - 서비스 간 호출 시 API를 사용하여, 통신 비용이나 Latency에 대한 이슈 존재
    • 데이터 관리
      - 데이터가 여러 서비스에 분산되어 조회가 어렵다.
      - 데이터를 관리하기가 어렵다.

 

AWS 서비스

  • EC2
    • IaaS로 크기를 조정할 수 있는 컴퓨팅 용량을 제공하는 웹 서비스 
  • IAM
    • AWS 서비스에 대한 엑세스를 안전하게 제어하는 웹 서비스
    • 사용자, 액세스 키와 같은 보안 자격 증명, 사용자와 애플리케이션이 어떤 AWS리소스에 엑세스 할 수 있는지 제어하는 권한 관리
  • Route53
    • AWS의 DNS
    • Route53을 사용하는 이유는 다른 AWS 인프라(ELB, S3 등)에 요청을 효과적으로 라우팅할 수 있다.
    • DNS + 모니터링 등으로 안정성이 보장된다고 한다.
  • Elastic Load Balancer
    • AWS의 네트워크 부하 분산 서비스
    • L7 : Application Load Balancer ( ALB )
      - 응용 프로그램과 관련된 계층으로 HTTP, FTP, DNS 등 사용자와 직접 접하는 프로토콜의 특성을 이용하는 로드밸런서
      - HTTP 헤더 정보로 부하 분산을 처리할 수 있다.
    • L4 : Network Load Balancer  ( NLB )
      - Transport Layer의 특성을 이용하는 로드밸런서
      - TCP, UDP를 사용하는 요청을 받아들여 부하분산을 처리한다.
      - HTTP 헤더를 해석하지 못하므로 헤더를 이용한 부하 분산은 불가능
    • Classic Load Balancer ( CLB )
    • 외부의 요청을 받는 리스너와 요청을 분산/전달할 리소스의 집합인 대상그룹으로 구성됨
    • 대상 그룹 내 리소스들은 헬스 체크(Health Check)를 활용해 주기적으로 상태를 확인받는다.
    • SSL 인증서를 탑재할 수 있어 대상 그룹의 EC2를 대신하여 SSL 암호화/복호화를 대신 진행할 수 있다.
    • 로드 밸런서 노드
      - 가용 영역마다 하나씩 존재하며, 가용 영역에 있는 부하분산 대상에 요청을 전달한다.


AWS EC2에 HTTPS 적용하는 과정

  1. 도메인 제공 업체에서 도메인을 구입한다. ex) 가비아
  2. AWS의 Route53에 호스팅 영역을 생성한다. ( AWS의 DNS인 Route53을 사용하기 위함 )
  3. Route53의 호스팅 영역을 생성하면 ns레코드가 생성된다. 가비아에 가서 구입한 도메인의 ns레코드를 등록한다.
  4. ACM을 사용하여 SSL인증서를 발급받는다.
  5. ELB를 생성하고 설정한다. (ELB의 가용 영역 설정, 리스너 추가 및 HTTPS 리스너에 SSL 인증서 설정, 대상 그룹에 EC2 인스턴스 연결 )
  6. Route53의 A레코드를 생성하고 ELB의 DNS 이름을 매핑
  7. EC2 인스턴스와 ELB 보안그룹에 사용자 요청을 받도록 설정해준다. ex) HTTP(80)와 HTTPS(443) 포트 열기

 

CSP 비교 ( AWS vs Azure vs Google Cloud )

AWS

  • 서비스 범위가 가장 넓음
  • 가장 오래된 성숙한 플랫폼
  • 온디맨드(사용한만큼) 비용
  • 난이도가 있고, 비용 산정이 유연한만큼 복잡하다

Azure

  • 마이크로소프트의 클라우드 서비스 플랫폼으로 마이크로소프트 서비스와 관련한 서비스 제공
  • Office365, Windows 서버 등 기업 기술에 대한 지원이 강력함
  • 엔터프라이즈 환경에 강점이 있다. => 기존 엔터프라이즈 솔루션과 호환
  • 학습곡선 존재, 글로벌 리전이 AWS에 비해 적다.

GCP

  • 구글의 클라우드 컴퓨팅 서비스로 빅데이터나 머신러닝 분야에 강점이 있다.
  • 사용자 친화적인 인터페이스를 제공함
  • 서비스 종류가 상대적으로 적고 엔터프라이즈 기능이 부족할 수 있다.

 

 


출처

https://aws-hyoh.tistory.com/134

https://aws-hyoh.tistory.com/128

https://hahahoho5915.tistory.com/71

https://suhyunsim.github.io/2022-12-08/%EC%9D%B8%ED%94%84%EB%9D%BC-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%A9%B4%EC%A0%91%EC%A7%88%EB%AC%B8

https://library.gabia.com/contents/infrahosting/9147/

https://ko.wix.com/blog/post/software-as-a-service-saas

https://www.samsungsds.com/kr/cloud-glossary/saas.html

https://www.samsungsds.com/kr/cloud-glossary/cloud-service.html

https://www.samsungsds.com/kr/cloud-glossary/what-is-cloud.html

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {1020, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다


LIS(최장 증가 부분 수열) 알고리즘 문제 입니다.

 

LIS의 길이를 구하는 방법은 크게 두가지가 있습니다. 

(1) DP : O(N^2) 

(2) Binary Search : O(NlogN)

 

N의 크기가 최대 1,000,000이 주어지므로 (2)를 사용하여 문제를 해결할 수 있습니다.

 

Binary Search로 LIS의 길이를 찾는 방법은 다음 예시로 설명드리겠습니다.

입력
6
10 20 15 19 30 18 // 배열 A

 

 

1) LIS 배열의 첫 원소는 주어진 배열 A의 첫 원소로 초기화합니다.

  • LIS[0] = A[0]; 
    LIS배열 [ 10 ]

2) A의 두번째 원소부터 LIS 배열에 들어갈 자리를 Binary Search를 통해 찾아 삽입합니다. 

  • BinarySearchkeyLowerBound(key보다 크거나 같은 첫번째 위치)를 반환합니다.
  • 현재 LIS배열은 [ 10 ]로 20보다 크거나 같은 값이 없으므로 반환 값은 1이 됩니다.
  • 인덱스 1에 20(key)을 삽입합니다.
  • LIS 배열 [ 10, 20

3) A의 세번째 원소 ( A[2] = 15 )

  • LIS배열은 [ 10, 20 ]로 BinarySearch가 반환하는 값은 1입니다.
  • 인덱스 1의 위치에 15(key)을 삽입합니다.
  • LIS 배열 [ 10, 15

4) A의 네번째 원소 ( A[3] = 19 )

  • LIS 배열은 [ 10, 15 ]로 BinarySearch가 반환하는 값은 2입니다.
  • 인덱스 2의 위치에 19(key)을 삽입합니다.
  • LIS 배열 [ 10, 15, 19 ]

5) A의 다섯번째 원소 ( A[4] = 30 )

  • LIS 배열은 [ 10, 15, 19 ]로 BinarySearch가 반환하는 값은 3입니다.
  • 인덱스 3의 위치에 30(key)을 삽입합니다.
  • LIS 배열 [ 10, 15, 19, 30 ]

6) A의 여섯번째 원소 ( A[5] = 18 )

  • LIS 배열은 [ 10, 15, 19, 30 ]로 BinarySearch가 반환하는 값은 2입니다.
  • 인덱스 2의 위치에 18(key)을 삽입합니다.
  • LIS 배열 [ 10, 15, 18, 30

이처럼 Binary Search를 이용한 방법은 LIS의 길이를 찾을 수 있지만, 정확한 LIS 배열을 찾지는 못합니다.

 

전체코드

더보기
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

// 가장 긴 증가하는 부분 수열 2
public class Main {

    static int A[];
    static int N;
    static List<Integer> LIS;

    private int binarySearch(List<Integer> list, int key) {
        int l = 0;
        int r = list.size() - 1;

        while (l <= r) {
            int mid = (l + r) / 2;

            int midVal = list.get(mid);

            if (midVal > key) {
                r = mid - 1;
            } else if (midVal < key) {
                l = mid + 1;
            } else {
                l = mid;
                break;
            }
        }

        return l;
    }


    private void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        N = Integer.parseInt(br.readLine());
        st = new StringTokenizer(br.readLine());
        LIS = new ArrayList<>();
        A = new int[N];

        for (int i = 0; i < N; i++) {
            A[i] = Integer.parseInt(st.nextToken());
        }

        LIS.add(A[0]);

        for (int i = 1; i < N; i++) {
            int idx = binarySearch(LIS, A[i]);
            if (idx == LIS.size())
                LIS.add(A[i]);
            else
                LIS.set(idx, A[i]);
        }

        System.out.println(LIS.size());
    }

    public static void main(String[] args) throws Exception {
        new Main().solution();
    }


}

 

 

드래곤 앤 던전

문제

용사는 공주를 구하기 위해 무시무시한 용이 있는 던전으로 향하기로 하였습니다. 우선 용사는 용사 자신과 던전을 분석하였습니다.

용사에게는 세 종류의 능력치가 있습니다. 

  • HMaxHP : 용사의 최대 생명력입니다. 이 값은 1이상이어야 하며 던전에 들어간 이후로 변하지 않습니다.
  • HCurHP : 현재 용사의 생명력입니다. 던전에 들어가기 전 이 값은 용사의 최대 생명력 HMaxHP와 같습니다. 이 값은 HMaxHP보다 커질 수 없습니다.
  • HATK : 용사의 공격력입니다.

던전은 총 N개의 방으로 이루어져 있고 i번째 방을 통해서만 i+1번째 방으로 이동 할 수 있습니다. 방에는 포션이 있거나 몬스터가 있는데 몬스터가 있을 경우 몬스터를 쓰러트려야지 다음방으로 이동 할 수 있습니다. N번째 방에는 공주와 용이 있고, 용을 무찌르면 공주를 구할 수 있습니다.

몬스터가 있는 방에 올 경우 다음과 같이 전투가 진행됩니다.

  1. 용사의 공격력 HATK만큼 몬스터의 생명력을 깎습니다.
  2. 몬스터의 생명력이 0 이하이면 전투가 종료되고 용사는 다음 방으로 이동합니다.
  3. 몬스터의 공격력만큼 용사의 생명력 HCurHP를 깎습니다.
  4. 용사의 생명력이 0 이하이면 전투가 종료되고 용사는 사망합니다.
  5. 다시 1부터 진행합니다.

포션이 있는 방에 올 경우 포션을 마셔서 현재 용사의 생명력 HCurHP가 일정량 회복되고 공격력 HATK도 일정량만큼 증가됩니다. 회복된 생명력이 최대 생명력 HMaxHP보다 큰 경우 용사의 현재 생명력 HCurHP가 최대 생명력 HMaxHP와 같아집니다.

용사는 던전으로 향하기 전에 만반의 준비를 하고 있습니다. 용사는 수련을 하면 최대 생명력 HMaxHP를 늘릴 수 있는데 얼마나 수련해야 할지 고민입니다.

용사는 N번 방에 있는 용을 쓰러트리기 위한 최소의 HMaxHP를 여러분이 계산해주면 좋겠다고 합니다.

입력

첫 번째 줄에 방의 개수 N (1 ≤ N  ≤ 123,456) 과 용사의 초기 공격력 HATK (1 ≤ HATK  ≤ 1,000,000) 가 주어집니다.

i+1번째 줄엔 i번째 방의 정보를 나타내는 세개의 정수 ti, ai, hi (ti ∈ {1, 2}, 1 ≤ ai, hi  ≤ 1,000,000) 가 주어집니다. 

ti가 1인 경우 공격력이 ai이고 생명력이 hi인 몬스터가 있음을 나타내고, ti가 2인 경우 용사의 공격력 HATK를 ai만큼 증가시켜주고 용사의 현재 생명력 HCurHP를 hi만큼 회복시켜주는 포션이 있음을 나타냅니다.

출력

용사가 N번째 방에 있는 용을 쓰러트리기 위한 최소의 HMaxHP를 출력합니다.


HMaxHP로 완전탐색을 하는 경우 시간은 123,456 * e^6 * e^6으로 시간초과가 발생합니다. 

따라서 이분탐색을 통해 HMaxHP를 찾습니다.

 

이분탐색 코드

    private void findAnswer() {
        long l = 1;
        long r = 123456l * 1000000l * 1000000l;

        while (l <= r) {
            long mid = (l + r) / 2;
			
            // HMaxHP = mid로 탐색합니다.
            if (simulate(mid)) {
                r = mid - 1;
                answer = mid;
            } else {
                l = mid + 1;
            }
        }
    }

 

전체 코드

더보기
package BackJoon;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

// 드래곤 앤 던전
public class BOJ16434 {

    static int N, H_atk;
    static Turn[] turns;
    static long answer;

    private boolean simulate(long maxHp) {
        long curHp = maxHp;
        long atk = H_atk;

        for (Turn turn : turns) {
            int t = turn.t;
            int a = turn.a;
            int h = turn.h;

            // 전투
            if (t == 1) {
                long i = h / atk;
                long j = h % atk;
                long cnt = ((j == 0) ? (i - 1) : (i));
                curHp -= (cnt) * a;
            } else {
                curHp = (Math.min(curHp + h, maxHp));
                atk += a;
            }

            if (curHp <= 0) {
                return false;
            }
        }
        return true;
    }

    private void findAnswer() {
        long l = 1;
        long r = 123456l * 1000000l * 1000000l;

        while (l <= r) {
            long mid = (l + r) / 2;

            if (simulate(mid)) {
                r = mid - 1;
                answer = mid;
            } else {
                l = mid + 1;
            }
        }
    }

    private void solution() throws Exception{
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine());

        N = Integer.parseInt(stringTokenizer.nextToken());
        H_atk = Integer.parseInt(stringTokenizer.nextToken());

        turns = new Turn[N];

        for (int i = 0; i < N; i++) {
            stringTokenizer = new StringTokenizer(bufferedReader.readLine());

            int t = Integer.parseInt(stringTokenizer.nextToken());
            int a = Integer.parseInt(stringTokenizer.nextToken());
            int h = Integer.parseInt(stringTokenizer.nextToken());

            turns[i] = new Turn(t, a, h);
        }

        findAnswer();


        System.out.println(answer);
    }

    public static void main(String[] args) throws Exception {
        new BOJ16434().solution();
    }

    static class Turn{

        int t, a, h;

        public Turn(int t, int a, int h) {
            this.t = t;
            this.a = a;
            this.h = h;
        }
    }

}

피아노 체조 

문제

피아노를 사랑하는 시은이는 매일 아침 피아노 체조를 한다. 시은이는 N개의 악보를 가지고 있으며, 1번부터 N번까지의 번호로 부른다. 각 악보는 1 이상 109 이하의 정수로 표현되는 난이도를 가지고 있다. 난이도를 나타내는 수가 클수록 어려운 악보이다. 1 ≤ x ≤ y ≤ N 을 만족하는 두 정수 x, y를 골라 x번부터 y번까지의 악보를 번호 순서대로 연주하는 것이 피아노 체조이다.

시은이는 피아노 체조를 할 때, 지금 연주하는 악보가 바로 다음에 연주할 악보보다 어렵다면 실수를 한다. 다시 말하자면, i(x  i < y)번 악보의 난이도가 i + 1번 악보의 난이도보다 높다면 실수를 한다. 특히, 마지막으로 연주하는 y번 악보에선 절대 실수하지 않는다. 시은이는 오늘도 피아노 체조를 하기 위해 두 정수 x와 y를 골랐고, 문득 궁금한 것이 생겼다. 오늘 할 피아노 체조에서 실수하는 곡은 몇 개나 될까?

입력

첫 번째 줄에 악보의 개수 N(1 ≤ N ≤ 100,000)이 주어진다.

두 번째 줄에 1번 악보부터 N번 악보까지의 난이도가 공백을 구분으로 주어진다.

세 번째 줄에 질문의 개수 Q(1 ≤ Q ≤ 100,000)이 주어진다.

다음 Q개의 줄에 각 줄마다 두 개의 정수 x, y(1 ≤ x ≤ y ≤ N)가 주어진다.

출력

x번부터 y번까지의 악보를 순서대로 연주할 때, 몇 개의 악보에서 실수하게 될지 0 이상의 정수 하나로 출력한다. 각 출력은 개행으로 구분한다.


누적합을 이용하면 정해진 시간 내로 해결할 수 있는 문제입니다.1번 악보부터 N번 악보까지의 실수의 합을 저장합니다.ex) prefix[5] : 1번부터 5번 악보까지 연주했을 때 실수의 합

더보기
package BackJoon;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

// 피아노 체조
public class BOJ21318 {

    static int prefixSum[];
    static int N, Q;

    private void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        N = Integer.parseInt(br.readLine());

        String[] s = br.readLine().split(" ");
        prefixSum = new int[N + 1];
        prefixSum[1] = 0;

        for (int i = 1; i < N; i++) {
            int a = Integer.parseInt(s[i - 1]);
            int b = Integer.parseInt(s[i]);

            prefixSum[i + 1] = prefixSum[i] + ((a > b) ? 1 : 0);
        }

        Q = Integer.parseInt(br.readLine());

        for (int i = 0; i < Q; i++) {
            String[] input = br.readLine().split(" ");
            int from = Integer.parseInt(input[0]);
            int to = Integer.parseInt(input[1]);
            bw.append(prefixSum[to] - prefixSum[from] + "\n");
        }

        bw.flush();
    }

    public static void main(String[] args) throws Exception {
        new BOJ21318().solution();
    }

}

 

+ Recent posts