모놀리식(monolithic)

  • 크고 복잡한 소프트웨어 시스템의 구조
  • 다음과 같은 특징을 가집니다.
  1. 단일 애플리케이션: 모놀리식 시스템은 단일 대규모 애플리케이션으로 구성되어 있으며, 여러 기능과 서비스가 하나의 코드베이스 내에 통합되어 있습니다.
  2. 긴밀한 결합: 시스템의 서로 다른 부분들은 서로 긴밀하게 연결되어 있으며, 한 부분의 변경이 다른 부분에 영향을 줄 수 있습니다.
  3. 단일 배포 단위: 애플리케이션의 모든 부분은 보통 함께 배포되며, 작은 변경을 위해서도 전체 애플리케이션을 재배포해야 할 수 있습니다.
  • 모놀리식 아키텍처는 개발의 초기 단계에서는 관리하기 쉽고 단순할 수 있지만, 시스템이 커지고 복잡해짐에 따라 유지보수와 확장이 어려워질 수 있습니다. 이러한 이유로 많은 현대적인 시스템들은 마이크로서비스 아키텍처로 전환하고 있는 추세입니다. 이는 시스템을 작고 독립적인 서비스로 나누어 각각을 별도로 관리하고 배포할 수 있게 하는 접근 방식입니다.

[ChatGPT-4.0]

부트스트랩

  • 시스템이 자체적으로 부팅하거나 초기화하는 과정

도메인

  1. 문제 영역 (Problem Domain): 이는 소프트웨어가 해결하려는 실제 세계의 특정 영역이나 분야를 의미합니다. 예를 들어, 은행 시스템의 경우 ‘도메인’은 금융 거래, 계좌 관리 등의 금융 활동을 포함할 수 있습니다.
  2. 비즈니스 로직 (Business Logic): 소프트웨어 내에서 도메인은 시스템이 어떻게 특정 비즈니스 문제를 해결하는지, 즉 비즈니스 규칙, 데이터 모델, 프로세스 등을 포함하는 부분을 가리킬 수 있습니다.
  • 도메인 주도 설계(Domain-Driven Design, DDD)
    • 각 도메인을 명확하게 구분하고, 도메인 간의 결합을 최소화하는 것을 목표로 합니다. 이를 통해 소프트웨어의 유연성과 확장성을 향상시키며, 복잡한 시스템의 관리와 개발을 용이하게 합니다.

모놀리식 아키텍처 vs모놀리식 아키텍처

모놀리식 아키텍처

  1. 정의: 모놀리식 아키텍처는 소프트웨어 애플리케이션이 단일 코드베이스와 단일 배포 단위로 구성된 구조입니다. 모든 기능이 하나의 애플리케이션 내에 통합되어 있습니다.
  2. 장점:
    • 초기 개발의 단순성: 초기 개발 및 배포가 간단하고, 이해하기 쉽습니다.
    • 테스트 용이성: 단일 애플리케이션으로 모든 구성 요소를 테스트할 수 있습니다.
    • 성능: 내부 호출이 네트워크 오버헤드 없이 이루어져 성능상 이점이 있을 수 있습니다.
  3. 단점:
    • 확장성 문제: 애플리케이션이 커짐에 따라 관리 및 확장이 어려워질 수 있습니다.
    • 유연성 부족: 한 부분의 변경이 전체 애플리케이션에 영향을 미칠 수 있습니다.
    • 배포 복잡성: 작은 변경에도 전체 애플리케이션을 재배포해야 할 수 있습니다.

컴포넌트 기반 아키텍처

  1. 정의: 컴포넌트 기반 아키텍처는 소프트웨어를 독립적이고 교체 가능한 모듈, 즉 ‘컴포넌트’로 분리하여 구성하는 방식입니다. 각 컴포넌트는 특정 기능을 수행하며, 서로 상호 작용합니다.
  2. 장점:
    • 재사용성: 컴포넌트는 재사용 가능하므로 개발 시간과 비용을 절감할 수 있습니다.
    • 유연성과 확장성: 개별 컴포넌트를 독립적으로 업데이트하거나 교체할 수 있어 시스템의 유연성과 확장성이 높아집니다.
    • 유지보수 용이성: 각 컴포넌트를 독립적으로 유지보수할 수 있습니다.
  3. 단점:
    • 복잡한 설계와 관리: 컴포넌트 간의 상호 작용을 관리하는 것이 복잡할 수 있습니다.
    • 성능 오버헤드: 컴포넌트 간의 통신에는 추가적인 오버헤드가 발생할 수 있습니다.
    • 초기 개발 비용: 모듈화된 시스템을 설계하고 구현하는 데 시간과 비용이 더 많이 들 수 있습니다.

