2024.09.30.월.TIL Software Architecture

김기남·2024년 9월 30일
post-thumbnail

안녕하세요, 오늘은 Software Architecture 에 대해 정리해 보았습니다.

IT 발전과정

1960 ~ 1980s : Fragile Cowboys

💡 Fragile 은 사전적 의미 그대로 깨지기 쉬운 시스템이라는 특징을 가지고 있다.
  • Mainframe, Hardware
  • 메인 프레임 방식으로 하드웨어가 중심이 되었다.
    • 소프트웨어 보다는 하드웨어의 사양에 맞추어 서비스가 구축되었다.
    • 하드웨어가 워낙 고가의 장비이기 때문에 서비스의 기능 수정이나 추가가 힘들었다.

1990 ~ 2000s : Robust, Distributed

💡 1990 ~ 2000년대는 분산이라는 키워드로 아키텍처를 볼 수 있다.
  • Changes
  • 분산되어 시스템이 안정화 되었다.
    • 분산된 시스템 덕분에 서비스의 불확실한 변화가 발생하여도 안정성 있는 서비스를 유지할 수 있게 됨

2010s~ : Resilient/Anti-Fragile, Cloud Native

💡 시스템이 Local 환경에서 Cloud로 이전되었다.
  • Flow of Value의 지속적 개선
  • Fragile과 반대되는 개념이 Anti-Fragile 이다.
  • Cloud Native로 시스템이 구축되던 시기
    • 확장성과 안정성이 강화됨
    • 지속적인 개선 및 변경이 발생해도 시스템을 탄력적으로 운영할 수 있다.

정리

  • 현대 : Anti-Fragile
    - DevOps라는 IT 문화가 생겨났다.
    - Cloud Native Architecture로 전환된 시기이다.
  1. Antifragile은 다른 개발 System이나 환경보다 시스템 변화가 적다
    a. 변화에 바로 적응할 수 있다.
  2. 그럼에도 비용이 저렴하다.

Antifragile의 4가지 특징

💡 취약한 시스템들이 스트레스에 약할 때, Antifragile 아키텍처는 변화에 대응하여 더 강력하고 적응력 있는 특징을 갖춘다.

1. Auto Scailing

  1. 시스템을 구성하고 있는 인스턴스를 하나의 Auto Scaling Group으로 묶는다.
  2. 최소 인스턴스를 지정할 수 있다.
  3. 사용량에 따라 인스턴스를 증가하도록 만들 수 있다.
  • 기존 1개의 서버 운영

  • 트래픽이 증가함에 따라 3개의 서버 운영

💡 위와같은 작업을 운영자의 설정이 아니라 ****CPU, Memory, 네트워크, DB의 사용량이나 **조건에 따라서 처리하는 개념**이바로 **Auto scaling** 이다**.**

Micro Services

💡 기존 시스템이 하나의 거대한 형태로 구축되어 서비스 되었다면, 마이크로 서비스는 전체 서비스를 구성하고 있는 개별적인 모듈이나 기능을 독립적으로 개발하고 배포하고 운영할 수 있도록 세분화된 서비스라고 할 수 있다.
  • AWS와 Netfilx의 Micro Service 구상도
    • 넷플릭스와 아마존은 클라우드 서비스를 가장 잘 구축하고 활용하고 있는 업체로 알려져있다.
    • 실제로 Spring Cloud의 초창기 라이브러리 중 많은 부분이 넷플릭스에서 개발되었다.
    • 만들어진 라이브러리들이 Spring 진영에 기부된 것

  • 넷플릭스 구상도에서 파란색은 서비스간의 연동이나 통신을 의미한다.
  • 초록색은 넷플릭스라는 전체 서비스를 구축하고 있는 각각의 Microservices 이다.
  • 마이크로 서비스는 Cloud Native Architecture Application의 핵심이다.

Chaos engineering

💡 급격하고 예측하지 못한 상황에서도 System이 안정적으로 견딜 수 있고 신뢰성을 쌓기위해 운영중인 소프트웨어 시스템에 실행하는 방법론
  • SK C&C Tech Blog

Chaos Engineering 개요

  • Naver Blog

카오스 테스트(카오스 엔지니어링)란 무엇일까요?

한마디로 어떠한 경우에도 안정적으로 서비스를 제공할 수 있도록 구축되어야 한다는것을 의미.

