BackEnd

소프트웨어 아키텍처 (Software Architecture)

sihanni 2025. 1. 16. 19:59

소프트웨어 아키텍처 스타일에 대해 알아보는 글

관련글: 디자인 패턴 https://sihanni.tistory.com/99

 

디자인 패턴

디자인 패턴디자인 패턴은 반복적으로 사용되는 설계 문제를 해결하기 위한 일반화된 솔루션이다.주로 코드의 재사용성, 가독성, 유지보수성을 높이고, 설계의 복잡성을 줄이는 데 사용된다.Mod

sihanni.tistory.com

 

 

소프트웨어 아키텍처의 정의

"시스템의 전체적인 구조에 대한 정의"

시스템의 구조, 구성 요소, 상호작용, 그리고 이를 설계하고 유지보수하기 위한 원칙과 지침을 정의하는 것

소프트웨어 아키텍처에 대해 이해하고 있으면 더욱 체계적인 코드를 기대할수 있고, 장기적으론 시스템 유지보수나 확장에도 장점이 있을 수 있다.

 

원칙

소프트웨어 설계 및 구현 과정에서 발생하는 복잡성을 관리하고, 유지 보수와 확장을 용이하게 한다.

  • 모듈화(Modularity)
    시스템을 여러 모듈로 분할하고, 각 모듈이 특정 기능만을 담당하도록 하는 방식이다.
    각 모듈은 독립적인 개발, 테스트, 배포를 할 수 있고, 모듈간의 결합도는 낮추되 응집도는 높히는 것이 좋다.
    (Loose Coupling, High Cohesion)
    모듈간의 의존성을 낮춰 각 모듈을 독립적으로 수정할 수 있어야하고(느슨한 결합), 모듈 내부 요소들이 밀접하게 결합되어 해당 모듈의 기능이 일관성 있게 수행하도록 하는 원칙(높은 응집도)
  • 추상화(Abstraction)
    복잡한 시스템을 이해하기 쉽도록 세부 사항을 감추고 중요한 개념만 드러내는 원칙
  • 캡슐화(Encapsulation)
    객체의 내부 상태를 숨기고, 외부에서 접근할 수 있는 인터페이스를 통해서만 상호작용하도록 하는 원칙

설계 원칙

"원칙은 도구일 뿐, 목표가 아니다"

원칙들을 무조건 따르는 것이 중요한 것이 아니라, 비즈니스 요구사항을 충족하면서 코드품질을 유지하는 균형을 찾는 것이 중요하다

 

SOLID 원칙

  • Single Responsibility Principle : 하나의 클래스는 하나의 책임만 가져야 한다.
  • Open/Closed Principle : 확장에는 열려 있고, 수정에는 닫혀 있어야 한다.
  • Liskov Substitution Principle : 자식 클래스는 부모 클래스를 대체할 수 있어야 한다.
  • Interface Segregation Principle : 특정 클라이언트를 위한 인터페이스를 분리
  • Dependency Inversion Principle : 고수준 모듈은 저수준 모듈에 의존하지 않아야 한다.

(내 생각이지만, solid 원칙이 절대적인지는 잘 모르겠다. 물론 확장성과 유지보수, 재사용에 장점은 있지만, 상황에 따라서는 solid 원칙을 다 따르다보면 복잡해질 수 도 있고, 빠른 속도로 개발하고 테스트해야하는 상황에서는 직관적인 코드를 작성하는 것이 좋을 때도 있지 않을까 싶다. 그래서 시간을 들여서라도 프로젝트 시작 전 설계를 잘해야할 것 같다. 말 그대로 가이드라인이라고 생각하니 마음이 편안해졌다.)

 

DRY 원칙

  • Don't Repeat Yourself : 중복 코드를 제거하여 유지보수를 쉽게 만듬

KISS 원칙

  • Keep It Simple, Stupid : 설계를 단순하게 유지

YAGNI 

  • You Aren't Gonna Need It : 현재 필요하지 않은 기능은 미리 구현하지 않음.

 

