[BACKEND] Layered Architecture의 단점은?

Block Odyssey Tech Blog
10 min readApr 19, 2023

--

기억에 남는 프로젝트 중 Layered Architecture로 구성하고 개발된 프로젝트가 있습니다.
많은 아키텍처 및 설계 방식이 있지만 왜 Layered Architecture를 선택 하게 되었는지와 추가적으로 어떤 방식들을 적용해서 개발을 진행하고 있는지에 대해 공유 드릴까 합니다!

아키텍처란?

시스템의 구조, 행위, 뷰를 정의하는 개념적 모형으로써 어떠한 시스템을 만들기 위한 각 컴포넌트가 무엇이고 어떠한 정보 교환 및 상호 방식으로 진행되는지, 각각 어떤 역할을 수행할지 정의하고 세분화 및 구조화를 목적을 가진다 라고 정의 할 수 있습니다.

진행에 앞서 몇 가지 아키텍처에 대해 간략히 소개 드릴까 합니다.

Layered Architecture

단순하고 일반적으로 가장 널리 사용되고 있는 표준 아키텍처 입니다. 구성되는 계층에 따라 N-tier Architecture 라고도 불리며 *모놀리식 아키텍처 중에 하나 입니다.

*모놀리식 아키텍처 : 모든 비즈니스 관련 사항을 함께 결합하는 하나의 코드 베이스를 갖춘 대규모의 단일 컴퓨팅 네트워크 입니다.

특징

Layered Architecture 패턴에서 레이어의 구성 갯수나 유형을 명시하고 있지 않지만, 일반적으로 Presentation, Business, Persistence, Database의 4개의 레이어로 구분합니다.
(단순하거나 복잡할 경우 3~5개 로 나뉠 수 있습니다.)

  • Presentation Layer
    :
    소프트웨어 시스템과의 사용자 상호 작용하는 UI로 표현하고 서버와의 통신을 처리하는 계층 입니다. (View, Controller)
  • Business Layer
    :
    기능적 요구 사항 달성과 관련된 측면을 처리합니다. 구성요소는 Service와 Domain Model 등이 있는데, 경우에 따라 Service와 Domain Model을 별개의 계층으로 나누어 분리하는 경우도 있습니다.
  • Persistence Layer
    :
    알고리즘 및 프로그래밍 구성 요소를 담당합니다. (Repository, DAO)
  • Database Layer
    :
    데이터를 저장하고 관리하는 계층입니다. (MySQL, MariaDB, PostgreSQL, MongoDB 등)

Layered Architecture의 주요 특징 중 하나가 바로 각각의 나뉘어진 계층은 수직적으로 격리되어 배치된다는 점입니다.
이러한 구조에서 각 레이어는 다른 레이어와 독립적인 상태이므로 각각의 레이어의 내부 동작을 알 수 없게 됩니다.
상위 레이어는 바로 하위 레이어에만 open, closed 상태로 연결되고 요청되며, 특정 도메인을 변경하려면 모든 레이어를 변경해야 하기 때문에 도메인 변경에 대한 어려움이 존재합니다.

Layered Architecture에서는 특정 레이어가 아무런 로직을 수행하지 않고 들어온 요청을 그대로 다시 하위 레이어로 내보내게 되는 경우가 발생하곤 하는데 이를 ‘싱크홀 안티 패턴’이라 합니다.
이러한 흐름은 불필요한 객체 초기화 및 메모리를 소모하며 성능 저하의 원인이 되며, 전체 흐름 중 20%정도의 싱크홀이 발생한 경우면 괜찮은 수준이라고 할 수 있습니다.

DDD(Domain Driven Design)

DDD(Domain Driven Design), 도메인 주도 디자인이란 도메인 패턴을 중심에 놓고 설계하는 방식으로써 ‘도메인 주도 패턴’이라고도 부릅니다.
복잡한 Application을 보다 쉽게 만들 수 있도록 하는 목적이 있습니다.

도메인이란?