Continuous deployments

💡 지난시간 배웠던 CI / CD 즉, 지속적인 통합과 지속적인 배포 CI / CD 라는 개념은 Cloud Naitve나 마이크로 서비스에서만 새롭게 사용되는것이 아니라 이전부터 시스템의 통합적인 관리와 운영을 위해 사용되었지만  Cloud Native나 마이크로 서비스에서 더욱 빛을 발하게 되었다.

  • Cloud Native Application은 수십, 수백개 이상의 마이크로 서비스로 도메인이 분리되어 개발된다.

  • 수많은 서비스들을 하나하나 빌드, 테스트, 배포 하는 등의 작업을 수작업으로 한다고 가정한다면?

    • 시스템 자체가 엄청나게 복잡해진다.
    • 각각의 서비스를 빌드하고 배포하는 작업이 하나의 큰 업무가 된다.
  • 마이크로 서비스들을 빌드하고 배포함에 있어서 자동화된 시스템을 구축하는것이 중요해졌다.

    • 하나의 작업에서 다른 작업으로 연계되는 작업을 파이프 라인으로 연결 시킨다면
    • 작은 변경 뿐만 아니라 전체적인 시스템 변경 측면에서도 빠르게 적용이 된다.

Cloud Native Architecture

💡 2010년대 이후부터 IT 시스템은 AntiFragile 혹은 Cloud Native Architecture의 형태로 발전해왔다.
  • 기존에 Local 환경(사내 서버 등)으로 구축하여 운영하던 시스템을
    Cloud 환경으로 전환하기 위해서 어떠한 구조가 필요한지 알아보자.

1. 확장성

  • 확장 가능한 형태의 아키텍처

    • 시스템의 수평적 확장 -> 더 많은 사용자의 요청을 처리할 수 있다.
    • 즉, 확장된 시스템으로 인해 부하를 분산하여 가용성이 보장되었다.
    • 시스템 확장은 Scale Up(수직 확장), Scale Out(수평확장) 크게 두가지로 나뉜다.
  • Scale Up, Scale Out

    • Scale Up
      • 수직적 확장
      • 하드웨어의 사용을 높인다. (CPU, Memory 등의 스펙을 높인다)
    • Scale Out
      • 수평적 확장
      • 같은 사양의 서버(인스턴스)를 여러대 배치
      • 동시에 더 많은 사용자 요청을 처리할 수 있도록 만듦.
      • 일반적으로 이렇게 시스템을 양적으로 늘리기 위해서는 하드웨어 비용이 증가
  • Cloud Service

    • 업체로부터 가상의 서버, 가상의 저장소, 가상의 네트워크 등을 빌려서 사용하게 되었다.
    • 시스템을 양적으로 늘리기 위해서 사용되던 비용을 최소화할 수 있게되었다.
      • 증축시킨 서버를 사용하지 않을 경우엔 자유롭게 반납하여 비용을 낮출 수 있다.
      • Cloud Service 업체를 사용하여 Auto Scailing 또한 가능하다.
    • Cloud Native 에서는 가상서버 기술이 핵심이 되었다.
    • 가상 서버와 리소스들은 모니터링 도구들을 통해 현재 사용량을 측정하기 쉽다.
  • Container 가상화

    • 기존의 서버 가상화 방식과 더불어 컨테이너 방식의 가상화를 같이 사용하게 됨.

2. 탄력성

  • 어플리케이션을 구성하는 각 기능을 하나의 분리된 서비스로 개발(Micro Service)

    • 분리되어 개발된 서비스들을 통합하고 배포하는 시간을 CI / CD로 처리함
    • 시스템 환경에 적용하는 시간을 단축
  • 무수히 많은 환경에 같은 내용을 서비스 배포하는 과정이 자동화 되어있지 않다면?

    • 개발자는 비지니스 로직을 개발하는 시간보다 빌드, 배포에 많은 시간을 들이게된다.
  • Micro Service

    • 서로 분리된 서비스들간에 원활한 통신을 위해 각각의 서비스들은 종속성을 최소화 시켜야한다.
    • 상태를 갖지않는 서비스를 제공하려고 노력해야 한다.(무상태 통신 프로토콜)
    • 마이크로 서비스들은 서비스가 배포될때 서비스들의 위치가 어디에 있는지 등록을 해야한다.
      • 다른 서비스들이 해당 서비스를 찾아 사용할 수 있도록 구성 해야한다.
  • Service Discovery

    • 마이크로 서비스들의 존재는 서비스 디스커버리라는 곳에 등록되고 삭제되는 작업을 하게된다.
      • 다른 서비스들이 해당 서비스를 찾아 사용할 수 있게 된다.

