본문 바로가기
아키텍처/클린 아키텍처

클린 아키텍처 - 설계원칙 - OCP

by SSaMKJ 2023. 2. 11.

설계원칙

SOLID

  • SRP: 단일 책임 원칙 Single Responsible Principle
  • OCP: 개방-폐쇄 원칙 Open-Closed Principle
  • LSP: 리스코프 치환 법칙 Liskov Substitution Principle
  • ISP: 인터페이스 분리 원칙 Interface Segregation Principle
  • DIP: 의존성 역전 원칙 Dependency Inversion Principle

 

OCP

  • 개방-폐쇄 원칙 Open-Closed Principle

소프트웨어 개체(artifact)는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.

  • 다시 말하자면 소프트웨어 개체의 행위는 확장할 수 있어야 하지만, 이때 개체를 변경해서는 안 된다.
  • 만약 요구사항을 살짝 확장하는 데 소프트웨어를 엄청나게 수정해야 한다면, 그 소프트웨어 시스템을 설계한 아키텍트는 엄청난 실패에 맞닥뜨린 것이다.
  • OCP는 클래스와 모듈을 설계할 때 도움되는 원칙이기도 하지만 아키텍처 컴포넌트 수준에서 OCP를 고려할 때 훨씬 중요한 의미를 가진다.
  • 사고 실험 (thoght experiment)을 해 보면 이 점이 분명해진다.

사고 실험 (thoght experiment)

  • 재무제표를 웹 페이지로 보여주는 시스템이 있다고 가정하자.
    • 웹 페이지에 표시되는 데이터는 스크롤할 수 있으며, 음수는 빨간색으로 출력한다.
  • 이제 이해관계자가 동일한 정보를 보고서 형태로 변환해서 흑백 프린터로 출력해 달라고 요청했다고 해보자.
    • 이 보고서에는 페이지 번호가 제대로 매겨져 있어야 하고, 페이지마다 적절한 머리글과 바닥글이 있어야 하며, 표의 각 열에는 레이블이 있어야 한다고 해보자. 또한 음수는 괄호로 감싸야한다.
  • 당연히 새로운 코드를 작성해야 한다. 그렇다면 원래 코드는 얼마나 많이 수정해야 할까?
  • 소프트웨어 아키텍처가 훌륭하다면 변경되는 코드의 양이 가능한 한 최소화될 것이다. 이상적인 변경량은 0이다.
  • 단일 책임 원칙(SRP)을 적용하면 데이터 흐름을 그림 2-1과 같은 형태로 만들 수 있다. 재무 데이터를 검사한 후 보고서용 데이터를 생성한 다음, 필요에 따라 두 가지 보고서 생성 절차 중 하나를 거쳐 적절히 포매팅한다.

\[그림 2-1. SRP 적용하기. 데이터 흐름\]
  • 보고서 생성이 두 개의 책임으로 분리된다. Financial Analyzer가 Financial Report Data를 만드는 책임이고, 나머지 하나는 이 데이터를 웹으로 보여주거나 종이에 프린터하기에 적합한 형태로 표현하는 책임이다.
  • 이처럼 책임을 분리했다면, 두 책임 중 하나에서 변경이 발생하더라도 다른 하나는 변경되지 않도록 소스 코드 의존성도 확실히 조직화해야 한다. 또한, 새로 조직화한 구조에서는 행위가 확장될 때 변경이 발생하지 않음을 보장해야 한다.

[그림 2-2. 처리 과정을 클래스 단위로 분할하고, 클래스는 컴포넌트 단위로 분리한다.]

  • 그림 2-2 설명
    • <I> : Data Structure
    • 열린 화살표 : using
    • 닫힌 화살표 : 구현(implement) 또는 상속
  • 주목할 점은 화살표의 방향이다. 화살표는 의존성을 나타낸다. Web View는 Screen Presenter를 알지만 Screen Presenter는 Web View를 모른다.
  • 클래스간 화살표의 방향은 오직 한방향으로만 간다.

[그림 2-3. 컴포넌트 관계는 단방향으로만 이루어진다.]

  • 컴포넌트 A의 변경으로부터 컴포넌트 B를 보호하기 위해서는 컴포넌트 A가 컴포넌트 B를 의존해야 한다. 즉, Web View의 변경으로부터 Screen Presenter는 보호된다.
  • Interactor는 OCP를 가장 잘 준수할 수 있는 곳에 위치한다. Database, Controller, Presenter, View에서 발생한 어떤 변경도 _Interactor_에 영향을 주지 않는다.
  • 왜 _Interactor_가 특별한 위치를 차지해야만 하는가? 그 이유는 _Interactor_가 업무 규칙을 포함하기 때문이다.
  • 보호의 계층구조가 수준(level)이라는 개념을 바탕으로 어떻게 생성되는지 주목하자.
    • 저수준 ---> 고수준
    • View ---> Presenter ---> Controller ---> Interactor
  • 가장 고수준인 Interactor를 다른 모든 컴포넌트의 변경에서 보호를 받지만, View는 거의 보호 받지 못 한다.
  • 이것이 바로 아키텍처 수준에서 OCP가 동작하는 방식이다. 아키텍트는 기능이 어떻게(how), 왜(why), 언제(when) 발생하는지에 따라서 기능을 분리하고, 분리한 기능을 컴포넌트의 계층구조로 조직화한다. 컴포넌트 계층구조를 이와 같이 조직화하면 저수준 컴포넌트에서 발생한 변경으로부터 고수준 컴포넌트를 보호할 수 있다.

결론

  • OCP는 시스템의 아키텍처를 떠받치는 원동력 중 하나다.
  • OCP의 목표는 시스템을 확장하기 쉬운 동시에 변경으로 인해 시스템이 너무 많은 영향을 받지 않도록 하는 데 있다.
    • 시스템을 컴포넌트 단위로 분리
    • 저수준 컴포넌트에서 발생한 변경으로부터 고수준 컴포넌트를 보호할 수 있는 형태의 의존성 계측구조를 만듬.

 

 

 

클린 아키첵처 전체 보기 

클린 아키텍처란? https://blog.kjslab.com/199
클린 아키텍처 - 설계원칙 - SRP https://blog.kjslab.com/200 
클린 아키텍처 - 설계원칙 - OCP https://blog.kjslab.com/201 
클린 아키텍처 - 설계원칙 - LSP https://blog.kjslab.com/202 
클린 아키텍처 - 설계원칙 - ISP https://blog.kjslab.com/203  
클린 아키텍처 - 설계원칙 - DIP & SOLID 요약 https://blog.kjslab.com/204 
클린 아키텍처 - 컴포넌트 https://blog.kjslab.com/205 
클린 아키텍처 - 컴포넌트 결합 - ADP https://blog.kjslab.com/206   
클린 아키텍처 - 컴포넌트 결합 - SDP https://blog.kjslab.com/207
클린 아키텍처 - 컴포넌트 결합 - SAP & 결론 https://blog.kjslab.com/208 

댓글