사전적으론 ‘정보와 활동의 영역’을 말하는데, 쉽게 말해 실세계에서 사건이 발생하는 집합 이라고 생각하면 쉽습니다.

DDD의 핵심 목표는 ‘Loose coupling’, ‘High cohesion’ 입니다.
즉 모듈간에 의존성은 최소화 하고 응집성을 최대화한다는 것입니다.

DDD는 Strategic Design(개념 설계)와 Tactical Design(구체적 설계)로 나눌 수 있습니다.

설계 방식

DDD의 Layer는 크게 3개의 Layer로 구분됩니다.

  • Application Layer
    -
    도메인 및 인프라에 따라 다르며 인프라는 도메인에 종속되지만 도메인은 모든 계층에 종속되지 않습니다.
    - 주로 도메인과 Repository를 바탕으로 실제 서비스(API)를 제공하는 계층입니다.
  • Domain Layer
    -
    Entity, VO(Value Object)를 활용하여 도메인 로직이 진행되는 계층입니다.
  • Infrastructure Layer
    -
    쉽게 말하면 외부와의 통신(ORM, DB, NoSql)을 담당하는 계층입니다.

CQRS

CQRS는 Command Query Responsibility Segregation 의 약자로 단어 그대로 해석하자면 ‘명령과 쿼리의 책임을 분리한다’라는 의미입니다.

일반적인 CRUD 아키텍처 기반에서 개발, 운영시 갈수록 다양해지는 고객의 니즈와 고차원적인 UX, 급변하는 요구사항에 Domain Model은 초기 설계 의도와는 다르게 다른 방향으로 변하게 됩니다.
그러다 보면 각 업무 영역에서 필요치 않는 Domain 속성들로 인해 복잡도도 증가하게 되는데요.
이러한 문제점을 해결하고자 ‘명령을 처리하는 책임과 조회를 처리하는 책임과 역할을 구분’ 한다는 것 입니다.

CQRS 패턴을 적용하기 위한 방법으론 최소 3가지 방법이 있는데 그 중에서 대중적이고 가장 널리 알려진 예시를 설명해볼까 합니다.

Event Sourcing Model

Event Sourcing 이란?

Application 내의 모든 Activity를 이벤트로 전환해서 Event Stream을 별도의 Database에 저장하는 방식을 말합니다.
Event Stream을 저장하는 Database에는 오직 데이터 추가만 가능하고 계속적으로 쌓인 데이터를 Materialized 시키는 시점에서 그때까지 구축된 데이터를 바탕으로 조회가 되는 대상 데이터를 작성하는 방법을 말합니다.

Event Sourcing 의 Event Stream은 오직 추가만 가능하고 필요한 시점에 Materialized 단계를 거쳐서 처리하는 구조를 가졌다는 점에서 CQRS의 Model 분리 관점에서 성능이 좋다고 여겨지기 때문에,
대부분의 CQRS 패턴이 Event Sourcing이 적용된 구조를 따르게 됩니다.

MSA (MicroService Architecture)

대용량 웹 서비스가 늘어남에 따라 정의된 아키텍처로 SOA(service-oriented architecture)에 근간을 두고 있습니다.
SOA가 엔터프라이즈 시스템이 중심이라면 MSA는 SOA 사상에 근간을 두되 대용량 웹 서비스 개발에 맞는 구조로 사상이 경량화되고 대규모 개발팀의 조직 구조에도 맞도록 변형된 아키텍처 입니다.

위 그림을 보시면 스스로 돌아 갈 수 있는 작은 서비스와 독립적 배포 기능 두개의 키워드가 MSA의 핵심적인 부분을 잘 설명해준다고 생각합니다.

장단점

유연한 배포 및 신속성,
즉 변경되어야할 서비스만 변경하고 재배포 하면 되기 때문에 전체 시스템의 영향을 최소화한 수준에서 빠르게 배포를 진행 할 수 있습니다.