3. 장애 격리

  • 특정 서비스에 오류가 발생해도 다른 서비스에 영향을 주지 않는다.
    • 마이크로 서비스들은 하나의 작은 단위의 Application이다.
    • 따라서 하나의 서비스에 생기는 오류 사항들을 다른쪽 서비스로의 영향을 최소화 할 수 있게된다.

Cloud Native Application

💡 Cloud Native Architecture에 의해 설계되고 구현되는 Application을 의미한다.

  1. 마이크로 서비스로 개발된다.

  2. CI / CD 과정을 거치게 된다.

  • 마이크로 서비스에 문제가 발생하였을 경우 바로 수정하여 다시 배포하는 과정을 반복할 수 있다.
  • 이러한 특징을 DevOps라고 한다. 고객이 원하는 최선의 결과물을 빠르게 만드는것이 목적이다.
  1. 마이크로 서비스들을 클라우드 환경에 배포하고 사용하기 위해서는 컨테이너 가상화 기술을 사용하게 된다.

Cloud Native Application 특징

배포전략

  • 시스템에 완성된 결과물을 배포하기 위해 사용되는 전략 두가지
  1. 카나리 배포
  2. 블루그린 배포
  • 카나리 배포

  1. 전체 사용자의 95% 가량의 비율은 이전 서비스를 사용하도록 한다.
  2. 전체 사용자의 5% 가량은 새로 만들어진 서비스를 사용하도록 한다.
  • 블루그린 배포

  1. 이전 버전(Blud)에 있던 트래픽을 거의 동일한 새 버전(Green)으로 점진적으로 이전시킨다.
  2. 두 버전 모두 프로덕션 환경에서 실행 상태를 유지해야 한다.

DevOps

💡 Development와 운영을 뜻하는 Operation이 합쳐진 용어 개발, 운영 조직의 통합을 의미한다.
  • 위와같은 통합으로 고객의 요구사항을 빠르게 반영하고 완성도 높은 결과물을 제시하는것에 목적이 있다.

기존의 엔터프라이즈 어플리케이션

  • 고객의 요구사항에 맞게 도메인을 분석 후
    시스템을 설계, 어플리케이션 구현, 테스트, 배포 과정을 거쳐 시스템 개발을 완료하게된다.
    이러한 과정은 적게는 수개월 많게는 수년까지 걸리게 된다.

  • 개발 조직에 따라서 중간 단계의 필수적인 과정이 있을 수 있다.

    • 개발 기간이 길어지게 된다.
    • 그만큼 변경 및 요구사항에 바로 대처하기 어렵다는 단점을 가질 수 있다.
  • 고객의 요구사항은 언제든지 변경될 수 있다.

    • 심지어 개발 마지막 단계에서 변경이 발생하기도 한다.
    • 필요할 때마다 바로바로 수정될 수 있는 구조가 더욱 좋다.
  • 필요할 때 마다 요구사항을 반영하고 테스트를 자주 하는것은 개발 일정이 지연될 수 있다

    • 그럼에도 불구하고 최종적으로 고객의 요구사항에 맞는 오류없는 완성물이 나와야한다.

정리

  1. 통합, 테스트, 배포 하는 과정을 전체 개발이 완료될때 까지 끊임없이 진행하는것을 DevOps라 한다.
  2. Cloud Native Application은 이러한 DepOps 환경에 맞춰서 서비스의 구조를 작은 단위로
    나눌 수 있게 함으로써 더 자주 통합, 테스트, 배포할 수 있는 구조가 되었다.

Container 가상화

