본문 바로가기

Design/Architecture

[Clean Architecture]SOLID 원칙 : 1.SRP 단일 책임 원칙

SRP 란?

 

SRP란, 하나의 모듈은오직 하나의 액터(actor)에 대해서만 책임져야 한다는 원칙이다.

 

 

SRP는 SOLID 원칙 중에서 의미 전달이 어려운 원칙이다.

단일 책임의 원칙이라고 하여 하나의 모듈은 단하나의 일만 해야한다는 의미가 아님에 주의하자.

(이는 함수는 반드시 하나의 일만 해야한다는 원칙이다. 이는 커다란 함수를 작은 함수들로 리펙터링하는 더 저수준에서 사용. SRP와 혼동하지 말자!)

 

SRP 원칙에 대한 설명에서 Actor는 이해관계자들이라고 생각하면 된다. 예를 들면 평가 모듈은 오직 평가 담당자(actor)에 대해서만 책임져야한다.(한 액터에 의한 수정이 다른 액터를 위한 모듈에 영향이 주어서안됨!)

 

모듈이란 무슨 뜻인가?

 모듈이란 내가 이해하기 쉬운 언어로 함수와 데이터 구조로 구성된 응집된(cohesive) 집합이다.

응집이라는 단어에 주의해보도록 하자. SRP의 원칙을 지키기 위해서는 오직 한 액터를 위한 기능이 응집된 집합을 형성해야한다는 것이다! 

 

 

SRP 원칙을 위반하는 징후

아래 두가지 징후를 살펴보면서 지금 내가 담당하고 있는 시스템의 이야기는 아닐까... 생각해보도록 하자.

 

1. 우발적 중복

 책에서는 급여 어플리케이션의 Employee 클래스로 예를 들고 있다.

간단하게 말하자면, 한가지 클래스(Employee)가 서로 다른 세가지 메서드를 담고있으며, 서로 다른 세 가지 액터를 책임지고 있는 상황이다. 생각해보면, 이 Employee 클래스의 데이터와 관련이 있는 메서드를 한 클래스에 둔다는게 특이한 케이스 인 것은 아닌듯하다..

 

한가지 예를 들어보자. 액터가 다른 A,B 메서드가 공유하고 있는 알고리즘 X가 있다고 했을 때, A의 요구사항에 의한 개발을 할때, 알고리즘 X에 대한 수정이 필요한 케이스가 생긴다고 가정해보자. 이때 X가 A뿐만 아니라 B에서도 사용하는 알고리즘이라는 것을 알아차리지 못하고 수정이 일어난다면, A 액터의 요구에 의해서 수정된 기능이 의도치 않게 B에도 영향이 미치게 된다. (생각만해도 끔찍...)

 

이러한 문제는 서로 다른 액터가 의존하는 코드를 너무 가까이 배치한 것이 원인이다. 이때 SRP는 서로 다른 액터가 의존하는 코드를 서로 분리하라고 말한다.

 

2. 병합

 어떤 클래스가 다양고 많은 매서드를 포함하면 병합문제가 발생될 가능성이 큰 것은 당연하다. 만약에 다양한 액터가 관여되어있는 클래스라면 병합 문제가 생길 가능성은 더 높아질 것이다. (병합은 간단히 Conflict라고 이해하면 될 듯함.)

 

사실 당연한 문제이므로 예시는 따로 들지 않겠슴.(건방지네)

 

정리하자면, 많은 사람이 서로 다른 목적으로 동일한 소스파일을 변경하는 경우에 해당한다. 이런 문제는 서로 다른 액터를 뒷받침하는 코드는 서로 분리하는 것이다.

 

해결책

    1. 데이터와 메서드를 분리하자.
      데이터와 다양한 액터를 위한 메서드를 데이터 클래스 + N가지 액터를 위한 메서드를 N개의 클래스로 분리한다. 이때 각 메서드는 데이터 클래스를 서로 공유하고, 각 클래스는 자신의 메서드에 꼭 필요한 소스만 포함해야하며, 서로의 존재를 몰라야한다!('우연한 중복 방지')

    2. Facade패턴을 사용하자.
      1번의 해결책은 개발자가 N가지로 나누어져있던 클래스를 각각 인스턴스화 하고 추적해야한다는 단점이 있다.(얘네들이 어디있는지 찾고 하는게 귀찮아지는..) 따라서 이를 위해 Facade 패턴을 사용하면 해결이 될 수 있다.

      참고!!)
      Facade는 "건물의 정면"을 의미하는 단어로 어떤 소프트웨어의 다른 커다란 코드 부분에 대하여 간략화된 인터페이스를 제공해주는 디자인 패턴을 의미함. 
      [Clean Architecture] Facade를 적용한 클래스
    3. 데이터와 가까이 두어야하는 중요 메서드는 그대로 두고, 나머지 메서드는 분리하자.
      만약 중요한 업무 규칙을 데이터와 가깝게 배치하고 싶다면, 가장 중요한 메서드는 기존 클래스에 그대로 유지하되, 덜 중요한 M개의 메서드들에 대해서는 별도 M개의 클래스로 빼고, 기존 클래스를 이 M개 클래스의 Facade로 사용. (즉, 1번과 2번을 혼합한 케이스!)
      [Clean Architecture] 1번과 2번을 혼합한 형태의 해결책

 

  1.  

 

결론

단일 책임 원칙은 메서드와 클래스 수준의 원칙이다. 이보다 더 상위 수준에서는 다른 형태로 다시 등장할 것임.

(컴포넌트수준 : 공통 폐쇄 원칙 / 아키텍쳐 수준 : 아키텍쳐 경계의 생성을 책임지는 변경의 축 => 아직 무슨 말인지 전혀 모르겠으나... 차차 알아가 보도록 하자.)