Skip to content

3.3 시스템 아키텍처 선정 #1478

@jongfeel

Description

@jongfeel

3.3 시스템 아키텍처 선정

3.3.1 아키텍처 선정 시 주요 고려 사항

  • 아키텍처 선정은 트레이드오프 과정임을 인식한다.
  • 아키텍처 패턴을 활용한다.

아키텍처 선정은 트레이드오프다

우선적으로 고려해야 할 품질 속성을 선정하고, 이를 바탕으로 아키텍처 드라이버 목록을 정리해야 합니다.

아키텍처 선정은 단순한 선택이 아니라 각 품질 속성을 조정하며 최적의 균형점을 신중히 찾아가는 트레이드오프 과정입니다.

이 과정에서 사용한 평가 방법과 결과는 기록해 두어 나중에 다시 검토할 수 있도록 해야 합니다.
이를 위한 방법으로 ‘아키텍처 의사 결정 기록 architecture decision record (ADR)’이 있습니다.

아키텍처 패턴을 활용한다

패턴은 다양한 문헌에서 각 특징과 적합성, 사용 시 주의점 등을 포함하여 체계적으로 정리되어 있습니다.
아키텍트는 개발 업계의 선배들이 축적해온 자산으로서 이러한 패턴을 적극적으로 활용해야 합니다.
다만, 아키텍처 스타일과 아키텍처 패턴은 개념의 범위나 관점이 서로 다를 수 있습니다.

아키텍트는 설계 과정에서 시점마다 주목하는 추상화 레벨과 관점에 따라, 적절한 패턴을 선택하는 요령을 익혀야 합니다.

3.3.2 시스템 아키텍처 검토

모놀리식 아키텍처와 분산형 아키텍처

모놀리식 아키텍처monolithic architecture는 시스템에 필요한 모든 기능을 하나의 대규모 애플리케이션으로 구축하는 방식입니다.
이러한 대규모 애플리케이션을 모놀리스monolith 라고 부르며, 이는 ‘단일형’이라는 의미입니다.

분산형 아키텍처distributed architecture는 시스템의 기능을 여러 개로 분할하여 각각 독립적으로 배포할 수 있는 애플리케이션으로 구축하는 방식입니다.
분산형 아키텍처에서 개별 애플리케이션은 보통 서비스service로 불립니다.

모놀리식 아키텍처의 장점과 단점

모놀리스는 단순함이 가장 큰 특징이며, 다음과 같은 장점이 있습니다.

  • 소스 코드의 관리, 빌드, 배포가 간편하다.
  • 시스템 전체를 대상으로 테스트하기 쉽다.
  • 트랜잭션이 단일 애플리케이션 내에서 완료되므로, 정합성 consistency 유지에 용이하다.
  • 기술 스택을 통일할 수 있어 IT 거버넌스 governance 적용, 즉 시스템 전반의 통합 관리가 쉽다.

한편, 다음과 같은 단점도 있습니다.

  • 빌드와 배포에 시간이 많이 걸린다.
  • 모듈과 컴포넌트 간 의존성이 복잡해져 거대한 진흙 덩어리 패턴에 빠지기 쉬우며, 이로 인해 유지보수성이 저하될 수 있다.
  • 작은 변경에도 전체 애플리케이션의 빌드와 배포가 필요하다.
  • 일부 기능 부하나 충돌로 인해 시스템 전체에 위험(성능 저하, 정지 등)이 발생할 수 있다.
  • 스케일링이 어렵고, 특히 단일 데이터베이스에서 병목 bottleneck 이 발생하기 쉽다.
  • 각 모듈 및 컴포넌트 구현에 필요한 라이브러리 사용으로 DLL 지옥(DLL hell, 버전 충돌 문제)이 발생하거나 종속성 오류가 생기기 쉽다.
  • 단일 기술 스택은 구현과 기술 도입 모두에 제약이 될 수 있다.

분산형 아키텍처의 장점과 단점

