마이크로서비스 내부아키텍처 - 1회 : 데이터 중심 아키텍처의 문제점

Updated:

마이크로서비스 내부아키텍처 - 1회 : 데이터 중심 아키텍처의 문제점

마이크서비스 내부 아키텍처에 대해 살펴보자. 3회에 걸쳐서 기존 아키텍처의 문제점 및 이를 개선하고자 했던 아키텍처 변화양상과 이를 반영한 어플리케이션 구조에 대해 알아 보겠다.

이번 포스트에서는 1회로 기존 데이터중심 아키텍처의 문제점에 대해 살펴보자.

로버트 C 마틴(Robert c martin)은 그의 책 ‘클린 아키텍처(Clean Architecture)’에서 소프트웨어는 가치는 행위 가치와 구조 가치로 나눠지고 소프트웨어를 정말로 부드럽게(Soft)하게 해주는 것은 구조적 가치라고 하였다. 여기서 행위 가치는 소프트웨어의 기능을 말하며, 구조 가치는 소프트웨어 아키텍처를 말한다.

그는 토끼와 거북이의 경주를 예를 들며 빨리 가능 방법은 제대로 가는 방법이며 코드와 설계의 구조를 깔끔하게 만들려는 생각을 하지 않고 기능 구현 만을 목적으로 하면 엉망이 된 상황을 대처하는데 더 많은 비용이 든다는 점을 강조하였다. 우리는 실무에서 단기간의 프로젝트 동안 어플리케이션 설계나 구조에 신경 쓰지 않고 오직 기능 구현에만 몰두한 소프트웨어의 유지보수가 얼마나 힘든지 잘 알고 있다.

이런 소프트웨어들은 전혀 소프트 하지 않다. 이런 제품들은 새로운 형태의 UI나 기술이 추가되어야 한다고 할 때 거의 처음부터 새로운 시스템을 만드는 것과 마찬가지의 수정이 일어나야 되고 작은 기능 변경에도 그 파급효과 및 영향도를 알 수 없어 그에 따른 실제 변경 작업보다 다른 모듈의 영향도를 파악하기 위한 테스트에 더 많은 시간을 투자해야 한다.

특히 개발과 운영에 모든 책임을 가지고 있는 마이크로서비스팀 입장에서는 소프트웨어의 초기 개발 뿐만 아니라 지속적인 비즈니스의 변화에 빠른 대응을 할 수 있는 구조가 필요함은 당연한데 소프트웨어가 부드럽지 않다면 기민한 대응이 어려울 것이다.

이번 포스트 에서는 국내 소프트웨어들의 내부 아키텍처 문제점을 살펴보고 2회 포스팅을 통해 바람직한 어플리케이션 아키텍처 아이디어에 대해 알아보고, 3회 포스팅에서 마이크로서비스 내부 설계 시 고려해야 할 여러가지 어플리케이션 패턴에 대해 살펴보자.

비지니스 로직은 어디에? - 관심사의 분리

소프트웨어의 핵심은 비즈니스 로직(Business Logic)이라는 말을 많이 들어봤을 것이다. 비즈니스 로직이란 보통 시스템의 목적인 비즈니스 영역의 업무 규칙(Rule) , 흐름(Flow), 개념(Concept)들을 표현하는 용어이다. 개발자의 역할이란 문제 영역의 이런 비지니스 로직을 분석,이해하여 프로그래밍 언어라는 도구로써 잘 표현 하는 일이다. 또한 잘 표현한다는 것은 기능이 잘 동작하는 것과 더불어 이해하기 쉽고, 변경하기 쉬운 시스템을 만드는 것을 의미한다.

설계 원칙 중에 관심사의 분리( Separation of Concerns) 라는 원칙이 있다. 이는 시스템의 각 영역이 처리하는 관심사가 분리되어 잘 관리되어야 한다는 의미이고 이 원칙은 시스템을 이해,변경하기 쉽게 만들어 준다. 이 원칙에 따라 각 영역은 고유 관심사에 의해 분리되고 집중 되야 한다. 모듈화 및 계층화도 이런 원칙에 기인한다. 특히 비즈니스를 표현하는 비즈니스 로직 영역과 기술문제를 처리하기 위한 기술 영역은 철저히 분리하는 것이 좋다. 이는 비즈니스 로직은 기술보다는 오랫동안 지속되고 안정적이어야 될 어플리케이션 핵심 영역이기에 기술에 영향을 적게 받도록 설계하는 것을 강조 한 것에서 기인한다.

