본문 바로가기
OOP

[OOP] 객체지향의 원칙 SOLID - 단일 책임 원칙 (SRP)

by mizuiro 2024. 6. 21.
객체지향에서 가장 중요한 키워드는 바로 '객체' 이다

객체는 역할을 가지고 책임이 있으며, 다른 객체와 협력하는 존재이다

또한 객체는 협력적이며 자율적이어야 한다

 

협력적 : 객체가 협력적이지 않고 혼자 스스로 처리하려고 하면 내부 복잡도에 의해 소멸한다

자율적 : 스스로 책임에 대해 수행할 수 있어야 한다 , 다른 객체의 영향을 받으면 안된다 (캡슐화)

 

이러한 객체의 개념을 생각하면서 SOLID를 생각해야 조금 이해가 쉬워진다

또한 객체지향에서 말하는 용어와 자바에서 말하는 용어가 겹쳐질 때가 있는데 단어만 같은 것이지 의미는 객체지향이 더 포괄적이므로 자바의 용어와 헷갈리지 말자

 

 

단일 책임 원칙 (Single Responsibility Principle, SRP)


클래스는 하나의 책임만 가져야 한다.
클래스가 변경되어야 하는 이유는 하나뿐이어야 한다.

 

일단 책임이란 하나의 기능(자바에서의 메소드) 가 아닌 클래스가 생성하는 객체의 책임을 말하는 것이다

전체 서비스에서 다른 객체와 협력 할 때 한 객체가 맡아서 수행하는 업무를 말한다

이렇게 객체가 하나의 책임을 가져야 전체 서비스에서 객체가 하나의 역할을 가질 수 있다

 

만약 객체가 여러개의 책임을 가진다면 내부 복잡도가 늘어나게 되고 코드가 변경이 자주 발생할 수 있기에 코드 유지보수가 어려워 진다 또한 응집도나 낮아지며, 결합도가 높아지게 된다

 

단일 책임 원칙 장점

1. 역할에 대한 모호성이 없어지고, 응집도가 높아지며 결합도가 낮추어진다

2. 맡은 책임을 자율적으로 수행하기 위해 캡슐화를 사용하여 내부 상태와 행위를 숨기고 공용 인터페이스 (public method) 만을 제공할 수 있다

 

단일 책임 원칙 단점

책임을 너무 작게 쪼개서 객체에게 할당이 되면 시스템에 많은 객체가 생성이 되고, 응집도가 과하게 높아져서 관리하기게 힘들어지므로 객체에게 주는 책임의 크기를 적절하게 쪼개야 한다

 

 

다른 원칙과의 관계

  • OCP: SRP를 지키면 클래스가 하나의 책임만 가지므로, 클래스 확장이 용이해져 OCP를 만족하게 됩니다.
  • LSP: SRP를 준수하면 클래스가 단일 책임을 가지므로, 서브 클래스도 일관되게 동작하여 LSP를 더 쉽게 만족시킬 수 있습니다.
  • ISP: SRP를 지키면 인터페이스도 단일 책임을 가지게 되어, ISP를 준수하는 인터페이스 설계가 가능합니다.
  • DIP: SRP를 지키면 각 클래스가 단일 책임을 가지므로, 의존성 주입 시 명확한 역할을 가진 객체들 간의 관계를 설정할 수 있습니다.

 

예시

커피 주문 시스템 시나리오

고객 객체와 판매자 객체가 존재
고객 객체 (커피 주문을 하는 책임), 판매자 객체 (커피 주문 받는 책임, 커피 제조하는 책임)

행동과정
고객객체가 주문을 요청하면 판매자 객체가 주문을 받고, 커피를 제조 한다

문제점
판매자는 2개의 역할(주문 받기, 커피 제조하기)을 가지고 있기에 고객 객체와 결합도가 높다
또한 커피 제조하는데 추가적인 기능이 생긴다면 너무 많은 행위(method)를 객체가 가지게 되면서 코드가 복잡해 진다

SRP 적용 
판매자 객체를 역할에 따라 캐셔(주문 받는 역할), 바리스타(커피 제조 역할) 로 나눌 수 있다
캐셔 객체는 고객 객체와 바리스타 객체와 협력하여 주문을 관리하고 전달하는 책임을 가지고,
바리스타 객체는 캐셔 객체와만 협력하여 캐셔 객체가 커피 제조 요청 행위를 하면 커피 종류를 가지고 커피를 제조해 준다
이렇게 3개의 객체가 되면서 응집도가 높아졌고 객체 간의 결합도가 낮아진다
또한 하나의 객체가 한 역할을 담당하게 되면서 스스로 책임에 대해 자율적으로 수행하고, 캡슐화가 된다