![](https://blog.kakaocdn.net/dn/HIFt7/btsyOFOKmav/EpJdQ7kwkIcjzVkOiA65K0/img.png)
* 이 글은 Agile Software Development, Principles, Patterns, and Practices - Robert Martin 책 내용을 번역 및 요약하여 작성하였습니다.
SRP: The Single-Responsibility Principle
왜 책임을 별도의 클래스로 분리하는 것이 중요한가요? 각 책임은 변경의 축이기 때문입니다.
요구 사항이 변경되면 그 변경은 클래스 간의 책임 변경을 통해 나타날 것입니다. 하나의 클래스가 두 개 이상의 책임을 가정하면 해당 클래스가 변경해야 하는 이유가 두 개 이상 발생할 것입니다.
하나의 클래스가 두 개 이상의 책임을 갖는 경우, 이러한 책임들은 서로 결합됩니다. 이때 한 책임에 대한 변경 사항은 클래스가 다른 책임을 충족하는 능력을 저해하거나 방해할 수 있습니다. 이러한 종류의 결합은 변경 시 예상치 못한 방식으로 깨지는 민감한 디자인을 유발합니다.
What Is a Responsibility?
SRP(Single Responsibility Principle)의 맥락에서 책임(responsibility)을 "변경의 이유(reason for change)"로 정의합니다.
한 클래스에 대해 두 개 이상의 클래스를 변경하려는 동기가 있다면 그 클래스는 두 개 이상의 책임을 갖고 있는 것입니다.
예를 들어 아래 코드 예제(Listing 8-1)에서의 Modem 인터페이스를 보면, 이 인터페이스는 크게 문제가 없어 보입니다. 이 인터페이스가 선언하는 네 가지 함수는 모뎀이 수행해야 하는 기능들의 함수들입니다.
![](https://blog.kakaocdn.net/dn/PNxDY/btsyHzhJ4ot/NabzH6hOmpmq7NWU0GgaH0/img.png)
그러나 여기에서 두 가지 책임이 나타납니다.
첫 번째 책임은 연결 관리이고, 두 번째는 데이터 통신입니다.
dial 및 hangup 함수는 모뎀의 연결을 관리하고, send 및 recv 함수는 데이터를 통신합니다.
응용 프로그램이 연결 함수의 시그니처에 영향을 미치는 방식으로 변경된다면, 설계는 강성(Rigidity)을 띄고 있습니다.
send와 recv를 호출하는 클래스들은 예상하는 것보다 빈번하게 다시 컴파일하고 재배포해야 할 것입니다.
두 가지 책임은 아래 Figure 8-3에 나와 있는 것처럼 분리되어야 합니다. 이렇게 하면 클라이언트 응용 프로그램이 두 가지 책임을 결합하지 않도록 유지됩니다.
![](https://blog.kakaocdn.net/dn/rAyBZ/btsyMpEItZD/5jparzk8cjtsNZDnSxjtvK/img.png)
그러나 반대로 응용 프로그램이 두 가지 책임을 서로 다른 시점에 변경시키지 않는 방식, 즉 동시에 변경시키는 방식으로 구현을 한다면 이들을 분리할 필요가 없습니다. 오히려 이들을 분리하는 것은 불필요한 복잡성을 만들 수 있습니다.
앞에서 말했듯이 책임은 변경 축이며 이는 변경 사항이 실제로 발생할 때만 변경 축입니다. 즉, 어떠한 증상이 없는 경우에는 SRP 또는 다른 원칙을 적용하는 것이 현명하지 않습니다.
Separating Coupled Responsibilities
![](https://blog.kakaocdn.net/dn/bOffb1/btsyH0zsjcD/NCHkEw644d49kIUZKVHFsk/img.png)
ModemImplementation 클래스에는 두 가지 책임을 모두 결합시켰습니다. 이것은 바람직하지 않지만 필요할 수 있습니다.
하드웨어나 운영 체제의 세부 사항과 관련된 이유로 결합하려고 하지 않으려는 경우가 종종 있습니다.
그러나 인터페이스를 분리함으로써 응용 프로그램의 나머지 부분에서는 이 개념을 분리했습니다.
ModemImplementation 클래스의 주목할 점은 모든 종속성이 외부로 향한다는 것입니다.
어떤 클래스도 이 ModemImplementation 클래스를 의존할 필요가 없습니다. 메인 함수를 제외하고는 이 클래스가 존재하는 사실을 알 필요가 없습니다. 따라서 ModemImplementation이 외부로 노출되어 응용 프로그램의 나머지 부분을 간섭할 일이 없습니다.
Persistence
아래는 SRP(Single Responsibility Principle)의 일반적인 위반 사례를 보여줍니다.
Employee 클래스에는 업무 규칙(CalculatePay)과 지속성 제어(Store)가 포함되어 있습니다. 이 두 가지 책임은 혼합되어서는 안 됩니다. 업무 규칙은 자주 변경되며, 지속성(Persistence)은 그렇게 자주 변경되지 않을 수 있지만 완전히 다른 이유로 변경될 수 있습니다. 업무 규칙을 지속성 하위 시스템(Persistence Subsystem)에 바인딩하면 문제가 발생할 가능성이 있습니다.
![](https://blog.kakaocdn.net/dn/dkWHSQ/btsyHXQgHAD/GMAP5rKM21MI1FUu5RFLwk/img.png)
Conclusion
SRP(단일 책임 원칙)은 가장 간단한 원칙 중 하나이지만 올바르게 적용하기 가장 어려운 것 중 하나입니다. 책임을 결합하는 것은 우리가 자연스럽게 하는 일입니다. 그리고 이러한 책임을 찾아내고 서로 분리하는 것이 소프트웨어 디자인의 핵심입니다. 실제로 다룰 다른 원칙들은 어떤 방식으로든 이 문제로 돌아옵니다.
'ComputerScience > DesignPattern' 카테고리의 다른 글
[SOLID] DIP: The Dependency-Inversion Principle (1) | 2023.10.19 |
---|---|
[SOLID] ISP: The Interface-Segregation Principle (0) | 2023.10.19 |
[SOLID] LSP: The Liskov Substitution Principle (1) | 2023.10.19 |
[SOLID] OCP: The Open–Closed Principle (0) | 2023.10.18 |
[DesignPattern] Agile Development (0) | 2023.10.11 |