그렇게 했을 때 복잡성이 낮아지고 유지보수성도 높아진다. 특히 객체지향 분석 설계(OOD: Object Oriented Design)에서는 에서는 이런 비즈니스 로직을 이해하기 쉽게 구조화 하여 객체 모델로 표현하는 것을 강조해 왔다.

그러나 우리 업계의 SW의 실상은 어떠 한가? 말만 객체지향 분석 설계 방법이었을 뿐이지 한 동한 개발생산성의 강화라는 미명 아래 기술로 범벅이 된 소스코드를 기계적으로 찍어내는 MDD 의 유행이 지나갔고, 순수한 자바 객체(POJO: Plain Old Java Object)를 지향하고 철저한 관심사의 분리를 강조하는 스프링 프레임웍를 기반으로 한 정부 표준 마저도 객체 모델을 중심으로 활용하지 있지 않다.

특히 현장의 소스 코드들을 보면 관심사의 분리 원칙이나 비즈니스 로직을 표현하는 객체 모델은 온데 간데 없고 모든 업무 로직이 데이터 질의 구문인 SQL 문에 들어있는 경우가 대부분이다. 비즈니스 로직를 처리할 JAVA구문은 10줄 미만 인데 100라인 ~1000라인이 넘는 SQL문 또는 프로시저(procedure) 가 가득한 시스템이 대부분이다.

내가 경험한 한 프로젝트의 한 개발자는 이런 아주 복잡한 SQL문을 오직 자신밖에 관리할 수 밖에 없다고 자랑스러워하고 절대 다른 사람이 건드리게 하지 않았다. 이 개발자는 특정 벤더DB에 정통했고 모든 로직을 압축하여 하나의 SQL에 작성하는 것을 최고라고 여겼다. 코드의 가독성 보다는 쿼리 성능을 위한 SQL문의 최적화에 좀더 우선순위를 두었다. 물론 이 프로그램은 본인이 가장 잘 이해 하고 있었고 업무 성과도 높았다. 그렇지만 문제는 그의 부재였다. 그의 부재 시 아무도 그가 작성한 소스코드를 이해 할 수 없었고 따라서 변경할 수도 없었다. 그가 휴가라도 간다면 큰일이었다. 결과적으로 모든 업무 변경 사항이 그에게로 집중되고 의존 돼서 그의 뛰어난 능력에도 불구하고 그는 팀의 업무 병목점이 되고 있었고 비지니스 로직이 대부분 SQL에 몰려 있다 보니 지속적인DB 성능 저하로 데이터베이스도 병목점이 되고 있었다. 결국 이 시스템은 더이상 변경하기 힘들어져서 전면 재개발될 수 밖에 없었다.

어플리케이션 유지보수성이 높다는 의미는 특정 개인에 의존하는 것 보다는 어떤 누구라도 쉽게 어플리케이션을 이해할 수 있고 유지 보수 할 수 있다는 것을 의미한다.

비즈 민첩성을 위해서 앞서 언급한 MSA 외부 아키텍처 및 관계패턴들도 중요하지만 지금부터는 바람직한 어플리케이션 내부 구조 즉 어떤 누구나 서비스가 제공하는 비지니스 개념을 이해할 수 있어 쉽게 변경, 확장이 가능해서 유지보수성이 높아 질 수 있는 구조에 대해 살펴보자.

데이터베이스 중심 아키텍처의 문제점

그렇다면 무엇이 문제일까? 위의 사례처럼 국내 엔터프라이즈 실무에서 문제라고 인식하지 못하고 일반적이고 빈번하게 사용하는 방식에 대해 알아보자. 나는 이런 구조를 데이터베이스 중심 아키텍처라 부르고 싶은데 ‘데이터베이스 중심 아키텍처’ 란 먼저 특정 관계형 데이터베이스에 의존한 데이터 모델링을 수행한 다음에 이 물리 테이블 모델을 중심에 두고 어플리케이션 구현을 위한 사고를 하는 방식이다.

