Post
KO

SRP 단일책임원칙

​

프로그래머가 이 원칙의 이름을 듣는다면 모든 모듈이 단 하나의 일만 해야 한다는 의미로 받아들이기 쉽다. 하지만 하나의 일만 해야 한다는 원칙은 사실 따로 있다. 그것은 바로 함수는 반드시 하나의, 단 하나의 일만 해야 한다는 원칙이다.

​

역사적으로 기술되어왔던 SRP는 아래와 같은 정의를 갖고 있다.

​

단일 모듈은 변경의 이유가 하나, 오직 하나뿐이어야 한다.

​

이 원칙을 다음 말로 바꿀 수도 있다.

​

하나의 모듈은 하나의, 오직 하나의 사용자 또는 이해관계자에 대해서만 책임져야 한다.

​

여기서 ‘사용자’와 ‘이해관계자’ 라는 단어를 여기에 쓰는 것은 사실 올바르지 않다. 이러한 지칭을 액터(Actor)라고 변경해보자.

​

하나의 모듈은 하나의, 오직 하나의 액터에 대해서만 책임져야 한다.

​

그럼 ‘모듈’의 뜻은 무엇인가?

가장 단순한 정의는 바로 소스 파일이다.

​

‘응집된(cohesive)’이라는 단어가 SRP를 암시한다. 단일 액터를 책임지는 코드를 함께 묶어주는 힘이 바로 (cohension) 이다.

​

​

SRP 를 개선 하는 방법에 대해 확인해보자.

​

징후 1: 우발적 중복

​

![](/assets/images/posts/222621602109/c73fcc505897.png?type=w580)

위 그림에서 Employee 클래스는 SRP를 위반하는데, 이들 세 가지 메서드가 서로 다른 매우 다른 세 명의 액터를 책임지기 때문이다.

​

calculatePay() 메서드는 회계팀에서 기능을 정의하며, CFO 보고를 위해 사용한다.

reportHours() 메서드는 인사팀에서 기능을 정의하고 사용하며, COO 보고를 위해 사용한다.

save() 메서드는 데이터베이스 관리자 DBA가 기능을 정의하고, CTO 보고를 위해 사용한다.

​

이 클래스의 문제는 서로 다른 액터가 의존하는 코드를 너무 가까이 배치했기 때문에 발생한다.

​

징후 2: 병합

​

많은 사람이 서로 다른 목적으로 동일한 소스 파일을 변경하는 경우에 해당한다. 다시 한번 말하지만, 이 문제를 벗어나는 방법은 서로 다른 액터를 뒷받침하는 코드를 서로 분리하는 것이다.

​

해결책

​

이 문제의 해결책은 다양한데, 그 모두가 메서드를 각기 다른 클래스로 이동시키는 방식이다.

![](/assets/images/posts/222621602109/da0e4179d602.png?type=w580)

위와 같은 해결책은 개발자가 세 가지 클래스를 인스턴스화하고 추적해야 한다는게 단점이다. 이런 난관에서 빠져나올 때 흔히 쓰는 기법으로 퍼사드(Facade) 패턴이 있다.

![](/assets/images/posts/222621602109/e5182ab2df39.png?type=w580)

EmployeeFacade에 코드는 거의 없다. 이 클래스는 세 클래스의 객체를 생성하고, 요청된 메서드를 가지는 객체로 위임하는 일을 책임진다.

​

![](/assets/images/posts/222621602109/5264ac2a9074.png?type=w580)

​

모든 클래스는 반드시 단 하나의 메서드를 가져야 한다는 주장에 근거하여 앞의 해결책에 반대할 수도 있다. 하지만 이 주장은 현실과는 전혀 다르다. 각 클래스에서 지불, 보고서 생성, 데이터 저장 기능을 구현하는 데 필요한 메서드의 개수는 실제로 훨씬 더 많을 것이다. 이들 클래스는 모두 다수의 private 메서드를 포함할 것이다.

​

이처럼 여러 메서드가 하나의 가족을 이루고, 메서드의 가족을 포함하는 각 클래스는 하나의 유효범위가 된다.

​

결론

​

단일 책임 원칙은 메서드와 클래스 수준의 원칙이다. 컴포넌트 수준에서는 공통 폐쇄 원칙 (Common Closure Principle)이 된다.

아키텍처 수준에서는 아키텍처 경계(architectural Boundary)의 생성을 책임지는 변경의 축 (Axis of Change)이 된다.

​

​

​

This article is licensed under CC BY 4.0 by the author.