또한 확정성이 용이합니다.
모노리틱 아키텍처는 서버 부하시 전체 시스템을 늘려줘야하는 반면, MSA는 부하가 많은 특정 서비스에 대해서만 서비스 컴포넌트만 확장해주면 됩니다.

여러가지 장점을 제공하는 대신 그만한 단점도 가지고 있는데,
성능 관련해 MSA는 서비스 간의 호출을 위해 API 통신을 이용하기 때문에 값을 JSON 혹은 XML에서 데이터 모델로 변환하는 마샬링 오버헤드가 발생하고 이 메시지들이 네트워크로 전송되기 때문에 통신 비용이나 Latency가 늘어나게 됩니다.
또한 테스트 및 트랜잭션 처리시 분리된 여러 시스템을 봐야하기에 복잡도가 증가하고 많은 리소스를 필요로 합니다.
운영 관점에서도 확인해야할 대상 시스템이 늘어나고 서로 다른 기술을 사용 할 수 있기에 필요한 기술의 수도 늘어나게 됩니다.

Layered Architecture 선택 배경

Layered Architecture를 선택한 배경으로는 우선 진행했던 프로젝트 목표 일정이 짧았었고, Domain도 Business 로직이 그리 복잡하지 않았습니다.

이러한 상황 속에서 다양한 Architecture를 살펴보았고 그중에서 학습비용이 낮고 코드품질을 유지할 수 있는 기준으로 trade-off를 고려한 결과,
추후 서비스가 커질수록 복잡도와 확장성이 떨어지지만 앞서 말씀 드린데로 도메인이 복잡하지 않았으며 확장성보단 단기적으로 일관성을 가져가야된다는 판단하에 Layered Architecture 선택해서 추진하게 되었습니다.

DTO 정의 (Data Transfer Objects)

일반적인 요청은 CRUD 형태로 오는데 데이터 요청 부분과 검증 로직의 구현으로 인한 중복을 어떻게 할것인가, 그리고 어느 계층의 범위까지 사용해야 하는가에 대해 고민을 많이 했습니다.

결론적으론 검증 로직 부분이 필요한경우 코드상 중복이여도 분리하는것이 좋다고 생각했고 계층 범위는 Controller — Service, Service — Repository 로 지정하여
사용한 DTO는 분리하되, DTO가 완전히 동일하다면 중복해서 사용해도 좋을것으로 판단 했습니다.

끝으로

1986년 ‘프레드 브룩스’가 쓴 소프트웨어 공학 논문에서 은탄환의 존재에 대해 최초로 언급했는데, 이와 동시에 ‘소프트웨어 개발의 복잡성을 한번에 해소할 마법같은 솔루션(은탄환)은 없다’고 선언하였습니다.

스프트웨어는 복잡성을 내포하고 있으며 여러가지 문제를 포함하고 있는데, 이러한 문제를 단번에 해결할 기술, 개발, 관리 방법은 없으나, 지속적인 혁신을 통해서 필수적으로 복잡성은 개선할 수 있다고 논문에서는 말한다.
-
프레드 브룩스, 1986 -

이처럼, 모든 문제를 해결해주는 완벽한 아키텍처는 아직까지는 없다고 생각합니다.

앞으로 대규모 트래픽이 발생하는 프로젝트 혹은 기존 프로젝트가 확장되고 변경되게 된다면,
개발자 위치에선 아키텍처의 사용 이유와 특징을 잘 이해하고 설득력 있는 구조와 설계에 대한 수준 높은 고민, 그리고 기술적인 노하우를 미리 갖추어서
그 순간 순간의 상황에 맞게 최선의 선택과 함께 준비 하는것이 바람직한게 아닌가 생각 합니다.

좋은 약이라고 하더라도 효능과 복용법을 잘 숙지하고 복용을 해야되는데, 남들이 다 좋다고 무조건 복용하는건 오히려 독이 될 수 있다고 생각합니다.

기회가 된다면, 새로운 아키텍처의 도입 과정과 설계에 대한 고민 등 어떠한 노력들을 기울이고 진행했었는지 공유 드리도록 하겠습니다.

--

--