의존성(Dependency)

  • 한 코드 부분이 다른 코드 부분의 기능이나 데이터에 의존하는 관계를 의미합니다. 이는 소프트웨어의 구성 요소 간의 연결 및 상호 작용을 나타내는 중요한 개념입니다.

의존성의 특징

  1. 코드 상호작용: 한 클래스, 모듈 또는 함수가 다른 클래스, 모듈 또는 함수의 메서드나 데이터를 사용할 때, 이를 ‘의존성’이라고 합니다.
  2. 결합도(Coupling): 의존성은 종종 결합도와 연관되어 있습니다. 높은 결합도는 한 컴포넌트가 다른 컴포넌트에 강하게 의존하고 있음을 의미합니다.
  3. 유지보수성: 의존성이 많을수록 코드의 유지보수가 어려워질 수 있습니다. 한 부분의 변경이 의존하는 다른 부분에 영향을 미칠 수 있기 때문입니다.
  4. 재사용성: 의존성이 낮은 코드(즉, 낮은 결합도를 가진 코드)는 재사용하기가 더 쉽습니다. 이러한 코드는 다른 컨텍스트에서도 쉽게 사용될 수 있습니다.

의존성 관리

  1. 의존성 주입(Dependency Injection): 의존성을 관리하는 일반적인 방법입니다. 이를 통해 코드의 결합도를 낮추고, 유연성과 테스트 용이성을 향상시킬 수 있습니다.
  2. 의존성 역전 원칙(Dependency Inversion Principle): 이 원칙은 고수준 모듈이 저수준 모듈에 의존하지 않도록 하는 설계 원칙입니다. 대신, 둘 다 추상화에 의존해야 합니다.
  3. 모듈화와 패키징: 코드를 잘 정의된 모듈이나 패키지로 분리함으로써, 각 모듈이나 패키지의 의존성을 명확하게 관리할 수 있습니다.

의존성 주입 (Dependency Injection, DI)

  • 의존성 주입은 객체 간의 의존 관계를 외부에서 주입하는 기법입니다. 즉, 객체가 필요로 하는 의존성(다른 객체나 서비스)을 외부(주로 프레임워크나 컨테이너)에서 제공하는 방식입니다. 이를 통해 각 객체는 의존성을 직접 생성하지 않고, 사용할 준비가 된 의존성을 제공받습니다. 이 방식의 주요 목적은 코드의 결합도를 낮추고, 유연성과 테스트 용이성을 향상시키는 것입니다.

    특징과 장점:

    • 결합도 감소: 객체가 자신의 의존성을 직접 생성하거나 검색하지 않기 때문에 결합도가 감소합니다.
    • 재사용성 및 유지보수성 향상: 의존성이 외부에서 주입되므로, 코드의 재사용성과 유지보수성이 향상됩니다.
    • 테스트 용이성: 의존성을 주입하므로, 테스트 중에 다른 구현이나 모의 객체(mock objects)로 쉽게 대체할 수 있습니다.

    사용 예:

    • 생성자 주입: 의존성이 객체의 생성자를 통해 주입됩니다. 이 방법은 객체의 의존성이 변경 불가능(immutable)하고, 필수적일 때 적합합니다.
    • 세터 주입: 의존성이 객체의 세터 메소드를 통해 주입됩니다. 이 방법은 의존성이 선택적이거나 변경 가능할 때 유용합니다.
    • 필드 주입: 의존성이 객체의 필드에 직접 주입됩니다. 이 방법은 간단하지만, 테스트와 유지보수 측면에서 제한이 있을 수 있습니다.

의존성 역전 원칙 (Dependency Inversion Principle, DIP)

  • 의존성 역전 원칙은 소프트웨어 설계 원칙 중 하나로, 고수준 모듈이 저수준 모듈에 의존하지 않도록 권장합니다. 대신, 둘 다 추상화에 의존해야 한다고 주장합니다. 이 원칙은 객체 지향 프로그래밍의 SOLID 원칙 중 하나입니다.