💡 Cloud Native Architecture의 핵심 기존의 로컬 환경에서 운영해야만 했던 시스템을 Cloud 환경으로 이전해서 작은 비용으로 탄력성 있는 시스템을 구축할 수 있게된 배경에는 컨테이너 가상화 기술이 있다.

  1. Traditional Deployment

    • 기존의 하드웨어 가상화, 서버 가상화에 비하여 적은 리소스를 사용하여 가상화 서비스를 구축할 수 있다.
      • 전통적인 방식은 하드웨어 시스템 위에 운영체제를 설치하고 그 다음 어플리케이션을 운영한다.
  2. Virtualized Deployment

  • 가상화를 통한 개발 시스템에서는 Hypervisor 기술을 통한 가상 머신을 기동한다.
    • 가상머신은 시스템이 가지고있는 Hardware(호스트 시스템)를 나누어 사용한다.
      • 각각의 가상머신에 Application을 운영할 수 있다.
      • 하나의 가상머신은 독립적인 운영체제를 가지고 실행될 수 있다.
    • 하지만 가상머신에서 작동되는 어플리케이션은 호스트 운영체제에 많은 부하를 주게된다.
      • 즉, 시스템 확장에 한계가 발생한다.
  1. Container Deployment
  • 운영체제 위에 컨테이너 가상화를 기동하기 위한 소프트웨어 서비스를 작동한다.
    • 공통적인 라이브러리나 리소스를 공유하여 사용한다.
    • 각자 필요한 부분에 대해서만 독립적인 영역에 실행할 수 있는 구조
    • 기존의 하드웨어 가상화 기술보다 더 적은 리소스를 사용
      • 컨테이너 가상화 위에서 동작하는 서비스들은 가볍고 빠르게 운영할 수 있다는 특징

12 Factors

💡 Cloud Native Application을 구축함에 있어서 고려해야할 12가지 항목
  • 한국어 번역 사이트

The Twelve-Factor App (한국어)

  • Heroku 헤로쿠
    • 자사의 고객들을 상대로 Cloud Service시에  발생했었던 문제점과 개선점
      시행착오등을 바탕으로 가이드 라인을 만들어 배포하였다.
    • 많은 Cloud Native Application에서 가이드를 바탕으로 어플리케이션을 설계, 개발, 운영하는데 사용

Base Code (코드 통합)

  • 자체 Repository에 저장된 각 마이크로 서비스에 대한 단일 코드 베이스
  • 버전을 제어하기위한 목적이 있다, 형상 관리를 위해서 코드를 한곳에서 배포하기 위함
  • 개발, 운영에 배포하기 위해서 코드의 통일적인 관리가 필요하기 때문에 가장 중요한 항목으로 꼽힌다.

2. DEPENDENCY ISOLATION (종속성의 배제)

  • 각 마이크로 서비스는 자체 종속성을 가지고 패키징 되어있다
  • 전체 시스템에 영향을 주지 않는 상태에서 변경되고 내용을 수정할 수 있어야 한다.

3. CONFIGURATIONS (환경설정의 외부 관리)

  • 하드코딩 되어있는 설정정보가 아니라 시스템 코드 외부에서 구성관리 도구를 통해서
    마이크로 서비스에 필요한 작업들을 제어한다.
  • 올바른 구성이 적용된 환경에서 동일한 배포가 전파될 수 있다.

4. LINKABLE BACKING SERVICES (백업 서비스의 분리, 서비스 지원)

  • 예를들어 DB, Cache, Messaging Service, Broker 등을 이용해서
    마이크로 서비스가 가져야할 기능들을 추가로 지원할 수 있는것을 말한다.
  • 응용 프로그램 자체에서 필요한 BACKING System Resource를 분리하게 됨으로써
    서로 상호가능한 서비스들의 Dependency를 갖지 않는 상태에서 작업할 수 있게 된다.

5. Build Release and Run, STAGES OF CREATION (개발, 테스트, 운영환경의 분리)

  • 개발 서버에서 만들어진 코드를 배포하기 위해서 실행단계까지 옮기는 과정을 엄격하게 분리

  • 각각은 고유한 아이디로 태그를 가지고 있어야 한다.

  • 이전 상태로 돌아가는 롤백기능을 지원해야 한다.

  • CI / CD 시스템을 완벽하게 이용해서 자동화된 시스템을 구축하는것이 좋다.

6. STATELESS PROCESS (상태관리)

  • 각각의 마이크로 서비스는 실행중인 다른 서비스와 분리된채 자체 프로세스에서 운영될 수 있어야 한다.
  • 마이크로 서비스에 필요한 자원이 있다면 캐시, 데이터 저장소등을 이용하여 외부와 데이터 동기화 하면된다.