이런 구조는 일반적으로 아래 그림과 같은 구조로 정의된다. 일반적으로 스프링(Spring)을 활용한다면 컨트롤러(Controller), 서비스(Service), DBIO, DTO(Data Transfer Object) 로 구성되고 데이터 처리는 SQL매핑 프레임웍인 마이바티스(Mybatis)를 사용한다.

이런 구조에서 일반적으로 비즈니스로 로직은 서비스에 존재해야 한다고 말하지만 서비스에 존재하게 될 로직은 흐름 제어 로직 밖에 없다. 그 외 비지니스 개념과 규칙들은 앞의 사례처럼 테이블과 SQL 질의에 있게 된다. DTO는 질의를 통해 가져오는 Information Holder의 역할밖에 할 수 없다. 이런 구조가 이후 살펴볼 어플리케이션 로직 구성 패턴인 트랜잭션 스크립트 구조와 비슷한데 간단한 처리 로직의 경우는 편하지만 업무가 복잡해 지면 점점 그 복잡성을 제어 할 수 없게 된다.

데이터베이스 중심의 아키텍처

이런 구조는 업무 개념은 특정 저장 기술인 데이터베이스 테이블로 표현되고 특히 업무가 복잡해 질 수록 업무 규칙은 데이터 질의 기술 언어와 섞여 표현된다. 앞서 비즈니스 민첩성을 위해 유연성과 확장성이 중요하다 했다. 예를 들어 한 회사에서 비즈니스 특정 기능을 위해 읽기에 최적화된 NOSQL저장소로 교체하기로 결정했다고 하자. 그렇지만 이런 시스템구조에서는 저장소를 변경하려고 해도 쉽게 그럴 수가 없다. 왜냐면 기술과 비즈니스가 끈끈하게 붙어 있기 때문에 저장소 변경 시 모든 것을 다시 구현해야 해야 한다고 개발팀이 판단했기 때문이다.

또한 이런 데이터베이스 중심의 아키텍처에서의 성능 측면을 보면 이런 구조에서는 대부분의 성능을 데이터베이스에 의존한다. 서비스의 비즈니스 개념과 규칙이 대부분 데이터베이스에 표현되기 때문이다. 어플리케이션은 별로 할 일이 없다.

따라서 데이터가 쌓여 감에 따라 데이터베이스의 성능은 지속적으로 감소 할 수 밖에 없다. 이에 이를 위한 최적화 방법으로 데이터베이스 서버의 사양과 용량을 계속 증가시키고 질의문 튜닝에 몰두 할 수 밖에 없다. 앞서 클라우드 인프라를 사용 시 큰 장점인 사용량에 대해 탄력적으로 대응하는 방법인 자동 스케일 아웃이 의미가 없어진다. 정작 바쁜 것은 데이터베이스 이기 때문에 어플리케이션을 아무리 스케일 아웃해봐야 그 효과가 미미하다.

데이터베이스는 사실 데이터 저장 처리에 최적화된 시스템이다. 질의문도 비즈니스 로직을 처리하는 것을 위한 언어가 아니라 데이터 처리를 위해 최적화된 언어이다. 스토리지가 비싸고 한정적인 인프라 상황에서 최적의 성능을 발휘하기 위해 데이터베이스 중심의 아키텍처가 필요했던 시기가 있었다. 그렇지만 클라우드 시대에선 무궁무진한 인프라를 유연하게 사용할 수 있고 저장기술 또한 다양하게 선택할 수 있다. 예전처럼 웹과 관계형 데이터베이스만 고려해야 되는 상황도 아니다. 웹, 모바일, 명령어 창, IoT기기 등 여러 디바이스의 입출력이 지원되어야 하고 관계형DB, 메모리 DB, NoSQL DB, 메시지 큐까지 다양한 저장소 연계가 요구된다.

즉 이런 클라우드의 풍부한 자원환경에서는 어플리케이션 자체의 성능보다는 어플리케이션의 부드러움이 좀더 요구되는 시대이다. 따라서 위에 언급한 관심사의 분리 원칙에 따라 끈끈하게 결합되어 있던 비즈니스 로직 처리와 데이터처리를 철저히 분리하는 것이 받드시 요구된다.