SOLID의 중요성과 아키텍처 설계
SOLID의 중요성과 레이어 설계
작은 프로젝트에서는 크게 문제가 없었지만, 기능이 많아지고 비즈니스 로직이 많아 지면서 스파게티 코드가 생기기 시작하였습니다. 그래서 이러한 문제들을 해결하고자 멀티 모듈을 도입을 하면서 Layerd architecture를 도입하게 된 스토리를 풀어보려고 합니다. 설계를 진행하다 보면 문제들이 많이 생기는데 우아한형제들 기술 블로그에서 작성한 멀티모듈설계이야기 를 참고하면서 설계를 했습니다. 여러분들도 보시면 도움이 많이 될 거 같습니다.
SOLID의 부재
Spring을 공부하면 MVC 패턴에 대해서 배우게 됩니다. 저희 팀도 이를 기반으로 Controller, Service, Repository로 레이어를 구분하여 개발을 시작했습니다. 초기에는 기능이 한두 개 있을 때는 큰 문제가 없었지만, 기능이 5개 이상 넘어가면서 비즈니스 로직이 많아지고 서비스 간 의존성이 강해지는 문제점이 발생했습니다. 더 큰 문제는 Repository에 로직이 다양한 서비스와 연결되면서 구분이 어려워지는 것이었습니다. 이 문제를 회의 때 이슈로 제기했고, 더 커지기 전에 해결책을 찾아야 했습니다.
회의 중에 이렇게 된것은 SOLID 원칙을 지키지 않아 발생한 문제를 제기하였고, 팀원들은 공감했습니다. 그래서 문제를 해결하기 위해 다양한 비슷한 로직을 하나의 서비스에서 처리하여 중복 코드를 제거하고, Repository는 하나의 로직에서만 호출하도록 하여 의존성 문제를 해결하기로 했습니다. 그러나 이러한 접근 방식은 오히려 더 큰 문제를 초래했습니다.
총체적 난국의 시작..
책임만 생각하며 작선한 코드베이스는 스파게티 코드(spaghetti code)가 생성되기 좋은 환경이 되어 버렸습니다. 책임 부여로 코드의 중복은 많이 줄었지만, 서비스에 비즈니스 로직이 점점 추가되면서 문제가 생기기 시작했습니다. 예를 들어, "Auth 서비스에 User의 기능이 필요하네, 이거 연결해야겠다", "Intranet 서비스에서는 User 정보를 참조해야 하니 연결해야지", "User에서 Auth의 기능이 필요한데?"와 같은 상황이 발생하며 다양한 순환 참조 문제가 생겼습니다. 단순히 책임을 부여만 하는것과 서비스 레이어를 하나만 두는 것으로는 이 문제가 해결되지 않을 것 같았습니다.
더 큰 문제는 기능이 추가되면서 Controller에 다양한 행위가 생기고, 이로 인해 Service 레이어 간의 의존성이 문제가 되었다는 점입니다. 서로 간에 의존하게 되면서, 정작 Admin 모듈에 필요 없는 코드들까지 모두 의존해야 하는 상황이 발생했습니다. 이는 인터페이스 분리 원칙(ISP, Interface Segregation Principle)에 위배되는 것이었으며, 이러한 문제는 설계상 큰 결함으로 판단되었습니다.
SOLID을 지키고 레이어로 구분짓자
개발을 진행하면 완성은 할 수 있더라도 유지관리 문제가 더 크게 발생할 것으로 판단하여, 프로젝트를 잠시 중단하고 팀원들과 함께 SOLID 원칙과 클린 아키텍처(Clean Architecture)를 공부하기로 했습니다.
이후, 공부한 내용을 바탕으로 회의를 진행하면서 소프트웨어 아키텍처를 어떻게 설계해야 문제가 없을지 논의하였고, 레이어드 아키텍처(Layered Architecture)를 이용해 각 레이어 간에 명확한 책임을 부여하기로 결정했습니다.
저희는 총 3개의 레이어로 구성된 아키텍처를 설계하였습니다: Controller, Delegator, Domain. 이 중 Delegator 레이어에서는 비즈니스 로직을 조립하는 역할을 맡게 하였습니다. Domain 레이어에는 각 기능에 대한 책임지도록 서비스들을 구성했습니다. Domain 서비스들은 BusinessService, MasterService, ReplicaService, RepositoryDao, Repository로 구분되며, 각 서비스는 자신의 책임만을 담당하고 다른 처리는 하지 않도록 설계되었습니다. 이로 인해 Delegator는 Domain의 서비스들을 호출하여 조합하는 역할을 수행하게 되면서 스파게티 코드와 같은 의존성 문제를 해결할 수 있었습니다.
설계는 중요하다
이번 설계를 통해 강한 결합(Tight Coupling)은 많이 줄어들었지만, 여전히 Delegator에는 일부 남아있어 이를 해결하는 것이 숙제로 남았습니다. 이 프로젝트는 완성과 서비스를 배포하는 것도 목표로 하고 있어서 다양한 문제를 접하여 좋은 경험이 되었습니다. 특히, 이번 프로젝트를 통해 SOLID 원칙의 중요성을 제대로 느낄 수 있었습니다. 특히 우아한형제들 기술 블로그에 나와있던 멀티모듈 설계 이야기는 의존성 문제를 해결하는 데 많은 도움이 되었습니다. 여러분들도 꼭 한 번 읽어보시면 좋을 것 같습니다.
참고문헌
댓글
이 글 공유하기
다른 글
-
Rocky Linux 9.x 미러서버 변경하기
Rocky Linux 9.x 미러서버 변경하기
2024.10.26 -
Firebase crashlytics으로 앱 안정성 확보하기
Firebase crashlytics으로 앱 안정성 확보하기
2024.06.26 -
직접 클라우드 서버 제작 및 서버 인프라 설계
직접 클라우드 서버 제작 및 서버 인프라 설계
2023.12.18 -
WebRTC란?
WebRTC란?
2023.04.10