분산형 아키텍처는 다음과 같은 장점이 있습니다.

  • 빌드 및 배포 시간이 짧다.
  • 서비스 단위로 독립적인 배포가 가능하여 시스템의 어질리티가 높아진다.
  • 각 서비스의 소스 코드가 적어 유지보수하기 쉽다.
  • 부하가 큰 서비스만 선별적으로 확장할 수 있다.
  • 서비스별로 적합한 기술 스택과 데이터베이스를 사용할 수 있다.
  • 서비스별로 최적의 애플리케이션 아키텍처를 채택할 수 있다.
  • 서비스 단위로 재사용하기 쉽다.

한편, 다음과 같은 단점도 있습니다.

  • 소스 코드와 버전 관리가 복잡해진다.
  • 여러 서비스를 운영하며 상태를 모니터링하거나 장애 원인을 파악하기 어렵다.
  • 트랜잭션이 여러 서비스를 넘나드는 경우, 데이터 정합성을 보장하기 어렵다.
  • 서비스 간 통신이 오버헤드overhead(처리 시간이나 리소스 소모 증가)되어 응답 속도를 떨어뜨릴 수 있다.
  • 여러 서비스가 마스터 데이터 master data (공통 참조 정보)를 공유하는 과정에서 동기화 등 관리 이슈가 생기기 쉽다.
  • 적절한 서비스 분할이 어렵고, 아키텍처 설계에 고도의 판단이 요구된다.

서비스 분할을 해야 할까?

모놀리식 아키텍처로 충분하다면 굳이 서비스를 분할할 이유가 없습니다.
소규모 시스템의 대부분은 모놀리스로 구축하는 것이 더 적합합니다.
그러나 모놀리식 아키텍처의 단점으로 인한 실질적인 피해가 허용할 수 없는 수준이라면 분산형 아키텍처를 고려해야 합니다.

3.3.3 분산형 아키텍처의 대표적 설계 패턴

서비스 기반 아키텍처

서비스 기반 아키텍처에서는 시스템을 구성하는 여러 서비스가 단일 데이터베이스를 공유하는 것이 기본적인 방식입니다.
또한 각 서비스는 비교적 큰 단위로 구성되며, 트랜잭션은 단일 서비스 내에서 완료됩니다.

마이크로서비스 아키텍처

각 마이크로서비스는 독립적인 전용 데이터베이스를 가지며, 서비스 간 데이터는 완전히 분리됩니다.
서비스 기반 아키텍처와 비교하면 개별 서비스 단위가 더 작아지는데, 이러한 특성 때문에 마이크로서비스라고 불립니다.
이로 인해 사용자의 요청을 처리하는 과정에서 다른 마이크로서비스를 호출하는 경우가 빈번하게 발생 합니다.
트랜잭션의 경계가 여러 서비스를 넘나드는 경우도 있습니다.

API를 통합하는 레이어를 경유하는 경우가 많습니다.
이 계층을 API 게이트웨이 gateway 라고 하며, 주요 목적은 다음과 같습니다.

  • 사용자 인터페이스에서 다수의 작은 단위의 서비스 호출(라운드 트립, 요청-응답의 왕복)이 발생하는 것을 방지한다.
  • 인증과 승인 등 횡단 관심사 cross -cutting concerns (공통 기능)를 한곳에서 처리한다.
  • 사용자 인터페이스가 개별 서비스에 직접 의존하지 않도록 보호하고 감춘다.
  • 여러 개의 작은 서비스 호출을 하나로 모아 집약한다.

COLUMN: 모듈형 모놀리스

모놀리스를 하나의 기능 단위로 적절히 모듈화하여 모듈 간 결합도를 낮추는 방법이 있습니다.
이 개념을 적용하면 배포 단위는 하나로 유지하면서 내부적으로 독립된 모듈들이 느슨 하게 결합된 애플리케이션을 구성할 수 있는데, 이러한 방식을 모듈형 모놀리스modular monolith라고 합니다.

모듈끼리 의존성을 많이 가져가지 않기 위해 다음 규칙을 따라야 합니다.

  • 모듈 간 연계는 명확하게 정의된 큰 단위 서비스 인터페이스를 통해 이루어져야 한다.
  • 다른 모듈의 데이터베이스에 직접 의존하지 않아야 한다.

데이터베이스를 완전히 분리하는 것은 현실적으로 쉽지 않으므로, 테이블 구조를 논리적으로 구분하는 단위인 데이터베이스 스키마database schema로 나누어 관리하는 방법도 고려할 수 있습니다.

