기본적인 아키텍처에 대해서 정리를 해서 문서화 할 필요성을 느끼고 Basic한 레이어드 아키텍처에 대해서 분석하고 개인적인 견해를 간단히 정리해본다.
Layered Architecture는 '관심사에 분리(Separation of concerns)'에 따라 어플리케이션을 일정한 책임을 기준으로 논리적인 Layer로 분리한 아키텍처 패턴이다. 계층은 잘 정의된 인터페이스를 통해서 통신하며 보통 각 Layer는 한단계 아래의 Layer의 컴포넌트와만 상호작용한다. 그러나 그렇게 할 경우 발생하는 불편함들이 꽤 있기에 아래 단계 뿐 아니라 동일한 Layer상의 컴포넌트 끼리와도 상호작용 할 수 있게 설계하는게 보통이다.
사실 아키텍처라는 것이 가진 본래 목적이 좋은 소프트웨어를 만들기 위함이고 좋은 이라는 모호한 특징 중에서도 보통은 유지보수하기 좋은 그러니까 재사용성 높고 변경과 확장하기 쉬운 소프트웨어라는 것을 위한 것이다 보니 특정 아키텍처라고 반드시 어떤 룰과 형식을 따라야한다라고 볼 순 없다.
건강하기 위해서 하는 운동이 건강을 헤치면 본질에 충실하지 못한 것이듯이 좋은 소프트웨어를 위해서 적용하는 아키텍처 패턴이 좋은 소프트웨어를 만드는데 방해가 된다면 그것은 비정상적인 상황이라고 볼 수 있다. 물론 예시로 든 운동이라는 행위가 건강이라는 하나의 목적을 위해서 행해지는 것은 아니지만
그러다보니 본래라면 한단계 아래와만 상호작용이 가능하고 보통 3이나 4 정도 레이어를 가진 아키텍처로 많이 사용되지만 경우에 따라서는 레이어를 줄이거나 더 추가하는 방식으로 또 동일한 책임은 아닐지라도 같은 레벨을 가진 레이어를 만들어서 동일한 계층간의 상호작용이 가능한 방식으로도 설계가 가능하다. 그럴때는 정석적인 레이어드 아키텍처라고 보긴 힘들고 파생 패턴 정도로 봐야하겠지만
레이어드 아키텍처의 본질은 결국 관심사 분리를 통해서 프로그램을 적절한 책임을 가진 레이어들로 나누어서 재사용성이나 확정성을 높이는 것이고 그러자면 각 레이어의 책임이나 의존성을 잘 설계하는 것이 중요하다고 볼 수 있다.
일반적으로 레이어드는 3티어나 4티어 정도로 많이 사용되는데 계층을 물리적이거나 논리적인 계층으로 나뉜다.(원래 티어는 물리적 개념 레이어는 논리적 개념)
프로그램 자체가 가진 목적에 의해서 일반적인 경우에 필수적으로 사용자 인터페이스(사용자 액션을 받거나 결과물을 보여주는 계층)와 그 데이터를 가공하는 비즈니스 로직(프로그램의 목적), 그에 필요한 데이터들의 구조나 저장을 담당하는 부분있기에 그를 기준으로 3가지 레이어를 잡고 가는게 보편적이다. 물론 데이터를 저장하지 않을 경우 데이터 구조나 저장에 대한 부분의 필요성이 떨어질 것이고 자동으로 돌아가면서 따로 사용자의 액션을 받지 않는 프로그램이라면 사용자 인터페이스 부분에 대한 필요성이 떨어질것이다.
보통 사용자 인터페이스 부분을 프레젠테이션 레이어(Presentation Layer)로 지칭하는데 웹 시스템을 기준으로 보면 프론트엔드(Frontend)에 해당한다. 그리고 데이터를 가공하는 비즈니스 로직이 있는 부분을 보통 어플리케이션 레이어(Application Layer)로 지칭하고 웹 시스템 기준으로는 벡엔드(Backend)에 해당한다. 데이터를 저장하는 영역을 보통 데이터 레이어(Data Layer) 또는 데이터 엑세스 레이어(Data Access Layer)로 지칭하고 웹 시스템 기준으로는 보통 데이터베이스와 ORM에 해당한다.
모놀리스식으로 서비스를 구성한다면 물리적으로 프레젠테이션과 어플리케이션의 티어가 구분 되지 않았을 것이고 데이터 레이어의 경우 물리적으로 구분된 데이터베이스 티어와 그 데이터베이스에 접근하기 위한 로직을 구분한 논리적 레이어가 결합된 복합 구조로 구성 되어 있을 것이다.
벡엔드서버, 프론트엔드 서버 구조로 서비스를 구성한다면 물리적으로 프론트엔드와 벡엔드 그리고 데이터 베이스가 나누어져 있을 것이다. 그리고 벡엔드나 프론트 서버 내부에서도 각각 동일하게 레이어를 쪼갤 수 있다. 여기서 볼 수 있듯이 사실 물리적이고 논리적인 차이는 소프트웨어의 관점에서 볼때는 사실 그렇게 중요한 개념은 아니라고 볼 수 있다. 실제로 인프라를 고려하는 설계 관점에서 보았을때는 유의미한 구분이지만 소프트웨어 적인 측면에서만 보았을때는 물리적이냐 논리적이냐는 시스템을 나누고 설계하는 측면에서는 그렇게 중요한 개념은 아니다. 왜냐하면, 물리적이든 물리적이지 않든 이미 논리적인 구분을 하기 때문이다.
그렇기에 대부분 티어와 레이어라는 용어에 상관없이 물리적이고 논리적인 계층을 혼용하는 것으로 보이는데 실제로 아키텍처를 인프라적인 측면까지 고려하는 상황이 아니라면 사실 이부분은 억지로 물리나 논리를 쪼개서 접근하려는 시도가 본질적이라고 보기 힘들고 그렇기에 대부분은 혼용하는 것으로 보인다.
더해서 프로그램 복잡도와 중요도에 따라서 레이어를 줄이거나 추가하기도 하는데 계층을 쪼개는 본질적인 요소는 재사용가능성, 그리고 유지보수의 용이함을 고려하는 것이라고 볼 수 있다.
그리고 해당 아키텍처의 핵심적인 부분인 의존성의 경우 바로 아래 계층 뿐아니라 그 아래까지도 내려가기도 하는 문제가 발생하기 쉬운데 레이어드 아키텍쳐의 안티 패턴중 싱크홀 패턴이 불필요하게 레이어를 거쳐가며 성능을 낭비하는 것을 경계한다지만 그럴 경우에는 기존 레이어 구조에서 독립적인 구조로 가져간다거나(유틸) 아니면 동일한 위계를 가진 다른 레이어로 따로 구분 짓는게 더 유의미하다고 보인다. 어떻게 보면 컴포넌트 개념이라 생각 되겠지만 레이어 자체가 일정 책임에 나뉜 논리적인 계층이라는 의미가 있으니 실제로는 동일한 수직층에 위치하는 조금 다른 책임을 가진 수평층으로 보는게 더 적절하다. 그리고 결국 의존성이나 추상화 단계를 일관성 있게 관리한다면 의존성이나 추상화가 제각각인 구조보다 상대적으로 그 구조를 이해하는데 크게 어렵지는 않기에 손쉬운(?)레이어드 구성을 가져가면서 최대한 유연하게 단점을 케어 할 수 있다.
예를 들면 기본적으로 P,A,D 3티어 구조를 가져가고 그 사이에 B나 S 같은 레이어가 추가적으로 필요한 부분이 존재한다 할지라도 기본적으로 P, A, D 3티어 구조의 의존성을 유지하면서 P가 A 뿐 아니라 B나 S에 의존하고 B나 S가 서로 의존하는 방식으로 의존성을 관리 할 수 있기 때문에 구조적인 유연성을 보장하면서도 의존관계나 추상화 단계를 적절하게 유지 할 수 있다. 물론 복잡도가 늘어난다면 이해하기 힘들어지는 것은 마찬가지겠지만 그럴때는 다른 해답을 찾는게 더 적절할테니까
결론적으로 레이어드 아키텍처란?
수직으로 구성되어서 물리적인 계층인 티어와 논리적인 계층인 레이어를 나누어서 시스템을 유지보수하는 것을 넘어서 비레이어, 수직레이어, 수평 레이어를 나누고 의존 관계를 적절하게 관리해서 시스템의 구성요소의 재사용성과 유지보수의 편리함을 추구하는 아키텍처 패턴이라고 볼 수 있다.
'개발' 카테고리의 다른 글
ChatGPT에 대한 감상 (0) | 2023.01.21 |
---|---|
기술부채에 대하여. (0) | 2022.05.11 |
SOLID 원칙에 대하여 (0) | 2022.05.04 |
클린코드와 표준 (0) | 2022.04.28 |
JWT 간단정리 (0) | 2022.01.27 |