아키텍처 스타일

  • 레이어드 아키텍처 (Layered Architecture)
    Presentation, Business Logic, Data Access 계층으로 구성
    소프트웨어 시스템을 여러 계층으로 분리해, 각 계층이 특정 역할을 담당하게 하는 구조
    레이어라는 단어 의미와 맞게 각 계층은 자신보다 하위 계층에만 의존한다. (단방향 의존성)
    • 관심사 분리 (Separation of Concerns): 각 모듈이 하나의 책임만 가지도록 설계
    • 확장성 (Scalability): 수평적/수직적 확장
    • 느슨한 결합(Loose Coupling): 모듈 간의 독립성을 높임
    • 장점: 명확한 분리, 유지보수 용이
    • 단점: 계층 간 의존성이 커질 수 있다.
  • 모놀리식 아키텍처 (Monolithic Architecture)
    모든 기능이 단일 애플리케이션으로 동작
    구조가 단순하여 개발 초기에 이점이 있지만, 코드 규모가 커지면 유지보수와 확장이 어려울 수 있다.
    사용자 UI -> [사용자 관리, 주문 관리, 재고 관리, 결제 처리] -> 데이터베이스
    • 장점: 단순한 배포와 관리
    • 단점: 확장성과 유지보수에 어려움
    • 초기 개발 단계의 간단한 애플리케이션에 장점이 있음여러 모듈이 강한 의존성으로 결합되어 작은 변경에도 전체 시스템을 다시 빌드하고 배포해야하는 문제가 생길 수도 있다.
      그래서 기존 모놀리식 아키텍처의 단점을 보완한 모듈식 모놀리식 아키텍처란 것도 있다고..
  • 마이크로서비스 아키텍처 (Microservices Architecture)
    애플리케이션을 작은 독립적인 서비스로 나누어 각각 특정 비즈니스 기능을 수행하도록 설계한 아키텍처 패턴
    각 서비스는 독립적으로 배포 가능한 작은 서비스들과 각각의 데이터베이스를 가지고 있다.
    그래서 시스템의 확장성과 유연성이 향상되며, 특정 서비스의 변경이 다른 서비스에 미치는 영향을 최소화할 수 있다.
    또한, 각 서비스는 독립적으로 배포될 수 있어 대규모 시스템 개발에 적합하며, 서비스별로 다양한 기술 스택을 사용할 수 있어 서비스 별로 적합한 기술을 선택할 수 있다.
    • 장점: 독립적 배포, 확장성, 기술 스택 다양성
    • 단점: 네트워크 비용 증가, 복잡한 운영 및 배포, 데이터 일관성 유지
    • 사용사례: 대규모 애플리케이션, 다양한 기능을 가진 플랫폼(Netflix, Amazon..)
    • 모놀리틱 -> MSA
      우선 MSA로 전환해야할 명확한 목표를 세워야한다. (확장성, 팀의 생산성, 특정 모듈의 독립배포와 관리가 필요한지 등)
      트래픽 증가에 따른 확장성 문제를 해결해야할 수도있고, 유지보수나 배포 속도 개선을 위해 모듈을 독립적으로 분리해야할 수 도 있다.
      이렇게 목표가 명확해졌다면, 도메인을 주요 기능별로 나눠야 한다.(사용자 관리, 주문 처리, 결제, 알림 등..)
      그리고 의존성이 높은 모듈은 하나의 서비스로 묶고, 그렇지 않으면 의존성을 줄이는 리팩토링이 필요할 수 있다.
      각 도메인의 책임과 경계를 명확히 하는 것이 중요하다.
      초기 모놀리틱에서는 단일 데이터베이스를 사용했지만, MSA에서는 각 서비스가 자체 데이터베이스를 가지도록 설계해야하므로, 데이터 정규화 여부와 관계형/비관계형 DB 선택도 검토해야한다.
      서비스 간 데이터 직접 공유를 피하고, API나 메시징 시스템(Kafka 등)을 통해 통신한다.
      1. API Gateway 도입 : 클라이언트 요청을 각 서비스로 라우팅, 인증/인가 관리 (NGINX, AWS API Gateway..)
      2. 서비스별로 기능 분리
      3. 데이터 이관 (점진적 데이터 분리)
      4. 서비스 간 통신관리 (RabbitMQ, Kafka ..)
      5. CI/CD 파이프라인 구축 (Docker, K8s를 활용한 컨테이너화 및 오케스트레이션, Git Action등을 통한 자동화된 빌드/테스트/배포)
      6. 테스트(성능, 장애, 모니터링)
  • Event-Driven Architecture
    시스템 구성 요소가 이벤트를 통해 상호작용하도록 설계한 아키텍처 패턴
    이벤트 생산자, 이벤트 소비자가 있고, 이벤트 대기열을 관리하는 이벤트 중재자가를 통해 비동기적으로 통신한다.
    비동기 통신을 통해 시스템이 느슨하게 결합되며, 높은 확장성, 실시간 데이터 처리능력을 갖출수 있다.
    • 장점: 비동기 작업 처리, 확장성
    • 복잡한 이벤트 관리
    • 사용사례: 금융 시스템, 주문 처리 시스템
  • Serverless Architecture
    클라우드에서 함수 단위로 코드를 실행
    • 장점: 비용 효율적, 인프라 관리 불필요
    • 단점: 벤더 종속적, 디버깅 어려움
    • 사용 사례: 이벤트 기반 처리, 빠르게 배포해야 하는 프로젝트

설계시 고려해야할 비기능적 요구사항

  • 확장성
    시스템이 사용자 증가에 따라 성능을 유지할 수 있는가?
    수직 확장: 더 강력한 하드웨어 추가
    수평 확장: 더 많은 서버 추가
  • 성능
    요청에 대한 응답 시간이 충분히 빠른가
  • 보안
    데이터 암호화, 인증, 권한 관리는 어떤 방식으로 가져갈 것인가
  • 유지보수성
    코드와 설계가 얼마나 쉽게 수정될 수 있는가

 

 

 

 

레퍼런스

https://yozm.wishket.com/magazine/detail/2743/

'BackEnd' 카테고리의 다른 글

APM (Application Performance Management)  (1) 2025.06.22
[Redis] Redis, Redis Pub/Sub (Redis Stream)  (0) 2025.06.06
디자인 패턴  (0) 2025.01.14
로드 밸런서  (0) 2024.12.31
[bcrypt] 비밀번호가 관리되는 방식  (0) 2024.12.27