Clean Architecture는 소프트웨어의 유지보수성을 향상 시키는데 도움을 주는 원칙들을 제안하고 있다. Clean Architecture의 목적은 적은 인력으로 효율적인 Software를 개발하는 것이다. 특히, Software의 변경을 적은 비용으로 달성하기 위해 어떻게 설계해야 하는지 설명하고 있다
Clean Architecture 의 목적 : 변경하기 쉽게
Software 개발자들이 가장 고통스러워 하는 부분은 바로 끊임없는 고객의 요구 사항 변경일 것이다. 초기 개발 단계 에서 요구 사항을 수집하고 분석하는 절차를 진행하더라도, 이해당사자간 커뮤니케이선 에러나, 시장 환경의 변경, 시스템의 변경으로 요구 사항은 언제든지 변경될 수 있다.
개발 초기에는 분명히 필요한 기능이였지만, 시장 환경의 갑작스러운 변경으로 불필요해질 수 있다. 가령, 코로나 이전엔 재택근무가 일반적이지 않아, 화상회의가 거의 없었다. 그러나 코로나 시대 이후, 재택근무 증가로, 화상회의 기능이 갑작스럽게 필요해졌다.
또한 Software가 동작하는 시스템의 변경은 주기적으로 발생한다. 임베디드 소프트웨어의 경우, Hardware가 발전함에 따라 Software도 이에 맞춰 변경해주어야 한다.
이렇듯 요구사항과 제약사항이 변경되더라도, 효율적으로 Software를 유지보수 하기 위해서 Clean Architecture 원칙을 적용해야 한다.
개발 경험이 많은 숙련된 개발자들은 그들의 Software에서 재사용이 빈번하기 발생하는 재사용모듈과 변경이 많이 발생하는 가변모듈을 알고 있을 것이다. 가변모듈도 변경이 발생하는 원인이 다양할텐데, 이러한 가변 요소까지 식별하고 있을 것이다. 우리는 알게 모르게 이러한 Clean Architecture 원칙을 적용하고 있다.
요구사항 변경에 빠르게 대응할 수 있는 Architecture가 되어야 한다. 이것이 적은 비용으로 지속가능한 Software를 만드는 길이다.
Clean Architecture 의 목적은 중요한 것을 재사용할 수 있도록 구조를 잡는것이다.
SOLID 원칙
SOLID 원칙은 Class를 설계할 때, 유지 보수성을 높이기 위해서 고려해야 하는 원칙들이다. 변경에 유연한 Architecture 또는 가독성이 좋은 Architecture 가 되기 위해서 추구되어야 하는 원칙이다.
SRP (Single Responsiblility Principle)
단일 책임 원칙으로써, 하나의 Class는 하나의 책임 만을 갖어야 한다는 의미이다. 해당 Class의 변경의 원인이 단 한 가지 여야 한다는 의미이다. 하나의 Class가 여러 책임을 갖게 된다면, 각 기능이 변경될 때 마다, 해당 Class를 변경해야 한다. 여러 책임을 갖는 Super Class가 있다면, SRP원칙을 적용하여 책임 별 분리를 진행해야 한다. 이는 모듈의 응집도와 연관성을 갖는다. 클래스의 응집도를 높이고, 다른 클래스와 커플링을 줄이는 것이 이 원칙의 목적이다. 모듈화를 위한 가장 기초적인 원칙이다.
OCP (Open Closed Principle)
개방 폐쇄 원칙으로써, 확장엔 Open, 변경엔 Close 하라는 원칙이다. 핵심 Logic 으로 변하지 않아야 하는 것은 Close 하여 노출하지 않도록 하고, 쉽게 기능을 확장할 수 있는 구조를 갖어야 한다는 것이다. 이는 유지 보수성을 위한 가장 핵심이 되는 원칙이다. Code의 재사용성을 위해, 핵심 Logic은 보호하고, 기능 추가 및 확장은 쉽게 하여, 요구 사항의 변경에도 기존의 Code를 재사용할 수 있으며, 새로운 기능의 추가가 기존 코드의 수정 없이 가능하게 된다.
유지보수성을 위한 Software가 달성해야 할 궁극적인 목표이다. 여러 Design Pattern 들도 이 원칙에 따라 기능 확장하기 위한 구조를 제시한다.
LSP (Liskov Subsititution Principle)
리스코프 치환 원칙으로 올바른 상속 관계에 대하여 가이드 한다. 자식은 부모를 대체할 수 있어야 한다는 원칙으로 부모의 형질을 상속 받은 자식이 부모를 대체해야 한다는 것이다. 그래야 다형성을 활용한 Code의 확장 가능한 구조가 가능해 진다. 상속 구조를 하기와 같이 잡게 되면, 정사각형은 사각형을 대체하지 못하기 때문에 문제가 발생한다.
Rectangle Type으로 Square Instance를 받은 후, H와 W를 setting하고자 할 때, 문제가 발생한다. 객체 간 상속 관계를 잡을 때, 행위를 기반으로 공통적인 것을 찾아 설계 해야 한다. 그래야 해당 행위가 추후 인터페이스 클래스로 도출 되어 사용될 수 있다.
외적으로 보여지는 행위에 기반하여 상속 관계를 잡아야 한다.
ISP (Interface Segregation Principle)
하나의 클래스가 여러 Interface를 갖게 되면, 변경에 취약해 진다. Interface를 사용하는 Client에 맞춰 특화된 세분화된 Interface를 제공해야 한다. Operation 단위로 Interface를 분리하여, Client의 의존성을 분리 시켜야 한다. User 1,2,3이 각각 서로 다른 Interface를 의존하고 있다.
DIP (Dependency Inversion Principle)
의존성 역전의 법칙으로, 의존성이 중요한 모듈에서 자주 변경 모듈로 향한다면, 중요한 모듈이 변경점에 의해 쉽게 영향을 받게 된다. 때문에 이러한 의존 관계를 역전 시켜야 한다. 의존관계를 역전 시키기 위해, Interface를 두고, 이에 의존하게 하여 Interface라는 공통의 약속인 안정적인 Class의 의존하도록 한다.
재사용률이 높은 핵심 Class는 자주 변하는 불 안정적인 Class에 의존하지 않아야 하며, 필요시 Interface를 설계하여 이에 의존하도록 하고, 자주 변하는 Class는 이를 상속 받아 구현하도록 해야 한다.