주요 내용:

  • 고수준 모듈: 비즈니스 규칙이나 로직을 포함합니다.
  • 저수준 모듈: 데이터 저장, UI, 외부 서비스 통신 등 구체적인 작업을 수행합니다.
  • 추상화: 고수준과 저수준 모듈 모두 추상화(인터페이스나 추상 클래스)에 의존해야 합니다.

장점:

  • 유연성: 시스템의 고수준 정책을 저수준의 구현으로부터 독립시킬 수 있습니다.
  • 재사용성: 고수준 모듈이 저수준 모듈의 구체적인 구현에 묶이지 않으므로, 다양한 상황이나 다른 저수준 모듈에서 재사용할 수 있습니다.
  • 테스트 용이성: 저수준 모듈을 모의 객체나 다른 구현으로 쉽게 대체할 수 있어, 단위 테스트가 용이합니다.

사용 예:

  • 인터페이스 기반 프로그래밍: 고수준 모듈은 저수준 모듈의 구체적인 구현 대신 인터페이스에 의존합니다.
  • 의존성 주입: DIP를 실현하는 데 사용될 수 있으며, 의존성 주입을 통해 고수준 모듈이 저수준 모듈의 구체적인 구현에 직접 의존하지 않도록 할 수 있습니다.

Feature Flag(또는 Feature Toggle)

  • 소프트웨어 개발 및 운영에서 사용되는 기술로, 소프트웨어의 특정 기능을 동적으로 활성화하거나 비활성화할 수 있도록 하는 메커니즘입니다. 이 방식은 개발자가 코드 베이스 내에서 조건부로 특정 기능을 켜고 끌 수 있게 해줍니다.

사용 사례

  1. 롤아웃 및 롤백: 새로운 기능을 점진적으로 배포하거나 필요한 경우 신속하게 롤백하는 데 사용됩니다.
  2. A/B 테스팅: 사용자 그룹에 따라 다른 기능이나 UI 변형을 제공하며, 성능을 테스트하고 사용자 반응을 측정하는 데

활용됩니다.

  1. 환경 구성: 개발, 스테이징, 프로덕션 등 다양한 환경에서 다른 기능을 활성화하거나 비활성화할 수 있습니다.
  2. 사용자 권한 및 기능 제어: 특정 사용자 그룹이나 개인에게만 기능을 제공하고자 할 때 유용합니다.

장점

  1. 유연한 기능 관리: 실시간으로 기능을 켜고 끌 수 있어, 배포 프로세스가 더 유연해집니다.
  2. 리스크 감소: 새 기능이나 변경사항을 점진적으로 도입함으로써 위험을 최소화하고, 문제 발생 시 신속하게 대처할 수 있습니다.
  3. 효율적인 테스트 및 배포: 기능 플래그를 사용하면, 완전히 개발된 기능이 아니더라도 코드를 프로덕션 환경에 배포하고 테스트할 수 있습니다.
  4. 사용자 맞춤형 경험 제공: 사용자 또는 사용자 그룹별로 맞춤형 기능을 제공하여, 개인화된 사용자 경험을 만들 수 있습니다.

고려 사항

  • 기능 플래그 관리: 많은 수의 Feature Flag가 사용되면 관리가 복잡해질 수 있습니다. 따라서 Feature Flag를 체계적으로 관리하고, 사용하지 않는 플래그는 정리하는 것이 중요합니다.

  • 성능 영향: Feature Flag가 많을 경우, 시스템의 성능에 영향을 줄 수 있습니다. 각 Flag가 평가되는 방식과 시기를 신중하게 고려해야 합니다.
  • 테스트 복잡성: 다양한 기능 플래그 조합으로 인해 테스트 케이스가 복잡해질 수 있습니다. 각 조합에 대한 테스트 계획이 필요할 수 있습니다.

기술적 구현

  • Feature Flag의 구현은 간단한 조건문부터 시작해, 복잡한 클라우드 기반 서비스나 전용 소프트웨어까지 다양합니다. 중요한 것은 기능 플래그를 사용하는 목적에 맞는 적절한 수준의 관리 체계와 도구를 선택하는 것입니다.

  • Feature Flag는 소프트웨어 개발의 유연성과 신속한 반응성을 크게 향상시키는 동시에, 적절한 관리 없이는 복잡성을 증가시킬 수 있습니다. 따라서 이를 효과적으로 사용하기 위해서는 주의 깊은 계획과 실행이 필요합니다.

참고

  • ChatGPT-4.0

보완/복습

  • 2024.01.12 생성