7. PORT BINDING (포트 바인딩)

  • 각각의 마이크로 서비스는 자체 PORT에서 노출되는 인터페이스 및 기능이 있어야 한다.
  • 위와같은 구조를 가지면 다른 마이크로 서비스와 격리가 가능해진다.

8. CONCURRENCY (동시성)

  • 마이크로 서비스는 사용 가능한 가장 강력한 인스턴스 컴퓨터에서
    가장 큰 인스턴스로 확장하는것과는 반대로
    아주 많은 수의 서비스 동일한 프로세스를 복사해서 확장한다.
  • 하나의 서비스가 여러가지 인스턴스에 동일한 형태로 복사되어 운영됨으로써 부하분산을 달성한다.
  • 따라서 서비스가 여러 인스턴스에 나누어져 있기 때문에 동시성을 가진다.

9. DISPOSABILITY (서비스의 올바른 상태유지 )

  • 서비스 인스턴스 자체가 삭제 가능해야한다.
  • 확장성 기회를 높여야한다.
  • 정상적으로 종료할 수 있어야 한다
  • 컨테이너 가상화 도구로써 Docker등을 사용하면 위와같은 과정을 쉽게 해결할 수 있다.

10. DEVELOPMENT, PRODUCTION PARITY (개발과 운영환경의 통일)

  • 개발 단계와 프로덕션 단계를 구분한다.
  • 운영프로그램의 수명주기 전반에 걸쳐 서비스에 직접 Access하는 기능을 방지해야 한다.
  • 환경 자체를 최대한 다른 서비스와 중복, 종속적이지 않은 상태로써 서비스를 유지할 수 있어야 한다.

11. LOGS (로그 분리)

  • 로깅 시스템은 마이크로 서비스에 의해서 생성된 로그를 이벤트 스트림으로 처리해야한다.
  • 로그를 출력하는 로직은 기존의 어플리케이션 로직과 분리되어
    어플리케이션이 실행되지 않는 상태여도 로그만은 정상적으로 작동되어야 한다.
  • 이러한 로그, 이벤트를 집계하기 위해서는 별도의 추가적인 서비스 혹은 모니터링 서비스를 사용할 수 있다.

12. ADMIN PROCESSES FOR EVENTUAL PROCESSES (관리 프로세스)

  • 현재 운영되고 있는 모든 마이크로 서비스들은 어떤 상태로 사용되고 있는지 알아야 한다.
  • 서비스들의 리소스가 현재 어떻게 사용되고 있는지 파악하기 위한 적절한 관리도구가 필요하다.
  • 이러한 작업에는 리포팅 할 수 있는 기술이 포함되어 있어야 한다.
  • 결과로 나온 데이터를 정리 및 분석하는 기능이 포함될 수 있다.

15 Factors

💡 최근에는 12가지에서 3가지가 추가된 15가지의 요인에 대하여 고민하여야 될 수 있다. 확실히 정해진것은 아님.
  • Pivotal 에서 발표한 + 3

IBM Developer

1. API First

  • 가지고 있는 모든 마이크로 서비스는 API 형태로 서비스가 제공된다.
  • API를 구축하에 있어서 사용자측에서 어떠한 형태로 쓸것인가를 먼저 고민하여 개발해야 한다.

2. Telemetry

  • 모든 지표는 수치화, 시각화되어 관리할 수 있는 항목이어야 한다.

3. Authentication and authorization

  • API를 사용함에 있어서 인증 작업은 필수이다.
  • 마이크로 서비스는 적절한 인증을 가지고 있는
    리소스, 서비스, 외부시스템에 대해서는 데이터를 전달, 교환하는 것이 가능하여야 한다.

오늘의 코드카타

class Solution {

    public int[] solution(int[] num_list) {
        int[] answer = new int[num_list.length];
        for (int i = 0; i < num_list.length; i++) {
            answer[i] = num_list[num_list.length - i - 1];
        }
        return answer;
    }
}
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        Solution solution = new Solution();

        int[] a1 = {1, 2, 3, 4, 5};
        int[] a2 = {1, 1, 1, 1, 1, 2};
        int[] a3 = {1, 0, 1, 1, 1, 3, 5};

        System.out.println(Arrays.toString(solution.solution(a1)));
        System.out.println(Arrays.toString(solution.solution(a2)));
        System.out.println(Arrays.toString(solution.solution(a3)));
    }
}

배열 뒤집기

profile
새로운 시작~!

0개의 댓글