모듈형 모놀리스로 애플리케이션을 구축해 두면, 향후 필요에 따라 마이크로서비스로 전환하기 쉬운 장점도 있습니다.

3.3.4 서비스 분할

패턴의 적용 방침

아키텍처 스타일 중 각 스타일이 지향하는 개념과 목적을 충분히 이해한 후 필요에 따라 적절히 조합하고 조정하여 우리 환경에 가장 적합한 아키텍처를 적용하는 것이 중요합니다.

서비스 분할의 과정

업무 기능의 관점에서 시스템을 논리적으로 서브시스템으로 분할합니다.
이때 도메인 주도 설계(DDD)의 분석 기법을 활용하여 경계 지어진 컨텍스트로 나누는 방법도 효과적입니다.

논리적 분할을 수행한 후, 물리적 분할을 검토합니다.

처음부터 모든 시스템을 마이크로서비스로 구축하는 것은 오히려 안티패턴으로 간주될 수 있습니다.
그 이유는 시스템의 초기 구축 단계에서 최적의 서비스 경계를 명확히 설정하는 것이 쉽지 않으며, 과도한 분할로 인해 시스템의 복잡성이 증가하고 운영 및 유지보수 비용이 급증할 위험이 있기 때문입니다.

트랜잭션 경계

트랜잭션의 정합성을 확실히 보장하려면 2단계 커밋two-phase commit을 지원하는 프로토콜이나 미들웨어를 사용하는 것이 필수적입니다.
한편, ‘마이크로서비스적’ 사고방식으로 서비스 간 강한 결합을 피하면서 결과적 일관성eventual consistency을 확보하는 방안을 검토해 볼 수도 있습니다.

Saga 패턴

마이크로서비스 아키텍처에서 여러 서비스에 걸친 분산 트랜잭션 중 일부가 실패 했을 때, 결과적 일관성을 달성하기 위한 대표적인 아키텍처 패턴이 바로 Saga 패턴 입니다.

데이터 불일치를 어떻게 처리하는 첫 번째 방법은 각 서비스에서 최초로 수행하는 처리를 준비 단계에서 보류하는 방식입니다.

또 다른 방법은 오류가 발생한 경우에 한해, 완료된 트랜잭션을 취소하는 별도의 트랜잭션을 실행하는 방식입니다.
이처럼 결과적 일관성을 유지하기 위해 조정 작업을 수행하는 트랜잭션을 보상 트랜잭션compensating transaction이라고 합니다.

두 방식은 장단점이 공존하는 트레이드오프 관계라고 할 수 있습니다.
이러한 점을 고려하면, 서비스를 분할할 때는 가능하면 여러 서비스에 걸친 분산 트랜잭션이 발생하지 않도록 설계해야 한다는 교훈을 얻을 수 있습니다.

Saga 패턴을 구현하는 방법으로는 다음 두 가지 방식이 있습니다.
먼저, 오케스트레이션orchestration은 앞서 예로 든 주문 처리 서비스처럼 서비스 간 흐름을 조정하는 방식입니다.
반면 코레오그래피choreography는 중앙에서 조정하는 역할 없이 각 서비스가 자율적으로 상호 조정하는 방식입니다.
관련된 서비스의 수가 적거나 단순한 경우를 제외하고는 대체로 오케스트레이션 방식을 채택하는 것이 좋습니다.

3.3.5 서비스 분할의 사례 연구

서브시스템 분할의 예

서브시스템을 분할할 때는 업무 프로세스의 흐름뿐 아니라 그 과정에 참여하는 사용자(업무 주체)의 차이도 함께 고려해야 합니다.

서비스 분할의 예

...

COLUMN: BFF 패턴

각 클라이언트 애플리케이션별로 전용 API 게이트웨이를 마련하는 방식을 BFF(backends for frontends)패턴이라고 합니다.

BFF 패턴을 적용하면, 웹 앱과 모바일 앱 전용 BFF를 각각 구성할 수 있습니다.

BFF 패턴은 SOLID 원칙 중 인터페이스 분리 원칙(ISP)을 아키텍처 레벨로 확장하여 적용한 패턴이라고 볼 수 있습니다.

Metadata

Metadata

Assignees

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions